Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

JPGraph Subform and Legend Issues

Status
Not open for further replies.

PCHomepage

Programmer
Feb 24, 2009
609
US
I have a JPGraph line plot inside a function and have showed below only the portions in question. The plot is working in pulling up multiple columns of data but I can't seem to get the legend to show properly, especially as there is also a sub form to selest what to graph. By default, all four columns are graphed, then there are checkboxes to pick more specifics. As it is, it shows all properly or I can pick only one at a time without a JPGraph crash (any two or more crashes it) but the main problem is in the legend, which has to get a title from a database table, shows all the titles for each column and it's obvious why but I'm not sure what to do about it! It's also showing all the same title so if two are being graphed, and there are four columns of data, I see the same file name eight times and it does not show the mark type.

I would also like it to show the column name at the peak of each graph.

Can anyone help?

Code:
if ($result = $mysqli->query("$Query")) :
	while ($row = $result->fetch_array()) :
		$datax[$row[0]][] = $row[1];
		$datay1[$row[0]][] = $row[2];
		$datay2[$row[0]][] = $row[3];
		$datay3[$row[0]][] = $row[4];
		$datay4[$row[0]][] = $row[5];
	endwhile;
	$result->close();
else:
	echo "<div class=\"Message\">\n";
	printf("MySQLi Error: %s\n", $mysqli->error);
	echo "</div>\n\n";
endif;

foreach($datay1 as $key=>$_datay): // for Legend
	$queryFN = "SELECT FileName FROM dcs_uploads ";
	$queryFN .= "WHERE ID = ".$key." ";
	$queryFN .= "ORDER by FileName";
	if ($result = $mysqli->query($queryFN)):
		$row = $result->fetch_row();
		$FileName = $row[0];
	endif;
endforeach;

if (!$SubData || $SubData == 'Red'):
	foreach($datay1 as $key=>$_datay): // for Red
		$lp[$key] = new LinePlot($_datay,$datax[$key]);
		$graph->Add($lp[$key]);
		$lp[$key]->mark->SetType(MARK_DIAMOND, 'red', 0.3);				
		$lp[$key] = new LinePlot($_datay,$datax[$key]);
		$graph->Add($lp[$key]);
		$lp[$key]->SetLegend(basename($FileName, ".csv"));
	endforeach;
endif;

if (!$SubData || $SubData == 'Gr'):
	foreach($datay2 as $key=>$_datay): // for Gr
		$lp[$key] = new LinePlot($_datay,$datax[$key]);
		$graph->Add($lp[$key]);
		$lp[$key]->mark->SetType(MARK_UTRIANGLE, 'green', 0.3);	
		$lp[$key] = new LinePlot($_datay,$datax[$key]);
		$graph->Add($lp[$key]);
		$lp[$key]->SetLegend(basename($FileName, ".csv"));
	endforeach;
endif;

if (!$SubData || $SubData == 'Gb'):
	foreach($datay3 as $key=>$_datay): // for Gb
		$lp[$key] = new LinePlot($_datay,$datax[$key]);
		$graph->Add($lp[$key]);
		$lp[$key]->mark->SetType(MARK_DTRIANGLE, 'teal', 0.3);	
		$lp[$key] = new LinePlot($_datay,$datax[$key]);
		$graph->Add($lp[$key]);
		$lp[$key]->SetLegend(basename($FileName, ".csv"));
	endforeach;
endif;

if (!$SubData || $SubData == 'B'):
	foreach($datay4 as $key=>$_datay): // for B
		$lp[$key] = new LinePlot($_datay,$datax[$key]);
		$graph->Add($lp[$key]);
		$lp[$key]->mark->SetType(MARK_SQUARE, 'blue', 0.3);	
		$lp[$key] = new LinePlot($_datay,$datax[$key]);
		$graph->Add($lp[$key]);
		$lp[$key]->SetLegend(basename($FileName, ".csv"));
	endforeach;
endif;
 
can you provide examples of the $datax and $datay[xxxx] please?
 
The data is something like this (over three hundred rows for each individual plot). There is also a column to the right with the numeric FileID to separate them but it is not contained in the original CSV files from which this was copied and pasted so it does not show here.

