There are a couple of questions, and it might be better to deal with them one
at a time.
The last, easier one first: If your data array has any non-empty strings in
the label positions (0 index of each row), then PHPlot will by default give
them priority over tick labels, assuming that if you put them in the array
they must be important to you. So you will see the label strings, not the X
values (tick labels) along the axis. If you want to see the tick labels
instead of data labels, either (1) don't put the labels in the array - leave
them all empty, or (2) use $plot->SetXTickLabelPos('plotdown') to position the
tick labels, or (3) use $plot->SetXDataLabelPos('none') to un-position the
data labels.
Be aware that the tick labels probably won't line up under your data points,
the way the data labels do. Tick labels and tick marks (which you turned off)
are at fixed intervals along the bottom. There are PHPlot functions to control
them.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
just to be clear my entire code is as follows (first graph plots red and black
lines fine, second graph is my own effort.
i am trying to get a straight line drawn y=mx+b : will it superimpose on the
first, the way i am doing it?
<?phpdate_default_timezone_set('Europe/London');////////////////////////////////////////////////////////////////////////////#PHPlotExample: OHLC(Financial)plot,basiclines,using#externaldatafile,text-dataformat.$namefile="GFS/".date("F")."cetchange.txt";define('DATAFILE',$namefile);// External data filerequire_once'phplot.php';functionread_prices_text_data($filename){$f=fopen($filename,'r');if(!$f){fwrite(STDERR,"Failed to open data file: $filename\n");returnFALSE;}// Read and check the file header.$row=fgetcsv($f);if($row===FALSE||$row[0]!='Date'||$row[1]!='cet'||$row[2]!='predict'||$row[3]!='16d'){fwrite(STDERR,"Incorrect header in: $filename\n");returnFALSE;}// Read the rest of the file into array keyed by date for sorting.while($r=fgetcsv($f)){$d[$r[0]]=array($r[1],$r[2],$r[3]);}fclose($f);// ksort($d);// Convert to a PHPlot data array with label and 3 values per row.foreach($das$date=>$r){$data[]=array($date,$r[0],$r[1],$r[2]);}return$data;}$thism=date("F")." CET prediction";$next="HadCET for ".date("M")." so far";$day16=date("j M",mktime(0,0,0,date("m"),date("d")+16,date("Y")));$text3="1 ".date("M")." to ".$day16." CET prediction";$legend_text=array($next,$thism,$text3);$plot=newPHPlot(800,600);$plot->SetTitle($thism." (Shawbury +0.5C as proxy)");$plot->SetDataType('text-data');$plot->SetDataValues(read_prices_text_data(DATAFILE));$plot->SetPlotType('linepoints');$plot->SetDataColors(array('black','red','blue'));$plot->SetLegend($legend_text);$plot->SetLegendWorld(0,20);$plot->SetXLabelAngle(90);$plot->SetXTickPos('none');//$plot->SetPlotAreaWorld(NULL, 0, NULL, 20);$plot->SetLineStyles('solid');$plot->SetLineWidths(2);$plot->SetYDataLabelPos('plotin');$plot->SetDrawBrokenLines(True);$plot->DrawGraph();//////////////////////////////////////////////////////////////////////////require("regression.php");$data=array();for($x=1;$x<=20;$x++)$data[]=array('1,2,3,4,5,6,7,8,9,10',($m*$x)+$b);$legend_text=array($next,$thism,$text3);$plot=newPHPlot(800,600);$plot->SetTitle($thism." (Shawbury +0.5C as proxy)");$plot->SetDataType('data-data');$plot->SetDataValues(read_prices_text_data(DATAFILE));$plot->SetPlotType('linepoints');$plot->SetDataColors(array('green'));$plot->SetLegend($legend_text);$plot->SetLegendWorld(0,20);$plot->SetXLabelAngle(90);$plot->SetXTickPos('none');$plot->SetXDataLabelPos('none');$plot->SetLineStyles('solid');$plot->SetLineWidths(2);$plot->SetYDataLabelPos('plotin');$plot->SetDrawBrokenLines(True);$plot->DrawGraph();
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
No it won't work that way. The first DrawGraph() sends the image, and the rest
is probably ignored by the viewer/browser. Read the below (which I wrote
before reading your latest).
I can think of 3 ways to add a line to your plot. You can consider it to be an
additional data set, an overlay plot, or an annotation.
Using an additional data set would involve adding a column to your data array,
probably with just 2 points (1 at Xmin, 1 at Xmax). I don't think is practical
in this case, because it involves messing with every row in the data array.
With an overlay plot, you would use $plot->SetPrintImage(False), do your main
graph, $plot->DrawGraph(), then make a new data array with just one line,
$plot->DrawGraph() again, and $plot->PrintImage() to output it. The second
graph will overlay the first. (Similar to what you posted, but you must turn
off automatic image print or you get 2 concatenated PNG images which won't
work.)
The third way is to use a drawing callback function to annotate your plot.
This is the most flexible way, but can take a little more work. There is an
example in the manual, but if you want I can post a little code that is more
specific to what you want. Or if you want to try the overlay, I can show you
one of those.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Call to a member function on non-object: You have to create the object before you can use it. Move that $plot->SetPrintImage(False) line anywhere after $plot=new PHPlot(...) and before the first $plot->DrawGraph().
You need to use $plot->SetDataValues($data) to load the data array for your second plot (the overlay).
Set the data colors again before the overlay. The first color slot (not the 3rd) will be used in the overlay.
The contents of the data array for the second plot could just be two points. You need to know Xmin and Xmax of your data, and calculate Y1 and Y2 from $m*$x+$b, giving you something like:
Except that won't work with text-data data type, which has implicit X values.
OK, that makes it harder. I'm going to have to try this out first. Are you
sure you don't want to try the annotation method using a callback?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I moved the position of setprintimagefalse and now i get the SECOND NEW PLOT
ONLY. My original lines have gone. Looks like only the second one is working?
Two problems I see right away with post #16 above is that your 2nd data array
is not correct, and you are creating a 2nd PHPlot object - which does not
overlay the plots, as you discovered. Sorry this is taking longer than it
should - partly because I couldn't duplicate your script because of the
external function you use to get the data (and partly because we seem to be on
different time zones...)
Let me make up some fake data and then I can do a complete script, and we can
work from there.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
OK, I got a plot with fake data and a yellow line across, but there is a
problem with "y = mx + b" not being well defined because X is not defined in
your first data set. That is, you are leaving "x" up to PHPlot by using text-
data, but then you want to draw a line y=mx+b for given m and b over it. Now,
I know you know what you want to do here, but can you explain it? For example,
do you want your first data point (Wed 2/15 12Z in the sample graph you
posted) to correspond to X=0? What about the other end - is there a fixed
number of points (looks like 49 or 50 in the sample), and what X would that
be?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
OK, here we go. This should give you something to work from. First, a summary
of what I changed:
The part at the top between "Fake data" and "End fake data" is added to build a data array, provide values for unknown variables, etc. You shouldn't need any of this (but try it this way first).
I removed SetLegendWorld() so PHPlot will place the legend in the corner. Your position was off the plot (Y=20 is not within range) so you won't get a legend. Rather than fix it, I just left it out so you get the default position.
For the second plot, I made a data array with 2 points, using data-data format (so I can specify explicit X values). If I did this right, this will draw Y = m * X + b on your graph, with X=1 being the first data point, and X=$datecount being the last.
I removed redundant code in your second plot. You don't want title, etc. Legend and Y data labels need to be explicitly turned off, or they get drawn twice. Also I made this a lines plot, not linespoints, because you don't need the points here. As I said in (3), data type is data-data here.
Try it first, before plugging in your functions. (If you have trouble copying
code from Sourceforge's forums, sorry, they know about it but aren't going to
fix it - affects some browsers only. If you are getting this thread by email
too, try the email version instead.)
<?php#forum: 2/28/2012muppet77require_once'phplot.php';#====Fakedata(somefromsampleimage):$next="Legend line 1";$thism="February CET Prediction";$text3="Legend line 3";$datecount=52;// Number of date points$m=0.06;// Slope of added line, Y = m * X + b$b=0.94;// Intercept of added linedefine('DATAFILE','unused');functionread_prices_text_data($ignored){global$datecount;$data=array();mt_srand(0);$base=gmmktime(12,0,0,2,15);for($i=0;$i<$datecount;$i++){#Labelisdateas:"Mon 02/15 @ 00Z"$data[]=array(gmstrftime('%a %m/%d @ %HZ',$base),mt_rand(5,38)/10,mt_rand(33,44)/10);$base+=6*60*60;// 6 hours}return$data;}#====Endfakedata$legend_text=array($next,$thism,$text3);$plot=newPHPlot(800,600);$plot->SetPrintImage(False);// Defer output until the end$plot->SetTitle($thism." (Shawbury +0.5C as proxy)");$plot->SetDataType('text-data');$plot->SetDataValues(read_prices_text_data(DATAFILE));$plot->SetPlotType('linepoints');$plot->SetDataColors(array('black','red','blue'));$plot->SetLegend($legend_text);// Note this won't work, Y=20 is off the graph//$plot->SetLegendWorld(0, 20);$plot->SetXLabelAngle(90);$plot->SetXTickPos('none');$plot->SetLineStyles('solid');$plot->SetLineWidths(2);$plot->SetYDataLabelPos('plotin');$plot->SetDrawBrokenLines(True);$plot->DrawGraph();// Code below replaces this://require ("regression.php");/* Mapping date values to X value: First date is x=1 (PHPlot uses x=0.5) Last date is x=$datecount (PHPlot uses $datecount-0.5). The line to add is Y = m * X + b for constants m, b. Create a data array with 2 points that solve that equation, but using PHPlot's idea of the X range. Y(x=1) = m + b Y(x=datecount) = m * datecount + b See top of file for $m and $b*/$data2=array(array('',0.5,$m+$b),array('',$datecount-0.5,$m*$datecount+$b),);$plot->SetDataType('data-data');// Note: data-data, array has X values$plot->SetDataValues($data2);$plot->SetPlotType('lines');$plot->SetDataColors(array('yellow'));$plot->SetLineWidths(2);$plot->SetYDataLabelPos('none');// Need to turn these off$plot->SetLegend(NULL);// Cancel legend$plot->DrawGraph();$plot->PrintImage();
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
i already have a graph beautifully drawn out at http://www.maidenerleghweathe
r.com/cetchangegraph.php
i wish to add a simple straight line according to the equation y=mx+b
the values of m and b are found in another file called regression.php and are
known as $m and $b.
as you can see i already have two lines drawn, (red and black) but NOT my
y=mx+b line yet.
how do i do it?
i have left my phplot code alone and added the below code, hoping that it
would superimpose the line????
in fact I have removed
$m = $result;
$b = $result;
as i don't need it.
$m and $b are fine on their own as that's what they are called in
regression.php
one issue is that my original graph has dates on the x axis and i think i need
numbers for my y=mx+b.
my original has $plot->SetDataType('text-data');
but my next version has
$plot->SetDataType('data-data');
not sure what i should be doing so i'll stop now and see if anyone can help!
thanks!
There are a couple of questions, and it might be better to deal with them one
at a time.
The last, easier one first: If your data array has any non-empty strings in
the label positions (0 index of each row), then PHPlot will by default give
them priority over tick labels, assuming that if you put them in the array
they must be important to you. So you will see the label strings, not the X
values (tick labels) along the axis. If you want to see the tick labels
instead of data labels, either (1) don't put the labels in the array - leave
them all empty, or (2) use $plot->SetXTickLabelPos('plotdown') to position the
tick labels, or (3) use $plot->SetXDataLabelPos('none') to un-position the
data labels.
Be aware that the tick labels probably won't line up under your data points,
the way the data labels do. Tick labels and tick marks (which you turned off)
are at fixed intervals along the bottom. There are PHPlot functions to control
them.
ok I am not fussed about data points on the line so will alter it.
can I change it on the original as I'd like the red and black lines to have
them?
what next?
ok gone for your option (3).
what now?
just to be clear my entire code is as follows (first graph plots red and black
lines fine, second graph is my own effort.
i am trying to get a straight line drawn y=mx+b : will it superimpose on the
first, the way i am doing it?
No it won't work that way. The first DrawGraph() sends the image, and the rest
is probably ignored by the viewer/browser. Read the below (which I wrote
before reading your latest).
I can think of 3 ways to add a line to your plot. You can consider it to be an
additional data set, an overlay plot, or an annotation.
Using an additional data set would involve adding a column to your data array,
probably with just 2 points (1 at Xmin, 1 at Xmax). I don't think is practical
in this case, because it involves messing with every row in the data array.
With an overlay plot, you would use $plot->SetPrintImage(False), do your main
graph, $plot->DrawGraph(), then make a new data array with just one line,
$plot->DrawGraph() again, and $plot->PrintImage() to output it. The second
graph will overlay the first. (Similar to what you posted, but you must turn
off automatic image print or you get 2 concatenated PNG images which won't
work.)
The third way is to use a drawing callback function to annotate your plot.
This is the most flexible way, but can take a little more work. There is an
example in the manual, but if you want I can post a little code that is more
specific to what you want. Or if you want to try the overlay, I can show you
one of those.
posting overlay plot code...
$plot->SetPrintImage(False);
returns: Fatal error: Call to a member function SetPrintImage() on a non-
object on this line
$plot->SetPrintImage(False);
when i // out the $plot->SetPrintImage(False);
it draws the graph again but without the extra new data line.
?
Call to a member function on non-object: You have to create the object before you can use it. Move that $plot->SetPrintImage(False) line anywhere after $plot=new PHPlot(...) and before the first $plot->DrawGraph().
You need to use $plot->SetDataValues($data) to load the data array for your second plot (the overlay).
Set the data colors again before the overlay. The first color slot (not the 3rd) will be used in the overlay.
The contents of the data array for the second plot could just be two points. You need to know Xmin and Xmax of your data, and calculate Y1 and Y2 from $m*$x+$b, giving you something like:
$data = array(array('', $xmin, $m$xmin+$b), array('', $xmax, $m$xmax+$b));
Except that won't work with text-data data type, which has implicit X values.
OK, that makes it harder. I'm going to have to try this out first. Are you
sure you don't want to try the annotation method using a callback?
ok - an easier idea.
in another php script (regression.php) i can calculate all the values needed.
if so, would you help me to draw the line please?
i will call them:
$xmin (the first date in the sequence)
$xmax (the last date in the sequence)
$ymin (derived from y=mx+b)
$ymax (as above)
i will be able to count the rows of data which will help me work out $xmin and
$xmax.
how does that sound? so i will have those 4 variables ready to use in the
script?
thanks in advance.
ok, the variables held in regression.php are
$xmin = Wed 02/15 @ 12Z
$xmax = Tue 02/28 @ 06Z
$ymin = 3.7
$ymax = 4.3
please could you help me integrate these to draw a line between these
coordinates?
how do i alter my code?
thanks
and this is the code i wrote - no luck though :-(
i have tried teh xmin and xmax with and without quotes. they are meant to be
dates, so i wasn't sure?
RIGHT, MOVEMENT!
I moved the position of setprintimagefalse and now i get the SECOND NEW PLOT
ONLY. My original lines have gone. Looks like only the second one is working?
i now have
...and the good news is that the data is getting sucked from regression.php
ok.
but hwy no first plot overlaying the second?
any ideas?
thanks
could it be down to the fact that my x values are realy text values and so it
is not matching them up?
Two problems I see right away with post #16 above is that your 2nd data array
is not correct, and you are creating a 2nd PHPlot object - which does not
overlay the plots, as you discovered. Sorry this is taking longer than it
should - partly because I couldn't duplicate your script because of the
external function you use to get the data (and partly because we seem to be on
different time zones...)
Let me make up some fake data and then I can do a complete script, and we can
work from there.
OK, I got a plot with fake data and a yellow line across, but there is a
problem with "y = mx + b" not being well defined because X is not defined in
your first data set. That is, you are leaving "x" up to PHPlot by using text-
data, but then you want to draw a line y=mx+b for given m and b over it. Now,
I know you know what you want to do here, but can you explain it? For example,
do you want your first data point (Wed 2/15 12Z in the sample graph you
posted) to correspond to X=0? What about the other end - is there a fixed
number of points (looks like 49 or 50 in the sample), and what X would that
be?
the number of x dates changes the whole time.
I call the first date x =1
I can give you a variable to let you know what the last x is if you need it
rather than working with dates?
and by that I mean I have a variable that is 52 or however many dates there
are.
assume it is called $datecount if that helps coding it.
if you use my y min and y max variables then yes, x=1 and x=$datecount every
time.
OK, here we go. This should give you something to work from. First, a summary
of what I changed:
The part at the top between "Fake data" and "End fake data" is added to build a data array, provide values for unknown variables, etc. You shouldn't need any of this (but try it this way first).
I removed SetLegendWorld() so PHPlot will place the legend in the corner. Your position was off the plot (Y=20 is not within range) so you won't get a legend. Rather than fix it, I just left it out so you get the default position.
For the second plot, I made a data array with 2 points, using data-data format (so I can specify explicit X values). If I did this right, this will draw Y = m * X + b on your graph, with X=1 being the first data point, and X=$datecount being the last.
I removed redundant code in your second plot. You don't want title, etc. Legend and Y data labels need to be explicitly turned off, or they get drawn twice. Also I made this a lines plot, not linespoints, because you don't need the points here. As I said in (3), data type is data-data here.
Try it first, before plugging in your functions. (If you have trouble copying
code from Sourceforge's forums, sorry, they know about it but aren't going to
fix it - affects some browsers only. If you are getting this thread by email
too, try the email version instead.)
awesome!!! many mnay thanks!
http://www.maidenerleghweather.com/newcetgraph.php
how do i move the legend around please so it's out the way of the data?