2

I am displaying normal distribution using JFreeChart, and I change the tick number to standard deviation; but I would also want there to always be 'mean' value in the middle from which ticks emerge. Cross-posted here.

So standard deviation = 2 ; mean = 1

-3 -1  1 3 5

Standard deviation = 5 ; mean = 15

0 5 10 15 20 25 30

JFreeChart.java

public class JFreeChartPanel extends JPanel {
    private final XYPlot plot;
    double mean = 0.0, sd = 1.0;
    XYDataset dataset = initDataset();
    NumberAxis domain = new NumberAxis("Y") {
    @Override
    protected double calculateLowestVisibleTickValue() {
        double lowTickValue = super.calculateLowestVisibleTickValue();
        if (mean % 2 == 1) {
            return lowTickValue + 1;
        } else {
            return lowTickValue;
        }
    }
};
    public JFreeChartPanel(){
        JFreeChart chart = ChartFactory.createXYLineChart(
            "Normal Distribution",
            "X", 
            "PDF", 
            dataset,
            PlotOrientation.VERTICAL,
            false,
            false,
            false
        );
        plot=chart.getXYPlot();
        domain.setAutoRangeStickyZero(false);
        domain.setTickUnit(new NumberTickUnit(sd));
        plot.setDomainAxis(domain);
        final ChartPanel chartPanel = new ChartPanel(chart);
        setLayout(new BorderLayout());
        add(chartPanel);
    }

    private XYDataset initDataset() {
        double minX=mean-(4*sd),maxX=mean+(4*sd);
        Function2D normal = new NormalDistributionFunction2D(mean, sd);
        XYDataset dataset = DatasetUtilities.sampleFunction2D(normal, minX, maxX, 100, "Normal");
        return dataset;
    }

    public double getMean() {
        return mean;
    }

    public void setMean(double mean) {
       this.mean = mean;
       plot.setDataset(initDataset());
    }

    public double getSd() {
        return sd;
    }

    public void setSd(double sd) {
        this.sd = sd;
        domain.setTickUnit(new NumberTickUnit(sd));
        plot.setDataset(initDataset());
    }
}

UI.java

public class UI extends javax.swing.JFrame {