Code:
wavelength [nm]	R [%]	Gr [%]	 Gb [%]	 B [%]
390	14	14	14	14
400	22.64	22.64	22.64	22.64
410	29.79	29.79	29.79	29.79
420	35.15	35.15	35.15	35.15
430	39.7	39.7	39.7	39.7
440	43.52	43.52	43.52	43.52
450	46.04	46.04	46.04	46.04
460	44.93	44.93	44.93	44.93
470	43.07	43.07	43.07	43.07
480	38.65	38.65	38.65	38.65
490	29.8	29.8	29.8	29.8
500	21.37	21.37	21.37	21.37
510	13.75	13.75	13.75	13.75
519.9	7.72	7.72	7.72	7.72
530	4.52	4.52	4.52	4.52
540	2.73	2.73	2.73	2.73
550.1	1.49	1.49	1.49	1.49
560	0.75	0.75	0.75	0.75
 
sorry not to have posted back on this. Have you resolved the issue?
 
No, not yet or completely but the crashing issues was resoved. There are still issues in differentiating items as I am required to make red show as red so each item is identical so it's impossible to tell which plot is for which set of data. Today I'll be working on an idea for generating a random color within each main RGB color that may at least handle the color portion of the issue.
 
In an attempt to make the red test plot itself as a shade of red, the code was modified as below. The problem is, of course, that all the reds are the same so I can't differentiate between them. I also added a form with checkboxes to the plot page to allow enabling/disabling the fill, marks and even the line weight but they too are the same for every plot in the given color so they do not help in differentiating one from another.

For the color issue, I tried to come up with a function for picking the color randomly from a pallet of the given color and the code works by itself but it still isn't changing anything within the plot. The idea was to call the function within the loop with the base color specified, then let the random color generator pick the different shades for each plot but they still appear to be the same!

There must be a more dynamic way of getting a multiple column plot than to have to duplicate the code for each column! All the below is just for a single Y and there are four of them so how can it be simplified while still being able to enable or disable a column at will of is having to force the color going to require the extras?

Code:
if (!$SubData || $Red):
	foreach($datay1 as $key=>$_datay): // for Red
		[COLOR=red]$red = randColor('red', 255);[/color]
		$lp[$key] = new LinePlot($_datay,$datax[$key]);
		$graph->Add($lp[$key]);
		$queryFN = "SELECT DISTINCT FileName FROM dcs_uploads ";
		$queryFN .= "WHERE ID = ".$key." ";
		$queryFN .= "ORDER by FileName";
		if ($result = $mysqli->query($queryFN)):
			$row = $result->fetch_row();
			$FileName = $row[0];
		endif;
		if ($Mark) $lp[$key]->mark->SetType(MARK_DIAMOND, 'red', 0.3);				
		$lp[$key] = new LinePlot($_datay,$datax[$key]);
		$graph->Add($lp[$key]);
		if ($Fill) $lp[$key]->SetFillColor([COLOR=red]$red[/color].'@0.7');
		if ($Weight) $lp[$key]->SetWeight(3);
		$lp[$key]->SetStyle('dashed');
		$lp[$key]->SetColor([COLOR=red]$red[/color]);	
		if ($Legend) $lp[$key]->SetLegend("Red-".basename($FileName, ".csv"));
	endforeach;
endif;


Here is the random color function. By starting the random values at 100, I was attempting to get lighter pallet colors but it seems to still putt out darker colors too.

Code:
// $val is base color, ie. 'red'; $max is the maximum range 255
 function randColor($val, $max) {
 
	 $r =  ($val == 'red') ? rand(100,$max): "";
	 $g =   ($val == 'green') ? rand(100,$max): "";
	 $b =   ($val == 'blue') ? rand(100,$max): "";

	 echo sprintf("#%02s%02s%02s", dechex($r), dechex($g), dechex($b));	
	
}

Here is what I did to get the different columns:

Code:
if ($result = $mysqli->query("$Query")):
	while ($row = $result->fetch_array()):
		$datax[$row[0]][] = $row[1];
		$datay1[$row[0]][] = $row[2];
		$datay2[$row[0]][] = $row[3];
		$datay3[$row[0]][] = $row[4];
		$datay4[$row[0]][] = $row[5];
	endwhile;
	$result->close();
