|
Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Jonathan on Apr-06-2011 05:11 |
|
Hi,
I have a contour chart by using XYChart (xyChart.addContourLayer(xVals, yVals, zVals)), and used ColorAxis for my color legend. First of all, when I create a contour chart, I notice that min and max values of color legend do not match with the min and max values in values in Z axis. Second, the min and max values of color legend keep changing as I set levels for ColorAxis. After all, can you tell me how I can set fixed min and max values for the color legend in my contour chart?
Here is my sample dataset I used for a simple contour chart (with default level).
x, y, z
1, 7, 100
2, 7, 100
1, 8, 100
2, 8, 100
3, 9, 110
4, 9, 110
3, 10, 110
4, 10, 110
5, 11, 120
6, 11, 120
5, 12, 120
6, 12, 120
The min and max values in Z Axis are 100 and 120, respectively. However, the min and max in color legend show as 98 and 122, respectively.
I appreciate your help.
Thanks,
Jonathan |
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Jonathan on Apr-06-2011 05:58 |
|
ColorAxis.setLinearScale(min, max); seems solve my problem I asked. Can you verify my solution is right?
Thanks in advance
Jonathan
|
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Peter Kwan on Apr-07-2011 01:20 |
|
Hi Jonathan,
The color axis is showing the max and min values of the chart, which can be greater and smaller than the max and min values of your data.
I have attached a line chart as an example. You can see there are six points, and their maximum value is 3. However, if you need to join the points with a curve, it is normal and natural that the top of the curve will be higher than 3.
The same happens in a contour chart. Your code provides some points. ChartDirector will need to compute the entire surface based only these points. If you use smooth interpolation (for a smoother contour), it is possible the highest point in the surface is larger than the maximum z data value.
If you would like the color axis to show only your data range (which is not the same as the contour range), you may use ColorAxis.setLinearScale to set the range. So your solution is a good solution.
Another alternative is not to use smooth interpolation, but use linear interpolation. (For a line chart, it is like joining the points with straight lines rather than a curve.) Linear interpolation will not overshoot or undershoot, but the contour will not be as smooth. For example:
myContourLayer.setSmoothInterpolation(false);
Hope this can help.
Regards
Peter Kwan
|
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Jonathan on Apr-07-2011 02:12 |
|
Hi Peter,
Thanks for your clear explanation. I have one more question in the same subject.
If I still use smooth interpolation with my data range, would the highest point in the surface which is larger than the maximum z data value have same color as the maximum z data value?
(BTW, Contour chart with linear interpolation doesn't look nicer as attached one below)
Thanks,
Jonathan
|
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Jonathan on Apr-07-2011 05:58 |
|
Hi Peter,
One more question. The color scale in the chart attached above wasn't displaying correctly. (I forgot removing the ColorAxis.setLinearScale(min, max))
Although I set this setting myContourLayer.setSmoothInterpolation(false), the color range is still not based on data range as you can see the attached chart here. (In this specific dataset, min value is not correct) Any thoughts/suggestions?
Thanks,
Jonathan
|
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Peter Kwan on Apr-07-2011 23:45 |
|
Hi Jonathan,
If you set the color axis range to 100 to 120, but the highest data point is larger than 120 (either because your original data points are higher than 120, or because the smooth interpolation creates a surface with points higher than 120), by default, these points will be colored as if they are at 120. Similarly, points that are below the lowest axis range will be colored as if it is at the lowest axis range.
For the linear interpolation case, we have known for some time that it may have rounding issues for absolutely flat surface (surface with constant z). The error is of the order of 10E-16 (or 0.0000000000000001) of the data value. Even the error is so small that it cannot affect the color, it can cause the minimum value to drop below 100 (to become 99.99999999999). So the color axis scale become less than 100. By default, ChartDirector will start the scale at a tick position, so it will choose 98 as the starting point, which is the nearest tick position below 100.
For your case, if you can use the smooth interpolation method, I suggest you use the smooth interpolation method. I am not sure if having a surface that exceeds the maximum data value would be an issue for your application. For many applications, this may be normal and acceptable.
For example, if you are measuring the temperature in a region, and the data shows an upward trend towards some point in the region that you have not measured, it is normal to expect that the temperature at that point is higher than any of your points. It is like the spline curve example in my last message, that it is normal for a point in the curve to be higher than all of the data points if there is trend.
However, if the nature of your application is that the surface can never exceed the data points, you may consider to set the color axis scale with your own code using setLinearScale.
Note that if you set the scale to "99.99999 to 120", ChartDirector may end up using 98 to 120 as the axis scale (because it will start the axis at a tick position). If you do not want ChartDirector to start the axis at a tick position, you may use Axis.setRounding like:
colorAxis.setRounding(false, false);
Hope this can help.
Regards
Peter Kwan |
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Jonathan on Apr-12-2011 23:08 |
|
Hi Peter,
Thanks for your answer. It really answers my question.
However, I have one more question regarding to "colorAxis.setRounding(false, false);" Could you tell me if both following options below can be meet at the same time.
1. User wants to see exact min and max value of data range. I understand that this is possible through colorAxis.setRounding(false, false)
2. User also wants to see a tick position at min and max value of data range. In other words, user also wants to see a tick at starting and ending position of the color legend. Otherwise, user won't know what are the min and max values of data range.
If your answer is no, is there any workaround to make it work by any chance?
For example, a tick starts at 2850.00 and ends at 3000.00 in the chart below. The min and max values of the data range are 2817.03 and 3030.97, respectively. Thus, in this case, I would like to display the color legend with both a starting tick with 2817.03 and a ending tick with 3030.97
Thanks,
Jonathan
|
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Peter Kwan on Apr-13-2011 01:30 |
|
Hi Jonathan,
You can use Axis.addMark to add a label at any place you want in the color axis, such as adding the label at the end points of the axis. For example:
colorAxis.addMark(minValue, -1, minValue).setMarkColor(Chart.Transparent, 0x000000, 0x000000);
Hope this can help.
Regards
Peter Kwan |
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Jonathan on Apr-13-2011 05:16 |
|
Hi Peter,
I found an issue with fixed linearScale with level equal to 1. Is this a bug within ChartDirector?
For example, I create 3 contour charts as followings:
1. first contour chart with
x, y, z
1, 7, 100
2, 7, 100
1, 8, 100
2, 8, 100
2. second contour chart with
x, y, z
3, 9, 110
4, 9, 110
3, 10, 110
4, 10, 110
3. third contour chart with
x, y, z
5, 11, 120
6, 11, 120
5, 12, 120
6, 12, 120
Both "ColorAxis.setLinearScale(min of z axis, max of z axis)" and "ColorAxis.setLevels(1)" setting applies to all three charts. The color legend label is not displaying only for the first contour chart while it is displaying for the other charts. I attach an image to illustrate this issue. Interestingly, when I change the contour level other than 1, color legend label does display. Can you explain how I can fix this issue?
|
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Jonathan on Apr-13-2011 23:12 |
|
Hi Peter,
Thanks for your support. We are getting there almost where customer wants to see the customized contour chart via ChartDirector.
I have one more question related to this ticket. Since I am using "colorAxis.setRounding(false, false);" to have the exact min and max value of the data range for the color range, I realized that ticks in certain data does neither start off nor end at the min and max value of the data range, respectively. It is important since user wants to see the exact contour level number ("ColorAxis.setLevels"). Is there a way I can customized tick position with its displaying value?
Here is a piece of my code I tried, but it doesn't work
=====================================================
if(!Double.isNaN(colorMax) && !Double.isNaN(colorMin)){
//fixed min and max of color range
cAxis.setRounding(false, false);
//display min and max of color range
cAxis.addMark(colorMin, -1, Double.toString(colorMin)).setMarkColor(0x000000, 0x000000);
cAxis.addMark(colorMax, -1, Double.toString(colorMax)).setMarkColor(0x000000, 0x000000);
//set exact number of contour level
int contourLevel = contourAttributes.getContourLevel();
double offset;
if(contourLevel==0){
offset = 0;
}else{
offset = (colorMax - colorMin) / contourLevel;
}
cAxis.setLinearScale(colorMin, colorMax, offset);
cAxis.setLevels(contourLevel);
//re-position tick position and its value ??
int tickLength = cAxis.getTicks().length;
double tickValue = colorMin;
for(int i=0; i<tickLength; i++){
tickValue += offset;
cAxis.getTicks()[i] = tickValue;
}
}
=====================================================
Also, here is an example to illustrate my issue. In this example, user sets 2 for contour level(ColorAxis.setLevels(2)). Here, I have displayed min value of 2814 and max value of 3128 value on color range, and two ticks which value is 2827 and 2984 seem to be generated by auto axis. In this case, I would like to display 3 ticks (since contour level is 2): first tick should be 2814 for min value, second tick should be 2971 (2971 = min + offset = 2814 + 157), and third tick should be 3128 for the max value. Is this feasible?
|
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Peter Kwan on Apr-14-2011 00:34 |
|
Hi Jonathan,
I think the issue is related to using setLevels(1) with setRounding(false, false).
If you do not use setRounding(false, false), you can see the true scale selected by ChartDirector, which should contain 1 segment (2 labels) as specified by setLevels(1). However, if setRounding(false, false) is used, the two labels may be trimmed off (in setRounding, the axis may not start or end at a label position), and the axis may end up having no label. This is further complicated by the fact the the axis scale used in setLinearScale may be invalid. (The min and max values in setLinearScale should be different, as an axis scale needs a finite range, otherwise ChartDirector may try to make up an arbitrary range.)
For your case, if you would like to use setLevels(1) with setRoundng(false, false), I suggest you may use the following instead.
If (minValue != maxValue)
ColorAxis.setLinearScale(minValue, maxValue, maxValue - minValue);
else
//min = max??? just make up a range
ColorAxis.setLinearScale(minValue * 0.5, maxValue + minValue * 0.5, minValue);
Hope this can help.
Regards
Peter Kwan |
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Jonathan on Apr-14-2011 00:55 |
|
Hi Peter,
The dataset I provided you above (Posted by Jonathan on Apr-12-2011 17:16) is just an example. As you can see in my post, the second (z=110) and the third contour chart (z=120) with the same min and max can display the label. BTW, I also see this issue in other real datasets where min value is not equal to max value. (My example just happens to be (min=max)) Any thoughts? and Could you answer the other question of mine (Posted by Jonathan on Apr-13-2011 11:12) as well when you have time?
Thanks so much in advance,
Jonathan |
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Peter Kwan on Apr-14-2011 02:46 |
|
Hi Jonathan,
For your case, I would probably use the following code:
if(!Double.isNaN(colorMax) && !Double.isNaN(colorMin)) {
if (contourLevel == 0) {
// I assume this means contour levels are not specified at all, so use auto-scaling
cAxis.setLinearScale(colorMin, colorMax);
cAxis.setRounding(false, false);
cAxis.addMark(colorMin, -1, Double.toString(colorMin)).setMarkColor(0x000000, 0x000000);
cAxis.addMark(colorMax, -1, Double.toString(colorMax)).setMarkColor(0x000000, 0x000000);
} else {
// The entire axis scale is specified. There is nothing to auto-scale. So just specify the scale.
cAxis.setLinearScale(colorMin, colorMax, (colorMax - colorMin) / contourLevel);
}
}
ChartDirector auto-scaling is normally used to automatically determine some scale parameters (the min, max and tick increment). However, if the scale is already completely determined by your code, you can just specify the scale directly.
Note that if colorMax and colorMin can be the same in your code, you may add the following code to make up a data range:
if (colorMax == colorMin) {
colorMax += 0.5 * Math.abs(colorMin);
colorMin -= 0.5 * Math.abs(colorMin);
}
Hope this can help.
Regards
Peter Kwan |
Re: Can I have a fixed min and max value on color legend in Contour chart? |
Posted by Jonathan on Apr-14-2011 04:47 |
|
Hi Peter,
Awesome! Your suggestion works as I want it. Thanks for your great support!!
Thanks,
Jonathan |
|