PChart Right axis to show labels for specific values - php

I currently have the wind chart shown below working with the mean, low and high values.
What i would like to add but i can figure out is:
I need a plot a right hand scale that would show the wind force. I would guess this would be set as a label for a specific value.
So in this case
label for force 1 should be in line with wind speed 1
label for force 2 should be in line with wind speed 4
label for force 3 should be in line with wind speed 7
label for force 4 should be in line with wind speed 11
label for force 5 should be in line with wind speed 17
is there anyway i can create a y axis that shows a specic label at specific value?
thus creating something like this: but where the numbers line up to the right values

Here is what worked for my application. I was making a particle count graph:
$MyData->addPoints(array(7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24),"ISO");
$MyData->setSerieOnAxis("ISO",1);
$MyData->setAxisName(1,"ISO Code");
$MyData->setAxisPosition(1,AXIS_POSITION_RIGHT);
$MyData->setSerieDrawable("ISO", FALSE); //dont plot results just show axis
then further down where you do your scale:
$AxisBoundaries = array(0=>array("Min"=>0,"Max"=>5),1=>array("Min"=>7,"Max"=>24));
$ScaleSettings = array("Mode"=>SCALE_MODE_MANUAL,"ManualScale"=>$AxisBoundaries);
$myPicture->drawScale($ScaleSettings);
So you set the scale for the left and right axis there. In my application my right side needed to go from 7 to 24 and my left side from 0 to 5. I didnt plot my right side graph, as I just wanted to show the scale.
You pretty much have to fiddle with your min and max to get them to line up where you want and you have to make sure the left axis is fixed. If its dynamic then it will be different each time depending on your data.

Related

How to make a Random Walk, PHP?

I've been trying for several hours to make a random walk (a path) like this one.
From top to down.
x 1 x
x 2 3
x x 4
7 6 5
8 x x
9 10 x
My greatest difficulty is to calculate the displacement from right to left because the cycles (for, while..) go from left to right.
I am not proficient in math, so I'm using a simple approach.
I have two arrays. One with the position of the previous row.
$previousRow=array(1=>"x",2=>"1",3=>"x");
One with the current row I have to fill.
$currentRow=array(1=>"",2=>"",3=>"");
$p //Is the current position. 1, 2 or 3. Example $currentRow[$p]
$last //the last number that increases each time the path has a new step.
I'm using some cycles and conditions to set the displacement.
Is this approach wrong?
EDIT: further specifications as requested from comments:
Start point is located in the middle point of the first row
End point is located in the last row
End point can be located in any column of the last row
per each field you have three possibilities: left, right, forward.
some cases reduce this, e.g. there is no field to the left or right or that field was visited already.
so find out about possible moves, pick one at random and go on.

How to convert artbitrary number to rgb color?

I have an application that has about one hundred users. We have a calender view in which every user can have multiple entries. Every entry of the same user should have the same color, but different users should have different colors. At the moment we have manually defined about 25 colors in an array, and the color a user gets is determined by
$color = $colors[$userid % count($colors)];
We don't want to manually add colors for every new user, and selecting a color for each user seems a bit tedious too.
Is there a simple function to map a number (the users id) to a color (preferably RGB)? The next question that rises is; Is there a way to limit the function to a certain types of colors (ie. only colors in which white letters are readable)?
I don't have a solution, per se, but a suggestion.
First, since you want each user's colors to be unique but random, you could get started with some kind of numerical hash function. That gets you a random number that's most likely unique. if your hash function is decent and your users are in the hundreds that should suffice.
Now you need to turn that into colors, preferably on the dark end of the spectrum. If you go with RGB, You need three numbers. To keep them dark, lets say you keep the total or R, G and B under 200. That's a guess, of course, but it should be pretty dark. Pick a random number [index] between 1 and 3 - that's the R, G or B you're going to start with. Get a number between 0 and 200, and set record it for color[index1]. Now pick one of the remaining indexes, 1-3. For this, pick a number between 0 and color[index1] that you already have. Set the remaining number to 200-color[index1]-color[index2]. Now you have a randomish RGB value that should contrast with white.
I realize I never got much use from that hash function up front - maybe ditch it and just use the userid as a random(seed).
You want to work in the hue-saturation-lightness or hue-saturation-value (HSL or HSV) space.
http://en.wikipedia.org/wiki/HSL_and_HSV
Start by defining some colors based on hue and saturation, and set the lightness to the highest tolerable level that makes the text readable.
Then you can fix the hue and saturation for these colors and decrease the lightness.
So say you started by choosing 25 tolerable colors with different hues and maximum/minimum tolerable lightness.
To generate a color for an index you pick the base color to start with base = id % 25 You then decrease the luminance depending on the index within that color index = (Math.floor(id/25)). Set the luminance somewhere within the tolerable luminance range based on that value. So let's say we will have 5 luminance values per color, set the luminance to
lightness = maxLightness - index*(maxLightness / 4*minLightness)
This simply varies the lightness for each color. You can choose to vary saturation and hue slightly if you would prefer. Converting between HSV and RGB is a well documented procedure.
PHP HSV to RGB formula comprehension

Can text be inserted into a fusion chart?