else:
	echo "<div class=\"Message\">\n";
	printf("MySQLi Error: %s\n", $mysqli->error);
	echo "</div>\n\n";
endif;
 
perhaps the problem is that you are echo'ing the value from randColour rather than returning it?

Code:
function randColor($val, $max) {
 
	 $r =  ($val == 'red') ? rand(100,$max): "";
	 $g =   ($val == 'green') ? rand(100,$max): "";
	 $b =   ($val == 'blue') ? rand(100,$max): "";

	 [red][s]echo[/s] return[/red] sprintf("#%02s%02s%02s", dechex($r), dechex($g), dechex($b));	
	
}
 
also note that I think you set the axis colour through the $graph variable
Code:
$graph->ynaxis[n]->setColor('red');
where [n] is the index of the relevant axis

so you'd do something like this

Code:
$p2 = new LinePlot($datay2);
$p2->SetColor('teal');
$graph->AddY(0,$p2);
$graph->ynaxis[0]->SetColor('teal');

instead of generating random colours why not create an array of colours that you can reuse. if you take the view that you have a maximum of twenty plots on a graph, then just create an array of 20 colours and address them sequentially

Code:
$colours = array('red','indianred','teal','blue', etc);
foreach($datays as $key=>$datay):
 $p = new LinePlot($datay);
 $p->setColour($colours[$key]);
 $graph->AddY(0,$p);
 $grapg->ynaxis[$key]->SetColour($colours[$key]);
endforeach;
 
Thank you. On the function with "echo", that was an error in the posting as I hadn't copied the proper version to the clipboard before pasting and didn't notice it until after I posted. Sorry about that! It turns out that the function is actually working but in many cases the colors are simply too close together to be able to descern any difference. What I need instead of a random generator is a modification to the function to step the colors through some preset value so that they are always visually farther apart. Being able to do that should do the trick because it's very close to working now.

On the array of colors, I have another plot that does just that but the problem is that it seems to start somewhere in the middle of the array and then, when it gets to the end, everything after is yellow so it is rather useless for something like this where all the plotting for the red tests need to be in shades of red; all the green tests in shades of green, etc. I posted about this issue but it was never resolved.

Although I doubt that anyone would ever create 20 plots because 20 plots with four or five columns of data would be impossible to view, I don't want to limit it. But back to the original posting, I would like the legend to be clearer than it is. For example, right now it shows the file name over and over with either the color block or the line style next to it but it would be cleaner to show the name only once, then the colors or line styles with the column name below each name. I'm not sure if that's possible, though.

About the relevant axis, I just got to the office and found that my development server is down so I can't look or try anything until it's back up! I'm woking on that and will post again if needed.
 
I didn't quite follow what you meant but when I tried:

Code:
$graph->AddY(0,$lp[$key]);
$graph->ynaxis[$key]->SetColor($red);

I got a fatal JPGraph error:

[bold]Fatal error: Call to a member function SetColor() on a non-object [/bold]
 
The ynaxis array starts at one not zero. So address element $key+1. My bad.
 
got that wrong again. i don't use jpgraph enough ...

Code:
$graph->AddY([red]$key[/red],$lp[$key]);
$graph->ynaxis[$key]->SetColor($red);
the AddY method has two arguments as shown. the first argument is the number that you want to give the axis. this is then used in the ynaxis collection.

 
Thank you, that seems to be what I was looking for. However, I'm not totally sure if I'm feeding it all the data because I had previously broken up each plot color into a separate Y value as $datay1, $datay2 etc. from the query but I'm not sure what to give it for pulling up all the columns at once:

Code:
if ($result = $mysqli->query("$Query")):
	while ($row = $result->fetch_array()):
		$datax[$row[0]][] = $row[1];
		$datay1[$row[0]][] = $row[2];
		$datay2[$row[0]][] = $row[3];
		$datay3[$row[0]][] = $row[4];
		$datay4[$row[0]][] = $row[5];
	endwhile;
endif;

I think, though, that what I currently have will work while something like the following will not since it does not let me enable to disable a particular plot (column of data) at will so I think I'd best leave well enough alone!

