DynamicDataDemo2

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
PollerJava
Posts: 81
Joined: Wed Jul 25, 2007 10:40 am

DynamicDataDemo2

Post by PollerJava » Wed Jan 28, 2009 11:37 am

Hello,

I have a question to the little runnable application at the bottom,
So if a button is pressed, than a RegularTimePeriode and a Value is added to the serie.
If I press the button for instance 1 million times than than 1 million periods and values are added but only a trickle of the data is shown.

Is there any possibility to remove data when it isn't shown, so in the way: one data is added at the right hand of the serie and one data is removed at the left hand.

Thanks a lot,
Poller

Code: Select all

package javaapplication28;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.DefaultXYItemRenderer;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RectangleInsets;
import org.jfree.ui.RefineryUtilities;

public class DynamicDataDemo2 extends ApplicationFrame {

    static class DemoPanel extends JPanel implements ActionListener
        {
        private TimeSeries series1;
        private TimeSeries series2;
        private double lastValue1 = 100.0;
        private double lastValue2 = 500.0;

        public DemoPanel() {
            super(new BorderLayout());
            this.series1 = new TimeSeries("Random 1", Millisecond.class);
            this.series2 = new TimeSeries("Random 2", Millisecond.class);
            TimeSeriesCollection dataset1 = new TimeSeriesCollection(
                    this.series1);
            TimeSeriesCollection dataset2 = new TimeSeriesCollection(
                    this.series2);
            JFreeChart chart = ChartFactory.createTimeSeriesChart(
                    "Dynamic Data Demo 2", "Time", "Value", dataset1,
                    true, true, false);
            chart.setBackgroundPaint(Color.white);

            XYPlot plot = (XYPlot) chart.getPlot();
            plot.setBackgroundPaint(Color.lightGray);
            plot.setDomainGridlinePaint(Color.white);
            plot.setRangeGridlinePaint(Color.white);
            plot.setAxisOffset(new RectangleInsets(4, 4, 4, 4));
            ValueAxis axis = plot.getDomainAxis();
            axis.setAutoRange(true);
            axis.setFixedAutoRange(10000.0);  // 10 seconds

            plot.setDataset(1, dataset2);
            NumberAxis rangeAxis2 = new NumberAxis("Range Axis 2");
            rangeAxis2.setAutoRangeIncludesZero(false);
            plot.setRenderer(1, new DefaultXYItemRenderer());
            plot.setRangeAxis(1, rangeAxis2);
            plot.mapDatasetToRangeAxis(1, 1);

            ChartPanel chartPanel = new ChartPanel(chart);
            add(chartPanel);

            JButton button1 = new JButton("Add To Series 1");
            button1.setActionCommand("ADD_DATA_1");
            button1.addActionListener(this);

            JButton button2 = new JButton("Add To Series 2");
            button2.setActionCommand("ADD_DATA_2");
            button2.addActionListener(this);

            JButton button3 = new JButton("Add To Both");
            button3.setActionCommand("ADD_BOTH");
            button3.addActionListener(this);

            JPanel buttonPanel = new JPanel(new FlowLayout());
            buttonPanel.setBackground(Color.white);
            buttonPanel.add(button1);
            buttonPanel.add(button2);
            buttonPanel.add(button3);

            add(buttonPanel, BorderLayout.SOUTH);
            chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
       }

        public void actionPerformed(ActionEvent e) {
            boolean add1 = false;
            boolean add2 = false;
            if (e.getActionCommand().equals("ADD_DATA_1")) {
                add1 = true;
            }
            else if (e.getActionCommand().equals("ADD_DATA_2")) {
                add2 = true;
            }
            else if (e.getActionCommand().equals("ADD_BOTH")) {
                add1 = true;
                add2 = true;
            }
            if (add1) {
                double factor = 0.90 + 0.2 * Math.random();
                this.lastValue1 = this.lastValue1 * factor;
                this.series1.add(new Millisecond(), this.lastValue1);
                System.out.println("Amount of the Items in series1: " + this.series1.getItemCount());
                }
            if (add2) {
                double factor = 0.90 + 0.2 * Math.random();
                this.lastValue2 = this.lastValue2 * factor;
                this.series2.add(new Millisecond(), this.lastValue2);
            }
        }

    }

