Results 1 to 7 of 7
  1. #1
    Join Date
    Mar 2011
    Location
    Parma Italy
    Posts
    88
    Rep Power
    0

    Default Log scale for Y axis in XYChart

    Hi all,

    I would like to set Y axis as log scale, but it seems JavaFX does not have such possibility: searching on the web I have found suggestions about how to do to set as log scale but the cose is written in a completely different way, I never saw before.

    So I am asking if someone can help me to set Y scale as log, below are my simple class to plot data in linear mode

    Java FX Code:
    public class BaseXYChart extends Application {
    
    @Override
        public void start(Stage stage) {
           stage.setTitle("Linear plot");
            
           final CategoryAxis xAxis = new CategoryAxis();
           final NumberAxis yAxis = new NumberAxis(1, 22, 0.5);
            
           yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis){
                @Override
            public String toString(Number object){
                return String.format("%7.2f", object);
            }
        });
    final LineChart<String, Number>lineChart = new LineChart<String, Number>(xAxis, yAxis);
    
           lineChart.setCreateSymbols(false);
           lineChart.setAlternativeRowFillVisible(false);
                   
           XYChart.Series series1 = new XYChart.Series();
            
            series1.getData().add(new XYChart.Data("Jan", 1));
            series1.getData().add(new XYChart.Data("Feb", 1.5));
            series1.getData().add(new XYChart.Data("Mar", 2));
            series1.getData().add(new XYChart.Data("Apr", 2.5));
            series1.getData().add(new XYChart.Data("May", 3));
            series1.getData().add(new XYChart.Data("Jun", 4));
            series1.getData().add(new XYChart.Data("Jul", 6));
            series1.getData().add(new XYChart.Data("Aug", 9));
            series1.getData().add(new XYChart.Data("Sep", 12));
            series1.getData().add(new XYChart.Data("Oct", 15));
            series1.getData().add(new XYChart.Data("Nov", 20));
            series1.getData().add(new XYChart.Data("Dec", 22));
     
            BorderPane pane = new BorderPane();
            pane.setCenter(lineChart);          
            Scene scene = new Scene(pane, 800, 600);
            lineChart.getData().addAll(series1);
             
            stage.setScene(scene);
            stage.show();
        }
    
    public static void main(String[] args) {
            launch(args);
        }    
    }
    and this is what has been proposed here JavaFX chart API and logarithmic scale - dooApp technical blog

    JavaFX provides an impressive chart API that allow to draw a wide range of charts. Unfortunately the only scale that is available for XY charts is a linear implementation. Since the javadoc of the API is sometimes a bit rough it took me some times to get figure out how to get a logarithmic scale. After a discussion on mix.oracle.com it turned out that there where to approaches:

    the first one is to transform your data with the logarithmic function before injecting it into the chart and to adjust the formatting of the labels to "simulate" a logarithmic scale. Since I don't really like the idea of manipulating the data to get the expected representation I prefer the second approach:
    the second one is to provide your own implementation of a logarithmic Axis. Let's see how to do this:
    Extend the ValueAxis class. There are two methods to implement:
    public getDisplayPosition(value: java.lang.Object) : Number
    will do the mapping between a data value and its visual position. For a log axis, the implementation will look like this:


    Java FX Code:
    var logUpperBound: Number = bind Math.log10(upperBound);
    var logLowerBound: Number = bind Math.log10(lowerBound);
    
    override public function getDisplayPosition(arg0: Object): Number {
            def delta = logUpperBound - logLowerBound;
            def deltaV = Math.log10((arg0 as Number)) - logLowerBound;
            if (orientationVertical) {
                return (1 -((deltaV) / delta)) * height;
            } else {
                return ((deltaV) / delta) * width;
            }
        }

    2) protected abstract updateTickMarks() : Void

    will define which tick marks should be displayed. The javadoc does not say much about this function. It looks like the main idea is to update the tickMarks sequence of TickMark. The fields of TickMark are weirdly flagged as public-read package, so in oder to instantiate TickMark for our implementation we first need to define a class extending TickMark, let's say CustomTickMark, and to put it in the package javafx.scene.chart.part in order to be able to set the required fields. After that you just need to update the sequence of tick marks with the marks you want to see on your chart, which can look like this:


    Java FX Code:
    override protected function updateTickMarks(): Void {
            if (tickMarks.size() == 0) {
                for (i in [0..Math.log10(upperBound)-1], j in [1..9]) {
                    var v = j * Math.pow(10, i);
                    insert CustomTickMark {
                        customLabel: "{%6.0f v}"
                        customPosition: getDisplayPosition(v)
                        customValue: v
                    } into tickMarks;
                }
    
            }
        }
    Well I have never saw methods written in such way updateTickMarks(): Void , it seems a for each statment! And var, where does this come from? I know of int, double, float, String, etc. but never saw var as variable declaration.

    I do not know how to set my Y scale using such methods, can someone drop me some lines of code to add log scale to my code?

    Thanks!

    Susie

  2. #2
    DarrylBurke's Avatar
    DarrylBurke is offline Forum Police
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,458
    Rep Power
    20

    Default Re: Log scale for Y axis in XYChart

    Quote Originally Posted by susieferrari View Post
    Well I have never saw methods written in such way updateTickMarks(): Void , it seems a for each statment! And var, where does this come from? I know of int, double, float, String, etc. but never saw var as variable declaration.
    That's JavaFX Script, aka JavaFX 1.x (the last version was I think 1.3.1).

    Take a bash at converting that to Java code. If I'm reading the API correctly, you will want to override Axis#calculateTickValues(double length, Object range) to return an appropriately populated java.util.List<Axis.TickMark<T>>.

    db
    If you're forever cleaning cobwebs, it's time to get rid of the spiders.

  3. #3
    Join Date
    Mar 2011
    Location
    Parma Italy
    Posts
    88
    Rep Power
    0

    Default Re: Log scale for Y axis in XYChart

    Thanks Darryl,

    I do not know anything about JavaFX Script: are the method posted of any help in FX 2.0?

    I have no idea how to use or converting that methods, can you help me?

    Thanks

    Susie

  4. #4
    DarrylBurke's Avatar
    DarrylBurke is offline Forum Police
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,458
    Rep Power
    20

    Default Re: Log scale for Y axis in XYChart

    Quote Originally Posted by susieferrari View Post
    I do not know anything about JavaFX Script
    Search the net; there are tutorials and guides. It's not all that difficult to learn to read the script. You don't need to go in to how to write it.
    I don't know FX Script either, but the program statements are more or less self-explanatory.

    Quote Originally Posted by susieferrari View Post
    I have no idea how to use or converting that methods, can you help me?
    Here's an approximation, typed in Notepad -- may have typos or be otherwise uncompilable when plugged into a custom Axis subclass, and will need a translation of the getDisplayPosition method.
    Java FX Code:
    // instance field: first check whether Axis already has a protected field you can use.
    private List<Axis.TickMark> tickMarks = new ArrayList<Axis.TickMark>();
    
    // override protected function updateTickMarks(): Void {
    @Override
    protected java.util.List<T> calculateTickValues(double length, range) {
    
        if (tickMarks.size() == 0) {
    //            for (i in [0..Math.log10(upperBound)-1], j in [1..9]) {
            for (int i=0; i < Math.log10(upperBound) - 1; i++) {
                for (int j = 1; j <=9; j++) {
    //                var v = j * Math.pow(10, i);
                    double v = j * Math.pow(10, i);
    //                insert CustomTickMark {
                    TickMark tickMark = new TickMark();
    //                customLabel: "{%6.0f v}"
                    tickMark.setLabel(String.format("%6.0f", v));
    //                customPosition: getDisplayPosition(v)
                    tickMark.setPosition(getDisplayPosition(v));
    //                customValue: v
                    tickMark.setValue(v);
    //            } into tickMarks;
                    tickMarks.add(tickMark);
                }
            }
        }
    }
    db
    Last edited by DarrylBurke; 05-29-2012 at 08:08 PM.
    If you're forever cleaning cobwebs, it's time to get rid of the spiders.

  5. #5
    Join Date
    Mar 2011
    Location
    Parma Italy
    Posts
    88
    Rep Power
    0

    Default Re: Log scale for Y axis in XYChart

    Thank you very much, your help always greatly appreciated!

    Susie

  6. #6
    kevinsenechal is offline Member
    Join Date
    Aug 2012
    Posts
    1
    Rep Power
    0

    Default Re: Log scale for Y axis in XYChart

    Hi Susie,

    You could find my article on how to do it here:

    Logarithmic scale strikes back in JavaFX 2.0 - dooApp technical blog

    It should help you ;-)

    Good luck

    Kévin

  7. #7
    Join Date
    Mar 2011
    Location
    Parma Italy
    Posts
    88
    Rep Power
    0

    Default Re: Log scale for Y axis in XYChart

    Hi Kevin,

    thank you very much for the link you've pointed out: this is the perfect answer to my question.

    Great work, it's perfect!

    susie

Similar Threads

  1. Zoom on XYChart + draw freehand
    By susieferrari in forum JavaFX
    Replies: 5
    Last Post: 07-26-2012, 04:54 PM
  2. Add JsplitPanes in XYChart
    By susieferrari in forum JavaFX
    Replies: 4
    Last Post: 07-16-2012, 01:20 PM
  3. Draw text and lines on a XYChart
    By susieferrari in forum JavaFX
    Replies: 2
    Last Post: 04-11-2012, 05:31 PM
  4. The scale() method
    By IamKira in forum Java 2D
    Replies: 0
    Last Post: 07-15-2009, 04:49 PM
  5. How to use Scale in SWT
    By Java Tip in forum SWT Tips
    Replies: 0
    Last Post: 07-07-2008, 05:49 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •