Dynamic Y-axis scale

paqman
edited February 11, 2022 in Analytics #1
Hello BIRT Experts,<br />
<br />
I am trying to adjust the y-axis of a report based on a report parameter. If the report parameter is greater than the default y-axis maximum, the y-axis maximum should be set to the parameter. Otherwise, the y-axis scale should keep its default formatting.<br />
<br />
I've made some progress with the following script (note that the y and x axes are inverted in this report):<br />
<br />
<pre class='_prettyXprint _lang-auto _linenums:0'>function beforeGeneration( chart, icsc )
{
// Force the y-axis scale to increase if load mark is greater than its default
yAxis1 = chart.primaryBaseAxes[0];
yScale1 = yAxis1.getScale();
if(icsc.externalContext.scriptable.getParameterValue("LoadMark") > yScale1.getMax())
{
yScale1.setMax(NumberDataElementImpl.create(icsc.externalContext.scriptable.getParameterValue("LoadMark")));
yAxis1.setScale(yScale1);
}
}</pre>
<br />
The problem I'm having is that yScale1.getMax() is returning nothing (I'm assuming it gets set later on in the chart rendering) and the y-scale ends up always being set to the report parameter. Which event function sets the y-axis min and max, and what would be the best way to work out this problem?<br />
<br />
Thanks for your help<br />
<br />
David
«1