    public DynamicDataDemo2(String title) {
        super(title);
        setContentPane(new DemoPanel());
    }

    public static JPanel createDemoPanel() {
        return new DynamicDataDemo2.DemoPanel();
    }

    public static void main(String[] args) {

        DynamicDataDemo2 demo = new DynamicDataDemo2(
                "JFreeChart: DynamicDataDemo2.java");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);

    }
}


PollerJava
Posts: 81
Joined: Wed Jul 25, 2007 10:40 am

Post by PollerJava » Thu Jan 29, 2009 7:37 am

So I tested the application over night by adding a lot of records (time, value).
With 248340 records I got a Java heap space OutOfMemory,

So has anyone an idea what can I do?

Thanks,

mkivinie
Posts: 51
Joined: Wed Jul 06, 2005 8:35 am

Post by mkivinie » Thu Jan 29, 2009 9:09 am

Check the TimeSeries API.
You can either set maximum item age with setMaximumItemAge (older will be automatically removed) or maximum item count with setMaximumItemCount.

http://www.jfree.org/jfreechart/api/jav ... eries.html

That might help you.

PollerJava
Posts: 81
Joined: Wed Jul 25, 2007 10:40 am

Post by PollerJava » Thu Jan 29, 2009 10:04 am

mkivinie wrote:Check the TimeSeries API.
You can either set maximum item age with setMaximumItemAge (older will be automatically removed) or maximum item count with setMaximumItemCount.

That might help you.

Hi,

series1.setMaximumItemCount(400); works but
series1.setMaximumItemAge((long)xAxis.getLowerBound());
has no effect on the series.

That's my codefragment:

Code: Select all

else if (e.getActionCommand().equals("ADD_DATA_2")) {
                Thread th = new Thread() {
                    @Override
                    public void run() {
                        while(true) {
                            series1.removeChangeListener(demoPanel);
                            double factor = 0.90 + 0.2 * Math.random();
                            lastValue1 = lastValue1 * factor;
                            series1.addOrUpdate(new Millisecond(), lastValue1);
                            double factor1 = 0.90 + 0.2 * Math.random();
                            lastValue2 = lastValue2 * factor1;
                            series2.addOrUpdate(new Millisecond(), lastValue2);
                            try {
                                Thread.sleep(10);
                                } 
                            catch (InterruptedException ex) {
                                System.out.println("Ausnahme: " + ex);
                                }

                            ValueAxis xAxis = plot.getDomainAxis();                                                                               
                            series1.setMaximumItemAge((long)xAxis.getLowerBound() + 4*1000);
                            //series1.setMaximumItemCount(400);
                            series1.removeAgedItems(true);
                            series1.removeAgedItems((long)xAxis.getLowerBound(), true);
                            System.out.println("Amount of the Items in series1: " + series1.getItemCount() + ", " + new Timestamp((long)xAxis.getLowerBound() + 4*1000));
                            //series1.clear();
                            }
                        }
                    };
                th.start();
            }

mkivinie
Posts: 51
Joined: Wed Jul 06, 2005 8:35 am

Post by mkivinie » Thu Jan 29, 2009 12:52 pm

I have never used this feature personally, but I think you got the setMaximumItemAge behaviour wrong.

Now you are setting the maximum life-time of the items (i.e. the relative difference to the most recent item) to be the timestamp that happens to be the lower bound of you chart. Now if this is a real-time view --> you are allowing items to live roughly 39 years (as zero time is 1970-01-01)

So, instead you probably wish to set the maximum age to be the viewable range.
Something like

Code: Select all

series1.setMaximumItemAge((long)xAxis.getRange().getLength());

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Thu Jan 29, 2009 2:14 pm

The "age" is specified as a number of time periods - the length of 1 time period varies according to the type of data in the time series (daily, hourly, monthly etc).
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

Locked