Discussions
Categories
Groups
Community Home
Categories
INTERNAL ENABLEMENT
POPULAR
THRUST SERVICES & TOOLS
CLOUD EDITIONS
Quick Links
MY LINKS
HELPFUL TIPS
Back to website
Home
Intelligence (Analytics)
Move up a secondary y Axis and its series
bigFred
Hello,
anyone can help me out on this one ?
If you look at the gif's attached, I have a secondary y Axis and I'm desperately trying to move up this y Axis and its series so that the series start value of 100 is aligned with the horizontal axis (and therefore aligned with the 0% value on the primary y Axis).
I've tried many things in a java Chart handler : changing the chart Scale min/max values in beforeGeneration(), changing the values of the DataSet by removing 100 in afterDataSetFilled(), etc... without success.
Really appreciate any help....
Fred
Find more posts tagged with
Comments
bigFred
What I'm trying to do is the following :
in the beforeGeneration method, I calculate the max and the min of the series DataSet. With this values and a fixed number of axis ticks I want, I calculate the step, range between 2 ticks. And with this step, I finally calculate the difference between the total number of steps/2 and the number of steps from the origin to 100. It gives me the number I'll set in the field Min in the Scale : ...getScale().setMin(calc number)....
I have the feeling that somehow I reinvent the wheele, that this kind of algorithm should be done in the Chart engine. Either i didn't find it or we have no access to it.
Thanks if you have any idea for making this more simple.
mwilliams
Can you show me some sample data so I can try to recreate your chart? Or can you recreate the issue for me with the sample database or some other sort of source that I can use to run the report? Thanks!
bigFred
Thanks for looking at my problem. Attached is the CSV comma separated file chart_2_y_axis_data.txt containing all the data you need for my chart.
Note the following points :
1. - the xAxis category is build from column PtfDate,
- primary Bars yAxis from PtfPerf, BenchPerf, DiffPerf
- secondary Lines yAxis2 from PtfCumuPerf, BenchCumuPerf, DiffCumuPerf
2. In the chart, I set the xAxis Origin at Value 0
3. All axes have the Scale Step to Auto
mwilliams
What's your BIRT version?
bigFred
I have the chart engine 2.6.2
I think I'll come soon with a solution. I have to work on scal min, max, steps of both primary and secondary yAxis. I publish my temptative solution asap.
Thanks
bigFred
okay, I've got something. It works in the sense that I have my secondary axis centered at 1% (or 100 basis point), and the primary axis centered at 0%. I still have to work on the number of steps.<br />
<br />
Here is the code of my chart handler : <br />
<br />
public class GraphicalPerformanceChartEventHandler extends<br />
ChartEventHandlerAdapter {<br />
<br />
@Override
<br />
public void beforeGeneration(Chart chart, IChartScriptContext icsc) { <br />
<br />
super.beforeGeneration(chart, icsc); <br />
if (chart instanceof ChartWithAxesImpl) {<br />
ChartWithAxesImpl chartWithAxis = (ChartWithAxesImpl) chart;<br />
<br />
Axis yAxis = chartWithAxis.getOrthogonalAxes(xAxis, true)[0];<br />
Axis yAxis2 = chartWithAxis.getOrthogonalAxes(xAxis, true)[1];<br />
<br />
<br />
// Get the bar series<br />
EList<SeriesDefinition> ySeriesDefn = yAxis.getSeriesDefinitions();<br />
Series[] ySeries = yAxis.getRuntimeSeries();<br />
<br />
//Get the line series<br />
EList<SeriesDefinition> ySeriesDefn2 = yAxis2.getSeriesDefinitions();<br />
Series[] ySeries2 = yAxis2.getRuntimeSeries();<br />
<br />
//Find the max for the y series DataSet<br />
Double max = getMaxSeriesValue(ySeries);<br />
Double max2 = getMaxSeriesValue(ySeries2);<br />
<br />
//Add gaps to axis up limits<br />
max = Math.ceil(max);<br />
max2 = Math.ceil(max2);<br />
<br />
//calculate half amplitude, different for the secondary y axis<br />
Double halfAxisAmplitude = max ;<br />
Double halfAxisAmplitude2 = max2 - 1.0;<br />
<br />
Double min = 0.0 - halfAxisAmplitude;<br />
Double min2 = 1.0 - halfAxisAmplitude2;<br />
<br />
yAxis.getScale().setMin(NumberDataElementImpl.create(min.doubleValue()));<br />
yAxis.getScale().setMax(NumberDataElementImpl.create(max.doubleValue()));<br />
<br />
yAxis2.getScale().setMin(NumberDataElementImpl.create(min2.doubleValue()));<br />
yAxis2.getScale().setMax(NumberDataElementImpl.create(max2.doubleValue()));<br />
} <br />
} <br />
<br />
private Double getMaxSeriesValue(Series[] ySeries2) {<br />
Double max = new Double(0.0); <br />
for (int i = 0; i < ySeries2.length; i++) {<br />
Number[] values = (Number[])ySeries2
.getDataSet().getValues();<br />
for (int j = 0; j < values.length; j++) {<br />
if(i == 0 && j == 0){<br />
max = (Double)values[0];<br />
}<br />
if((Double)values[j] > max){<br />
max = (Double)values[j];<br />
}<br />
} <br />
}<br />
return max;<br />
}<br />
}
mwilliams
Thanks for the update. I had messed around with trying to set a secondary axis and x-axis intersection in an easier way, and I didn't see one. What you've done is probably what you have to do to get this exactly how you want it. If I find anything simpler, I'll let you know. You could always log an enhancement request for this in the eclipse.org/birt bugzilla to have a setting where the x-axis intersects the secondary axis.
bigFred
Thanks, actually the java handler I've programmed works pretty well now. I just had to add a calculation for the max + a gap, depending on the max series values that may have different decimal value. And also I needed to adjust the primary y Axis as well in order to center it to 0% following the max series value calculated before.<br />
<br />
Here is my final code version. Might help other BIRT developper : <br />
<br />
<pre class='_prettyXprint _lang-auto _linenums:0'>/**
* Handle the position of both y axis : the primary axis is centered to 0%
* and the secondary y axis is centered to 1% (100 basis point)
*
@param
yAxis the primary y axis
*
@param
yAxis2 the secondary y axis
*
@param
ySeries the primary y axis series
*
@param
ySeries2 the secondary y axis series
*/
private void handleVerticalAxisPosition(Axis yAxis, Axis yAxis2,
Series[] ySeries, Series[] ySeries2) {
//Find the max for the y series DataSet
Double max = getMaxSeriesValue(ySeries);
Double max2 = getMaxSeriesValue(ySeries2);
//Add gaps to axis up limits
Double maxWithGap = getMaxSeriesWithGap(max);
Double maxWithGap2 = getMaxSeriesWithGap(max2);
//calculate half amplitude, different for the secondary y axis
//the secondary y Axis is centerer on 1% (or 100 basis point) to the x axis
Double halfAxisAmplitude = maxWithGap ;
Double halfAxisAmplitude2 = maxWithGap2 - 1.0;
Double min = 0.0 - halfAxisAmplitude;
Double min2 = 1.0 - halfAxisAmplitude2;
yAxis.getScale().setMin(NumberDataElementImpl.create(min.doubleValue()));
yAxis.getScale().setMax(NumberDataElementImpl.create(maxWithGap.doubleValue()));
yAxis2.getScale().setMin(NumberDataElementImpl.create(min2.doubleValue()));
yAxis2.getScale().setMax(NumberDataElementImpl.create(maxWithGap2.doubleValue()));
}
/**
* Resize the max value with a gap.
* The rule applied here is to round to the first non 0 decimal :
* 0.037 -> 0.04, 3.4 -> 4
*
@param
max
*
@return
the max with the added gap
*/
private Double getMaxSeriesWithGap(Double max) {
int decimalIndex = 0;
while( max< 1.0 ) {
max = max * 10;
decimalIndex++;
}
max = Math.ceil(max)/Math.pow(10, decimalIndex);
return max;
}
/**
* Return the max value in the given series.
*
@param
ySeries
*
@return
the max value in the series
*/
private Double getMaxSeriesValue(Series[] ySeries) {
Double max = new Double(0.0);
for (int i = 0; i < ySeries.length; i++) {
Number[] values = (Number[])ySeries[i].getDataSet().getValues();
for (int j = 0; j < values.length; j++) {
if(i == 0 && j == 0){
max = (Double)values[0];
}
if((Double)values[j] > max){
max = (Double)values[j];
}
}
}
return max;
}</pre>