Dynamic Y-axis scale

edited December 31, 1969 in Designing Analytics Reports
Hello BIRT Experts,



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.



I've made some progress with the following script (note that the y and x axes are inverted in this report):



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);
}
}



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?



Thanks for your help



David
«1

Comments

  • mwilliamsmwilliams BIRT Guru
    edited December 31, 1969
    What is your BIRT version? I'll check it out in your version.

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: [email protected]

  • edited December 31, 1969
    We are using 2.6.1 - thanks for the help!
  • mwilliamsmwilliams BIRT Guru
    edited December 31, 1969
    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.

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: [email protected]

  • mwilliamsmwilliams BIRT Guru
    edited December 31, 1969
    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?

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: [email protected]

  • edited December 31, 1969
    Yes, good point. I can add a script to the dataset to determine the maximum value, and then put that into a global variable.
  • mwilliamsmwilliams BIRT Guru
    edited December 31, 1969
    Awesome. Let me know if you have any issues with this. Let us know whenever you have questions! :)

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: [email protected]

  • edited December 31, 1969
    Will definitely have more questions in the near future! :) Thanks guys
  • edited December 31, 1969
    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.



    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);
    }
    }
  • mwilliamsmwilliams BIRT Guru
    edited December 31, 1969
    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!

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: [email protected]

  • edited December 31, 1969
    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.
  • edited December 31, 1969
    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?
  • mwilliamsmwilliams BIRT Guru
    edited December 31, 1969
    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);
    }
    }

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: [email protected]

  • edited December 31, 1969
    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
  • mwilliamsmwilliams BIRT Guru
    edited December 31, 1969
    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.

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: [email protected]

  • edited December 31, 1969
    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.
  • mwilliamsmwilliams BIRT Guru
    edited December 31, 1969
    So, it's good now?

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: [email protected]

  • edited December 31, 1969
    All good - thanks for all the help!
  • mwilliamsmwilliams BIRT Guru
    edited December 31, 1969
    You're very welcome!

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: mwilliams.s[email protected]

  • edited December 31, 1969
    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

    Thanks,

    UY

  • mwilliamsmwilliams BIRT Guru
    edited October 22, 2012
    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?

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: [email protected]

  • edited December 31, 1969
    Hi Michael,



    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.



    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 );
    }



    Not sure why the code is not reading the mimimum and maximum values of "Series 1".



    Thanks

    UY

    Thanks,

    UY

  • mwilliamsmwilliams BIRT Guru
    edited December 31, 1969
    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.

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: [email protected]

  • edited December 31, 1969
    Hi Michael,

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

    Thanks for all your support.

    Regards
    UY

    Thanks,

    UY

  • mwilliamsmwilliams BIRT Guru
    edited December 31, 1969
    Glad you figured it out! :)

    Regards,

    Michael Williams

    eSignLive Evangelism & Community Manager | eSignLive by VASCO
     
    Find me on:
    Twitter
    Facebook
    Blog

    LinkedIn

    eSignLive Developer Community
     
    Email me:
    Google: [email protected]

  • Hello,


     


    I am trying to dynamically change the multiplier and suffix on the y-axis at run time.


     


    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, .....


     


    How might I be able to code that in the  beforeGeneration() function ?


     


    Many thanks


  • What version of BIRT are you using?  Is this commercial BIRT, or open source BIRT?


    Clement Wong
    Principal Analytics Architect

    OpenText Corporation
    http://www.actuate.com | http://www.opentext.com

  • We are using Actuate Birt Designer Professional Version 4.2.3.


     


    Have managed to find a working solution with the following :


     


    yAxis,formatSpecifier.multiplier


    yAxis.formatSpecifier.suffix

     


  • Clement WongClement Wong EM, Member mod
    edited November 3, 2016

    You can also do this in the beforeRendering event:



    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';
        };
    },

    Attached is a sample.


     


    In the future, please specify what version of BIRT you are using so that we can assist you more efficiently.


    Clement Wong
    Principal Analytics Architect

    OpenText Corporation
    http://www.actuate.com | http://www.opentext.com

  • edited November 29, 2016

    Clement Wong, 


     


     


    Qucik question: 


    what happens when you have secondary Y-axis. getYAxis just updates on primary -Yaxis. Any help would be appreciated. 


     


    Thanks


    Suresh


  • chart.getYAxisMax() only works for the first Y axis.


     


    However, if you want to check on the max of the secondary axis, you can get its value via:



    chart.getCore().yAxis[1].max

    Clement Wong
    Principal Analytics Architect

    OpenText Corporation
    http://www.actuate.com | http://www.opentext.com

Sign In or Register to comment.