    public UI() {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    private void initComponents() {
      Auto-generated Netbeans GUI COde
    }                     

    public void updateMean()
    {
        try{
            double m = Double.parseDouble(mean.getText());
            jFreeChartPanel.setMean(m);
        }catch(Exception e){
        }
    }
    public void updateSd()
    {
        try{
            double sd = Double.parseDouble(standardDeviation.getText());
            jFreeChartPanel.setSd(sd);
        }catch(Exception e){
        }
    }

    public static void main(String args[]) {
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Windows".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {

        }
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new UI().setVisible(true);
            }
        });
    }

    private javax.swing.JPanel inputPanel;
    private main.JFreeChartPanel jFreeChartPanel;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JToggleButton jToggleButton1;
    private javax.swing.JTextField mean;
    private javax.swing.JLabel meanLabel;
    private javax.swing.JTextField standardDeviation;
    private javax.swing.JLabel standardDeviationLabel;
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Higeath
  • 541
  • 5
  • 20
  • Are you using `DatasetUtilities.sampleFunction2D()` like [this](http://stackoverflow.com/q/40163655/230513)? – trashgod Oct 21 '16 at 22:45
  • @trashgod I have edited the question and added the exact code that I use right now. – Higeath Oct 21 '16 at 23:14
  • Looks right; I'd have to guess the problem is elsewhere; maybe a shadowed variable? – trashgod Oct 22 '16 at 11:25
  • @Trashgod Could you take a look http://pastebin.com/xW8jZKVQ it is this class it is quite short I don't want to overburden the question post. I dont think there is a shadow variable. – Higeath Oct 22 '16 at 17:18
  • To avoid fragmentation, I prefer to keep code on the site; I've adapted your approach to the [original example](http://stackoverflow.com/q/40163655/230513) below. – trashgod Oct 23 '16 at 03:38
  • Cross-posted [here](http://www.jfree.org/forum/viewtopic.php?f=3&t=117695); please edit your question to include a [mcve] that shows your revised approach and results. – trashgod Oct 24 '16 at 00:51
  • @trashgod I have added the code as advised. – Higeath Oct 24 '16 at 11:00
  • I don't see `plot.setDomainAxis(domain)`; see also [*Initial Threads*](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html).. – trashgod Oct 24 '16 at 15:56
  • @trashgod Added plot.setDomainAxis(domain) nothing has changed. Edited code in question as well. – Higeath Oct 24 '16 at 18:05
  • You're reusing the factory's axis, not the custom one; for more specific guidance, please edit your question to include a [mcve] that shows your revised approach. – trashgod Oct 25 '16 at 01:51
  • @trashgod I have updated the code I don't reuse the axis anymore and it is offset. – Higeath Oct 25 '16 at 13:14
  • It works for me; if you post an [mcve], I'll be glad to run it. – trashgod Oct 25 '16 at 15:57
  • @trashgod I've added I believe code that utilizes those guidelines – Higeath Oct 26 '16 at 15:17
  • Not really; your `UI` does not compile; I've elaborated below. – trashgod Oct 26 '16 at 16:06
  • @trashgod here http://pastebin.com/tHQFgLbM whole UI with auto-generated code – Higeath Oct 26 '16 at 16:18
  • Now that you know that the bug is _not_ in `JFreeChartPanel`, you should close this question and open a new question focusing on that problem; include a [mcve]. – trashgod Oct 26 '16 at 16:52
  • @trashgod I'm quite sure it has to be JFreeChartPanel since I have eliminated all lines including JFreeChartPanel from UI class except the adding to JFrame. This happens http://imgur.com/a/vpLN2 with higher mean. – Higeath Oct 26 '16 at 19:20
  • I've elaborated below. – trashgod Oct 27 '16 at 00:19
  • @trashgod The edit helped with that problem, but overriding the method for lowest tick only works when mean sd is 1 or 2 otherwise http://imgur.com/a/OWezy the middle value isn't mean, also with some values http://imgur.com/a/bjqNQ the amount of ticks on the left and on the right to the mean is not equal. – Higeath Oct 27 '16 at 10:22

1 Answers1

2

Starting from this example, I made the following changes, adapted from yours, to get the result illustrated below for µ=15 and σ=5:

import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
…
private double mean = 15.0, sigma = 5.0;
…
private XYDataset initDataset() {
    double minX = mean - (3 * sigma), maxX = mean + (3 * sigma);
    Function2D normal = new NormalDistributionFunction2D(mean, sigma);
    XYDataset dataset = DatasetUtilities.sampleFunction2D(normal, minX, maxX, 100, "Normal");
    return dataset;
}
…
public JFreeChartPanel() {
    …
    plot = chart.getXYPlot();
    NumberAxis domain = (NumberAxis) plot.getDomainAxis();
    domain.setTickUnit(new NumberTickUnit(sigma));
    …
}

µ=15; σ=5

Your other case, µ=1 and σ=2, requires overriding the NumberAxis method calculateLowestVisibleTickValue() to make ticks fall on odd values.

NumberAxis domain = new NumberAxis("Y") {
    @Override
    protected double calculateLowestVisibleTickValue() {
        double lowTickValue = super.calculateLowestVisibleTickValue();
        if (mean % 2 == 1) {
            return lowTickValue + 1;
        } else {
            return lowTickValue;
        }
    }
};
domain.setTickUnit(new NumberTickUnit(sigma));
plot = chart.getXYPlot();
plot.setDomainAxis(domain);

µ=1; σ=2

Why [is] the graph is slightly skewed for mean 3 and sd 1 also for mean 6 sd 2, mean 9 sd 3 and so on; here is a picture showing this.

As discussed here, there's "A flag that affects the size of the margins added to the axis range when the range is determined automatically."

domain.setAutoRangeStickyZero(false);

I've added…code.

Adding and instance of your revision 6 JFreeChartPanel to a JFrame with µ=1 and σ=2 produces the following result:

enter image description here

This happens with higher mean.

This

You can exclude zero from the auto-range.

exclude zero

domain.setAutoRangeIncludesZero(false);
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • each time after I change SD to higher number the number of ticks on X-axis increases. What I want to achieve is to always have in the middle visible tick for mean value and the next tick should be mean + standard deviation. – Higeath Oct 23 '16 at 13:14
  • one last thing I have no idea why the graph is slightly skewed for mean 3 and sd 1 also for mean 6 sd 2, mean 9 sd 3 and so on here is a picture showing this http://imgur.com/a/fDP3M – Higeath Oct 23 '16 at 14:42
  • As suggested [here](https://stackoverflow.com/a/67230096/230513), one approach is "to adjust the relevant axis to flank the desired range." – trashgod Dec 14 '21 at 17:09