Comments

  • mwilliams
    edited December 31, 1969 #2
    What is your BIRT version? I'll check it out in your version.
    Warning No formatter is installed for the format ipb
  • paqman
    edited December 31, 1969 #3
    We are using 2.6.1 - thanks for the help!
  • mwilliams
    edited December 31, 1969 #4
    The min and max values aren't set yet in the beforeGeneration. I'll keep working to see if I can find a way to set the scale if the parameter is higher than the max.
    Warning No formatter is installed for the format ipb
  • mwilliams
    edited December 31, 1969 #5
    Is there any way you can figure out the max value of the chart from your dataSet data so you could know in the beforeGeneration what you needed to do?
    Warning No formatter is installed for the format ipb
  • paqman
    edited December 31, 1969 #6
    Yes, good point. I can add a script to the dataset to determine the maximum value, and then put that into a global variable.
  • mwilliams
    edited December 31, 1969 #7
    Awesome. Let me know if you have any issues with this. Let us know whenever you have questions! :)
    Warning No formatter is installed for the format ipb
  • paqman
    edited December 31, 1969 #8
    Will definitely have more questions in the near future! :) Thanks guys
  • paqman
    edited December 31, 1969 #9
    Forgot to post the working code. A report parameter, 'LoadMark', is used to draw a marker line in the chart. The script determines the maximum value of all datasets and forces the y-axis to be the value of LoadMark if LoadMark is greater than the dataset maximum. <br />
    <br />
    <pre class='_prettyXprint _lang-auto _linenums:0'>importPackage(Packages.org.eclipse.birt.chart.model.data.impl);
    maxValue = 0;

    /**
    * Called before generation of chart model to GeneratedChartState.
    *
    * @param chart
    * Chart
    * @param icsc
    * IChartScriptContext
    */

    function beforeGeneration( chart, icsc )
    {
    // Force the y-axis scale to increase if the load mark is greater than its default
    yAxis1 = chart.primaryBaseAxes[0];
    yScale1 = yAxis1.getScale();
    if (icsc.externalContext.scriptable.getParameterValue("LoadMark") > maxValue)
    {
    yScale1.setMax(NumberDataElementImpl.create(icsc.externalContext.scriptable.getParameterValue("LoadMark")));
    yAxis1.setScale(yScale1);
    }
    }

    /**
    * Called before drawing each marker line in an Axis.
    *
    * @param axis
    * Axis
    * @param markerLine
    * MarkerLine
    * @param icsc
    * IChartScriptContext
    */

    function beforeDrawMarkerLine( axis, markerLine, icsc )
    {
    // Draw the LoadMark line if specified.
    var loadMark = icsc.externalContext.scriptable.getParameterValue("LoadMark");
    if (Number(loadMark) == 0)
    markerLine.getLineAttributes().setVisible(false);
    else
    markerLine.setValue(NumberDataElementImpl.create(loadMark));
    }

    /**
    * Called after populating the series dataset.
    *
    * @param series
    * Series
    * @param dataSet
    * DataSet
    * @param icsc
    * IChartScriptContext
    */

    function afterDataSetFilled( series, dataSet, icsc )
    {
    importPackage(Packages.java.io);
    importPackage(Packages.org.eclipse.birt.chart.model.type.impl);
    importPackage(Packages.org.eclipse.birt.chart.util);
    importPackage(Packages.java.util);
    ps = PluginSettings.instance();

    dsp = ps.getDataSetProcessor(series.getClass());
    if (dsp.getMaximum(dataSet) > maxValue)
    {
    maxValue = dsp.getMaximum(dataSet);
    }
    }
    </pre>
  • mwilliams
    edited December 31, 1969 #10
    Yeah, I completely wasn't thinking right when I answered you above. I've posted examples getting the min and max this same way before. Sorry about that! Glad you got it done the right way despite me having a brain lapse! :) Feel free to post this as an example in the devShare, if you'd like!
    Warning No formatter is installed for the format ipb
  • paqman
    edited December 31, 1969 #11
    No worries - you're allowed 1 brain lapse per 20 questions of mine that you answer :) Your suggestion pointed me in the right direction, so all is good.
  • paqman
    edited December 31, 1969 #12
    Actually, I just realized there's a mistake in afterDataSetFilled() - it will run through both the x and y axis for each dataset, so when the x-axis has larger numbers than the y axis, it won't work properly.

    Is there a way to run getMaximum() on a single axis/component of a dataSet?
  • mwilliams
    edited December 31, 1969 #13
    Yeah. Wrap your getMax code in an if statement that checks the series:

    if (series.eClass().getName().equals("Series 1")){
    dsp = ps.getDataSetProcessor(series.getClass());
    if (dsp.getMaximum(dataSet) > maxValue)
    {
    maxValue = dsp.getMaximum(dataSet);
    }
    }
    Warning No formatter is installed for the format ipb
  • paqman
    edited December 31, 1969 #14
    And one final thing - my chart is a flipped axis chart which seems to be causing some other issues (see attachment). In that chart, I've set the marker line to be at a value of 200 (and am using my workaround code to adjust the axis maximum accordingly). But when I check the maxValue variable in that code, it comes back as 745 and not 142 which makes me think it is looping through what appears to be the x-axis (but in reality is the y-axis in the chart, since the chart is flipped).

    Is there a way to only check the one axis' value? Thanks for all the help on this one
  • mwilliams
    edited December 31, 1969 #15
    Did my last post not help you? In the above code, "Series" would be the x-axis and "Series 1" would be the first y-axis series. When you flip the axis, maybe that is switched. Let me know. If not, if you can recreate the issue with the sample database and post it in here, I'll do some testing.
    Warning No formatter is installed for the format ipb
  • paqman
    edited December 31, 1969 #16
    Sorry, I thought that was referring to the series name - didn't realize it was the eClass() property. I played around with it and checking if it equaled 'Series' was what I needed - this ignored what appeared to be the x-axis in my report and only ran through the y-axis values for all datasets.
  • mwilliams
    edited December 31, 1969 #17
    So, it's good now?
    Warning No formatter is installed for the format ipb
  • paqman
    edited December 31, 1969 #18
    All good - thanks for all the help!
  • mwilliams
    edited December 31, 1969 #19
    You're very welcome!
    Warning No formatter is installed for the format ipb
  • actuser9
    edited December 31, 1969 #20
    Hi,

    I am trying to get the dynamic scale and the marker line based on the data set. X-axis seems to be working based on the series values but Y-axis does not. In the attached report, first chart has the code applied to X-axis scale and the second chart has the OnRender script applied to both X-axis and Y-axis.

    Any idea why the dynamic scale logic is not working for the Y-axis?

    Thanks
    UY
    Warning No formatter is installed for the format ipb
  • mwilliams
    edited October 22, 2012 #21
    When I run your report, it appears to me that the second chart's axis values are set based on the min and max values of the data in both the x and y. Am I not understanding the issue?

    Edit: Is it the scale you're wanting to be fixed?
    Warning No formatter is installed for the format ipb
  • actuser9
    edited December 31, 1969 #22
    Hi Michael,<br />
    <br />
    The Y-axis scale should look into the min and max values of the "Series 1" and get the Y scale. That does not seem to happen with the code below. <br />
    <br />
    <pre class='_prettyXprint _lang-auto _linenums:0'>if (series.getSeriesIdentifier() == "Series 1"){
    //(series.eClass().getName().equals("Series 1")){
    dsp = ps.getDataSetProcessor( series.getClass() );
    //dataset max
    ymax = dsp.getMaximum( dataSet );
    ymin = dsp.getMinimum( dataSet );
    }</pre>
    <br />
    Not sure why the code is not reading the mimimum and maximum values of "Series 1".<br />
    <br />
    Thanks<br />
    UY
    Warning No formatter is installed for the format ipb
  • mwilliams
    edited December 31, 1969 #23
    It is, for me, in the second chart. I'm not sure what you're seeing. Can you show me the screenshot? Maybe I'm not understanding the issue.
    Warning No formatter is installed for the format ipb
  • actuser9
    edited December 31, 1969 #24
    Hi Michael,

    I could resolve this with disabling the grouping on the X-axis series.

    Thanks for all your support.

    Regards
    UY
    Warning No formatter is installed for the format ipb
  • mwilliams
    edited December 31, 1969 #25
    Glad you figured it out! :)
    Warning No formatter is installed for the format ipb
  • <p>Hello,</p>
    <p> </p>
    <p>I am trying to dynamically change the multiplier and suffix on the y-axis at run time.</p>
    <p> </p>
    <p>For example in a bar chart if the min value of the chart is in excess of £1m, to have the scale shown as £1m, £2m,.... but if the min and max values are between £1k and £1m to have the scale shown as £1k, £2k, .....</p>
    <p> </p>
    <p>How might I be able to code that in the  beforeGeneration() function ?</p>
    <p> </p>
    <p>Many thanks</p>
  • <p>What version of BIRT are you using?  Is this commercial BIRT, or open source BIRT?</p>
    Warning No formatter is installed for the format ipb
  • <p>We are using Actuate Birt Designer Professional Version 4.2.3.</p>
    <p> </p>
    <p>Have managed to find a working solution with the following :</p>
    <p> </p>
    <p>yAxis,formatSpecifier.multiplier</p>
    <p>yAxis.formatSpecifier.suffix<br>
     </p>
  • Clement Wong
    Clement Wong E mod
    edited November 3, 2016 #29
    <p>You can also do this in the <em>beforeRendering</em> event:</p>
    <pre class="_prettyXprint">
    beforeRendering: function(options, chart)
    {
    if (chart.getYAxisMax() < 1000000)
        options.yAxis[0].labels.formatter = function() {
                return (this.value / 10000) + ' K';
        };
    else if (chart.getYAxisMax() > 1000000)
        options.yAxis[0].labels.formatter = function() {
                return (this.value / 1000000) + ' M';
        };
    },
    </pre>
    <p>Attached is a sample.</p>
    <p> </p>
    <p>In the future, please specify what version of BIRT you are using so that we can assist you more efficiently.</p>
    Warning No formatter is installed for the format ipb
  • suresh@anumolu
    edited November 29, 2016 #30
    <p>Clement Wong, </p>
    <p> </p>
    <p> </p>
    <p>Qucik question: </p>
    <p>what happens when you have secondary Y-axis. getYAxis just updates on primary -Yaxis. Any help would be appreciated. </p>
    <p> </p>
    <p>Thanks</p>
    <p>Suresh</p>
  • <p><span style="font-family:'courier new', courier, monospace;">chart.getYAxisMax()</span> only works for the first Y axis.</p>
    <p> </p>
    <p>However, if you want to check on the max of the secondary axis, you can get its value via:</p>
    <pre class="_prettyXprint">
    chart.getCore().yAxis[1].max
    </pre>
    Warning No formatter is installed for the format ipb