I'm using the Grid component in fusion charts and need a date string to be used in the value place. It will always fail when i do this as it is looking for a number. Is there anyway it can allow text to be used aswell?
Thanks
The ability to have date-time axis values is not yet available in FusionCharts. Nevertheless, the use case for you does not fit right.
Ideally, the grid component's right column should show a number (value). The left column is text showing the labels. For a grid, it makes very less sense to have text on both columns.
Instead of a date, the right column should show how many month's or days or hours, etc.
Excerpts from FusionCharts documentation: http://docs.fusioncharts.com/charts/contents/advanced/number-format/Number_Scaling.html
Say we're plotting a chart which indicates the time taken by a list of automated processes. Each process in the list can take time ranging from a few seconds to few days. And we've the data for each process in seconds itself. Now, if we were to show all the data on the chart in seconds only, it won't appear too legible. What we can do is build a scale indicating time and then specify it to the chart. This scale, in human terms, would look something as under:
60 seconds = 1 minute
60 minute = 1 hr
24 hrs = 1 day
7 days = 1 week
Now, to convert this scale into FusionCharts XML format, you'll have to do it as under:
First you would need to define the unit of the data which you're providing. Like, in this example, you're providing all data in seconds. So, default number scale would be represented in seconds. We can represent it as <chart defaultNumberScale='s' ...>
Next, we define our own scale for the chart as: <chart numberScaleValue='60,60,24,7' numberScaleUnit='min,hr,day,wk' >. If you carefully see this and match it with our range, you'll find that whatever numeric figures are present on the left hand side of the range is put in numberScaleValue and whatever units are present on the right side of the scale has been put under numberScaleUnit - all separated by commas.
Set the chart formatting flags to on as: <chart formatNumber='1' formatNumberScale='1' ...>
The entire XML would look like:
<chart defaultNumberScale='s' numberScaleValue='60,60,24,7' numberScaleUnit='min,hr,day,wk'><set label='A' value='38' /><set label='B' value='150' /><set label='C' value='11050' /><set label='D' value='334345' /><set label='E' value='1334345' /></chart>
A sample grid (not with the above data) would look like this:

Minimum value for graph axis

I am trying to make a bargraph that plots times.
So what the technical issue we are trying to get the minimum plot value to something.
For example if what I was trying to graph was 4 min 30 s (4:30), 4:45, 4:15, and 4:20,
I would like the y=0 value to be 4 minutes and each increment in the y axis to be 1 second.
Effectively, it would be a bargraph of 30, 45, 15, and 20 with the y = 0 axis labelled as.
Is there anyway of doing this without have to man handle the data?
Help please if you know how to do this with jpgrah.
Otherwise, does anyone know what this feature is called in general so I can google it up?
I was reading the documentation of jpgrah:
SetYBase seemed a like a good candidate but all it seemed to do when I played with the parameters was shrink the upper limit y-value [Specify the start plot for bars, (minimum Y-value). By default the base uses the value 0 as base.]
Found the appropriate method in the JPGraph documentation:
$aGraph = new Graph($aWidth,$aHeight,'auto');
$graph->SetScale('textlin',$aMinY,$aMaxY);
$aMinY and $aMaxY give the minimum and maximum values included in the graph.
Also, they are optional arguments.

Space a series of values so they don't overlap

There have been a couple of questions very close to this topic, but none really helped me.
Ive been programming a graphing library, and I need an algorithm to vertically place labels without overlapping. I've been stuck on this for a couple of days now, and managed to distil it to the most basic function:
If given a series of label positions along the Y axis, say, 1 1 2 3 5 6 9, and an upper and a lower limits 10 and 0 respectively, I need a way to space out the values to output 1 2 3 4 5 6 9
333467 should be 234567 weighted to be close to the original coordinates.
This should also work backwards, if values are bunched up at the upper end of the scale, they should be spread as much as possible (before overflowing)
I'm not looking for a definitive answer, but I'd like some help on how to approach this problem. Im completely stuck.
Last train of thought was to scan all labels for possible collisions and position them as one big block, aligning to the centre of all the Y coordinates. But this will not work if there are multiple sets of collisions.
EDIT: To put this algorithm in a bigger context, have a look at these two google chart API pie charts:
1) Top stacked labels
2) Bottom Stacked Labels
The labels are almost springy, they avoid collisions by joining together and moving their entire mass to the center of their mass.
Make the set of labels unique by inserting into an ordered set. Divide the difference between the y-axis upper and lower bound by the number of elements in the set. This is your spacing increment. Iterate over the set in order and position one label every spacing increment.
You didn't say anything about needing to preserve a scale...
Well, After some thought and advice from other sources i came up with a solution:
Pseudocode:
foreach labels as label
if label->collidesWith(labels->lowerLimit)
label->moveAwayFrom(labels->lowerLimit)
if label->collidesWith(labels->upperLimit)
label->moveAwayFrom(labels->upperLimit)
if label->collidesWith(label->previous)
label->moveAwayFrom(label->previous)
label->previous->moveAwayFrom(label)
if label->collidesWith(label->next)
label->moveAwayFrom(label->next)
label->next->moveAwayFrom(label)
endforeach
MoveAwayFrom moves 1 pixel at a time. When this function is run multiple times it rejiggles the labels until none of them collide. (in reality im calling this loop 100 times, havent figured out a way to do it more inteligently)

Categories