Code:
foreach($datay as $key=>$_datay):
	$red = randColor('red', 'dark', 255);
	$queryFN = "SELECT DISTINCT FileName FROM dcs_uploads ";
	$queryFN .= "WHERE ID = ".$key." ";
	$queryFN .= "ORDER by FileName";
	if ($result = $mysqli->query($queryFN)):
		$row = $result->fetch_row();
		$FileName = $row[0];
	endif;
	$lp[$key] = new LinePlot($_datay,$datax[$key]);
	$lp[$key]->SetLegend($FileName));
	$graph->AddY($key,$lp[$key]);
	$graph->ynaxis[$key]->SetColor($red);
endforeach;
 
the first code block looks ok, assuming row[0] is sequential. if it is not, then you might want to use a hard coded key.
 
Row[0], which is X, is sequential but my main concern was with Y and how to get multiple columns into some format where they could be plotted without having to repeat the same bits of code over and over as I am doing now, although that migth be necessary when plotting multiple values. For each value in row[0] there are four columns of Y data as row[1], row[2], etc.
 
where are you repeating the code? it just looks like a normal loop to me. you could finesse it a bit like so, but ultimately it's still a loop

Code:
[b][COLOR=#0000FF]if[/color][/b] [COLOR=#990000]([/color][COLOR=#009900]$result[/color] [COLOR=#990000]=[/color] [COLOR=#009900]$mysqli[/color][COLOR=#990000]->[/color][b][COLOR=#000000]query[/color][/b][COLOR=#990000]([/color][COLOR=#FF0000]"$Query"[/color][COLOR=#990000])):[/color]
[tab][b][COLOR=#0000FF]while[/color][/b] [COLOR=#990000]([/color][COLOR=#009900]$row[/color] [COLOR=#990000]=[/color] [COLOR=#009900]$result[/color][COLOR=#990000]->[/color][b][COLOR=#000000]fetch_array[/color][/b][COLOR=#990000]()):[/color]
[tab][tab][tab][tab][COLOR=#009900]$x[/color] [COLOR=#990000]=[/color] [b][COLOR=#000000]array_shift[/color][/b][COLOR=#990000]([/color][COLOR=#009900]$row[/color][COLOR=#990000]);[/color]
[tab][tab][tab][tab][b][COLOR=#0000FF]list[/color][/b][COLOR=#990000]([/color][COLOR=#009900]$datax[/color][COLOR=#990000][[/color][COLOR=#009900]$x[/color][COLOR=#990000]][],[/color] [COLOR=#009900]$datay1[/color][COLOR=#990000][[/color][COLOR=#009900]$x[/color][COLOR=#990000]][],[/color]  [COLOR=#009900]$datay2[/color][COLOR=#990000][[/color][COLOR=#009900]$x[/color][COLOR=#990000]][],[/color]  [COLOR=#009900]$datay3[/color][COLOR=#990000][[/color][COLOR=#009900]$x[/color][COLOR=#990000]][],[/color] [COLOR=#009900]$datay4[/color][COLOR=#990000][[/color][COLOR=#009900]$x[/color][COLOR=#990000]][])[/color] [COLOR=#990000]=[/color] [COLOR=#009900]$row[/color][COLOR=#990000];[/color][tab][tab][tab][tab]   
[tab][b][COLOR=#0000FF]endwhile[/color][/b][COLOR=#990000];[/color]
[b][COLOR=#0000FF]endif[/color][/b][COLOR=#990000];[/color]
 
That's a whole lot cleaner than the way it was suggested to do it in another post! It works perfectly.

As for the repetition, it is there in my original post at the top in each of the $SubData conditionals where it's there four times. They're not identical but they seem so close that it makes me wonder if it's necessary but because I'm trying to apply a specific color pallet to each plot and to have each one be shown or not shown on demand, maybe that's the only way to do it.
 
I think there may be something wrong with the data assembly code, now that I look at it again.

can you print_r the data and post it back in [ignore]
Code:
[/ignore] tags/
Code:
[COLOR=#009900]$datax[/color] [COLOR=#990000]=[/color] [COLOR=#009900]$datay1[/color] [COLOR=#990000]=[/color] [COLOR=#009900]$datay2[/color] [COLOR=#990000]=[/color] [COLOR=#009900]$datay3[/color] [COLOR=#990000]=[/color] [COLOR=#009900]$datay4[/color] [COLOR=#990000]=[/color] [b][COLOR=#0000FF]array[/color][/b][COLOR=#990000]();[/color]
[b][COLOR=#0000FF]if[/color][/b] [COLOR=#990000]([/color][COLOR=#009900]$result[/color] [COLOR=#990000]=[/color] [COLOR=#009900]$mysqli[/color][COLOR=#990000]->[/color][b][COLOR=#000000]query[/color][/b][COLOR=#990000]([/color][COLOR=#FF0000]"$Query"[/color][COLOR=#990000])):[/color]
[tab][b][COLOR=#0000FF]while[/color][/b] [COLOR=#990000]([/color][COLOR=#009900]$row[/color] [COLOR=#990000]=[/color] [COLOR=#009900]$result[/color][COLOR=#990000]->[/color][b][COLOR=#000000]fetch_array[/color][/b][COLOR=#990000]()):[/color]
[tab][tab][COLOR=#009900]$datax[/color][COLOR=#990000][[/color][COLOR=#009900]$row[/color][COLOR=#990000][[/color][COLOR=#993399]0[/color][COLOR=#990000]]][][/color] [COLOR=#990000]=[/color] [COLOR=#009900]$row[/color][COLOR=#990000][[/color][COLOR=#993399]1[/color][COLOR=#990000]];[/color]
[tab][tab][COLOR=#009900]$datay1[/color][COLOR=#990000][[/color][COLOR=#009900]$row[/color][COLOR=#990000][[/color][COLOR=#993399]0[/color][COLOR=#990000]]][][/color] [COLOR=#990000]=[/color] [COLOR=#009900]$row[/color][COLOR=#990000][[/color][COLOR=#993399]2[/color][COLOR=#990000]];[/color]
[tab][tab][COLOR=#009900]$datay2[/color][COLOR=#990000][[/color][COLOR=#009900]$row[/color][COLOR=#990000][[/color][COLOR=#993399]0[/color][COLOR=#990000]]][][/color] [COLOR=#990000]=[/color] [COLOR=#009900]$row[/color][COLOR=#990000][[/color][COLOR=#993399]3[/color][COLOR=#990000]];[/color]
[tab][tab][COLOR=#009900]$datay3[/color][COLOR=#990000][[/color][COLOR=#009900]$row[/color][COLOR=#990000][[/color][COLOR=#993399]0[/color][COLOR=#990000]]][][/color] [COLOR=#990000]=[/color] [COLOR=#009900]$row[/color][COLOR=#990000][[/color][COLOR=#993399]4[/color][COLOR=#990000]];[/color]
[tab][tab][COLOR=#009900]$datay4[/color][COLOR=#990000][[/color][COLOR=#009900]$row[/color][COLOR=#990000][[/color][COLOR=#993399]0[/color][COLOR=#990000]]][][/color] [COLOR=#990000]=[/color] [COLOR=#009900]$row[/color][COLOR=#990000][[/color][COLOR=#993399]5[/color][COLOR=#990000]];[/color]
[tab][b][COLOR=#0000FF]endwhile[/color][/b][COLOR=#990000];[/color]
[b][COLOR=#0000FF]endif[/color][/b][COLOR=#990000];[/color]
[b][COLOR=#0000FF]echo[/color][/b] [COLOR=#FF0000]'<pre>'[/color] [COLOR=#990000].[/color] [b][COLOR=#000000]print_r[/color][/b][COLOR=#990000]([/color][b][COLOR=#000000]concat[/color][/b][COLOR=#990000]([/color][COLOR=#FF0000]'datax'[/color][COLOR=#990000],[/color][COLOR=#FF0000]'datay1'[/color][COLOR=#990000],[/color][COLOR=#FF0000]'datay2'[/color][COLOR=#990000],[/color][COLOR=#FF0000]'datay3'[/color][COLOR=#990000],[/color][COLOR=#FF0000]'datay4'[/color][COLOR=#990000]),[/color]true[COLOR=#990000])[/color] [COLOR=#990000].[/color][COLOR=#FF0000]'</pre>'[/color][COLOR=#990000];[/color]
 
Oddly I get an error even though concat should be a standard PHP function:

Code:
Fatal error: Call to undefined function concat()
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top