StackedXYAreaRenderer + TimeSeriesCollection => Exception

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
Fabrice
Posts: 13
Joined: Fri Apr 23, 2004 8:37 am
Location: France

StackedXYAreaRenderer + TimeSeriesCollection => Exception

Post by Fabrice » Thu Aug 05, 2004 6:03 pm

I'm trying to use a StackedXYAreaRenderer with a TimeSeriesCollection but an exception is raised :

Code: Select all

java.lang.ClassCastException
	at org.jfree.chart.renderer.StackedXYAreaRenderer.drawItem(StackedXYAreaRenderer.java:307)
	at org.jfree.chart.plot.XYPlot.render(XYPlot.java:2204)
	at org.jfree.chart.plot.XYPlot.draw(XYPlot.java:1809)
	at org.jfree.chart.JFreeChart.draw(JFreeChart.java:905)
	at org.jfree.chart.ChartPanel.paintComponent(ChartPanel.java:987)
The org.jfree.data.TableXYDataset class is expected, but the org.jfree.data.time.TimeSeriesCollection is found.
It seems it's not the only problem with StackedXYAreaRenderer and ClassCastException with the TableXYDataset class
. . (see http://www.jfree.org/phpBB2/viewtopic.php?t=9828, but there's no answer yet...)

If I use a XYAreaRenderer instead of the StackedXYAreaRenderer a graph is drawn (but I don't get the effect I want : stacked areas...)

Here's the code I wrote to reproduce the error (I'm using JFreeChart 0.9.20) :

Code: Select all

package tests;

import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.data.time.*;
import org.jfree.ui.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.*;

public class testFabrice extends ApplicationFrame {
  public static void main(final String[] args) {
    testFabrice demo = new testFabrice();
    demo.pack();
    demo.setVisible(true);
  }
  public testFabrice() {
    super("Chart Problem");
    TimeSeries series1 = new TimeSeries("Series 1", Week.class);
    TimeSeries series2 = new TimeSeries("Series 2", Week.class);
    for (int i = 0; i < 15; i++) {
      series1.add(new Week(i + 1, 2004), Math.random()*50+200);
      series2.add(new Week(i + 1, 2004), Math.random()*50+100);
    }
    TimeSeriesCollection dataset = new TimeSeriesCollection();
    dataset.addSeries(series1);
    dataset.addSeries(series2);

    XYPlot plot = new XYPlot(dataset, new DateAxis(), new NumberAxis(), null);
//    plot.setRenderer(new XYAreaRenderer(XYAreaRenderer.AREA));
    plot.setRenderer(new StackedXYAreaRenderer(StackedXYAreaRenderer.AREA));
    JFreeChart chart = new JFreeChart(plot);

    ChartPanel chartPanel = new ChartPanel(chart);
    chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
    setContentPane(chartPanel);
  }
}
Thanks in advance for your help.

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 » Tue Aug 10, 2004 10:29 am

To create a "stacked" chart using the XYPlot class, you need to use a class that implements the TableXYDataset interface. Unfortunately, TimeSeriesCollection doesn't (DefaultTableXYDataset is the only class in the JFreeChart distribution that does).
David Gilbert
JFreeChart Project Leader

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

Fabrice
Posts: 13
Joined: Fri Apr 23, 2004 8:37 am
Location: France

Post by Fabrice » Tue Aug 10, 2004 5:32 pm

Thank you for your answer.

I can't find a way to make a stacked chart with weeks on the X axis (the DefaultTableXYDataset doesn't seem to make it possible).
Can you help me for this ?

If it's impossible for now, do you plan to create (in a near future) a class that implements the TableXYDataset interface and that allows the use of time (weeks, years...) on the X axis with stacked charts ?

Thank you in advance

hongping
Posts: 14
Joined: Thu Jul 29, 2004 1:32 am

Post by hongping » Tue Aug 10, 2004 6:33 pm

You could try using
org.jfree.data.time.TimeTableXYDataset

which implements the XYTable interface.

TimeTableXYDataset allows you to use org.jfree.data.time.RegularTimePeriod, which has Week and Year and other periods as its subclasses.

Hope this helps.

Fabrice
Posts: 13
Joined: Fri Apr 23, 2004 8:37 am
Location: France

Post by Fabrice » Wed Aug 18, 2004 1:37 pm

Yes, it works fine !
I don't get exceptions any more with the TimeTableXYDataset class.

Thank you for your help.

mlavwilson

Can you post your code for this...

Post by mlavwilson » Mon Mar 21, 2005 8:53 pm

Can you post your code for this, there is no example in the user guide showing stacked time series data...

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 » Mon Mar 21, 2005 11:38 pm

Try this:

Code: Select all

/* ---------------------------
 * StackedXYBarChartDemo2.java
 * ---------------------------
 * (C) Copyright 2005, by Object Refinery Limited.
 *
 */

package demo;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StackedXYBarRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeTableXYDataset;
import org.jfree.data.xy.TableXYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

/**
 * A simple stacked bar chart using time series data.
 */
public class StackedXYBarChartDemo2 extends ApplicationFrame {

    /**
     * Creates a new demo.
     *
     * @param title  the frame title.
     */
    public StackedXYBarChartDemo2(String title) {
        super(title);
        TableXYDataset dataset = createDataset();
        JFreeChart chart = createChart(dataset);
        ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
        setContentPane(chartPanel);
    }
    
    /**
     * Creates a sample dataset.
     * 
     * @return a sample dataset.
     */
    private TableXYDataset createDataset() {
        
        TimeTableXYDataset dataset = new TimeTableXYDataset();
        
        Day d1 = new Day(1, 3, 2005);
        Day d2 = new Day(2, 3, 2005);
        Day d3 = new Day(3, 3, 2005);
        Day d4 = new Day(4, 3, 2005);
        Day d5 = new Day(5, 3, 2005);
        
        dataset.add(d1, 1.0, "Series 1");
        dataset.add(d2, 1.7, "Series 1");
        dataset.add(d3, 2.3, "Series 1");
        dataset.add(d4, 3.7, "Series 1");
        dataset.add(d5, 2.6, "Series 1");

        dataset.add(d1, 3.2, "Series 2");
        dataset.add(d2, 1.1, "Series 2");
        dataset.add(d3, 1.4, "Series 2");
        dataset.add(d4, 2.9, "Series 2");
        dataset.add(d5, 0.6, "Series 2");
        
        return dataset;
        
    }
    
    /**
     * Creates a sample chart.
     * 
     * @param dataset  the dataset for the chart.
     * 
     * @return a sample chart.
     */
    private JFreeChart createChart(TableXYDataset dataset) {

        DateAxis domainAxis = new DateAxis("Date");
        domainAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
        NumberAxis rangeAxis = new NumberAxis("Y");
        StackedXYBarRenderer renderer = new StackedXYBarRenderer(0.10);
        renderer.setDrawBarOutline(false);

        XYPlot plot = new XYPlot(dataset, domainAxis, rangeAxis, renderer);
        JFreeChart chart = new JFreeChart("Stacked XY Bar Chart Demo 2", plot);
        return chart;
        
    }

    /**
     * Starting point for the demonstration application.
     *
     * @param args  ignored.
     */
    public static void main(String[] args) {
        StackedXYBarChartDemo2 demo = new StackedXYBarChartDemo2(
            "Stacked XY Bar Chart Demo 2"
        );
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }

}
David Gilbert
JFreeChart Project Leader

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

mlavwilson
Posts: 3
Joined: Mon Mar 21, 2005 8:53 pm

Post by mlavwilson » Tue Mar 22, 2005 3:10 pm

Code: Select all

package net.mlw.playground.view.message;

import java.util.Date;

import javax.swing.JComponent;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StackedXYBarRenderer;
import org.jfree.data.time.Minute;
import org.jfree.data.time.TimeTableXYDataset;

/**
 */
public class MessageHistoryRenderer3
{
   private TimeTableXYDataset dataset = new TimeTableXYDataset();

   public void add(Date date, long critic, long flash, long immediate, long priority, long routine)
   {
      Minute time = new Minute(date);

      System.out.println("add(" + time + ", " + critic + ", " + flash + ", " + immediate + ", " + priority + ", "
            + routine + ")");

      dataset.add(time, critic, "Critic");
      dataset.add(time, flash, "Flash");
      dataset.add(time, immediate, "Immediate");
      dataset.add(time, priority, "Priority");
      dataset.add(time, routine, "Routine");
   }

   /**
    * Creates a new application.
    */
   public JComponent init()
   {
      add(new Date(), 0, 0, 0, 0, 0);

      DateAxis domainAxis = new DateAxis(null);
      domainAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
      NumberAxis rangeAxis = new NumberAxis("Messages");
      StackedXYBarRenderer renderer = new StackedXYBarRenderer(1);
      renderer.setDrawBarOutline(false);

      XYPlot plot = new XYPlot(dataset, domainAxis, rangeAxis, renderer);
      JFreeChart chart = new JFreeChart(null, plot);
      ChartPanel chartPanel = new ChartPanel(chart);

      return chartPanel;
   }
}
I have used your previous post to produce MessageHistoryRenderer3. I have two problems:
  1. If I do not add some data [see line add(new Date(), 0, 0, 0, 0, 0);] then I get:

    Code: Select all

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageMonitorPanel' defined in class path resource [net/mlw/playground/cmfi/applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: Range(double, double): require lower<=upper.
    java.lang.IllegalArgumentException: Range(double, double): require lower<=upper.
    	at org.jfree.data.Range.<init>(Range.java:79)
    	at org.jfree.data.general.DatasetUtilities.findStackedRangeExtent(DatasetUtilities.java:1376)
    	at org.jfree.chart.renderer.xy.StackedXYBarRenderer.getRangeExtent(StackedXYBarRenderer.java:118)
    	at org.jfree.chart.plot.XYPlot.getDataRange(XYPlot.java:2736)
    	at org.jfree.chart.axis.NumberAxis.autoAdjustRange(NumberAxis.java:350)
    	at org.jfree.chart.axis.NumberAxis.configure(NumberAxis.java:333)
    	at org.jfree.chart.axis.Axis.setPlot(Axis.java:702)
    	at org.jfree.chart.plot.XYPlot.<init>(XYPlot.java:419)
    	at net.mlw.playground.cmfi.view.message.MessageHistoryRenderer3.init(MessageHistoryRenderer3.java:50)
    	at net.mlw.playground.cmfi.view.message.MessageMonitorPanel.init(MessageMonitorPanel.java:84)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:324)
    Which, I guess is ok, I can throw zeros in to prevent this.
  1. My real problem is that no chart is generated. I am calling, and need to call add(Date date, long critic, long flash, long immediate, long priority, long routine) after the chart is rendered. This will be updating in real time.
Thank you for your help,

Matthew Wilson

mlavwilson
Posts: 3
Joined: Mon Mar 21, 2005 8:53 pm

Developers Guide

Post by mlavwilson » Tue Mar 22, 2005 3:26 pm

I would like to see a topic on charting stacked time series in the Developers Guide :D

On a more personal note, good job on this open source effort. I know the effort that is needed to get a project to the point it is now, Congrats.

Matthew Wilson
-http://valuelist.sourceforge.net

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 » Tue Mar 22, 2005 5:40 pm

Are you using the latest release? There was a bug fix for the calculation of the "stacked bounds" for datasets, that might resolve the exception above.

I modified the MemoryUsageDemo example to show dynamically updated stacked bars, maybe this helps a little:

Code: Select all

/* -------------------------------
 * DynamicStackedBarChartDemo.java
 * -------------------------------
 * (C) Copyright 2005, by Object Refinery Limited.
 */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StackedXYBarRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.time.Hour;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeTableXYDataset;
import org.jfree.ui.RectangleInsets;

/**
 * A demo application showing a dynamically updated chart that displays the current JVM memory
 * usage.
 */
public class DynamicStackedBarChartDemo extends JPanel {

    private TimeTableXYDataset dataset;

    private RegularTimePeriod t = new Hour();
    
    /**
     * Creates a new application.
     * 
     * @param historyCount  the history count (in hours).
     */
    public DynamicStackedBarChartDemo(int historyCount) {

        super(new BorderLayout());

		this.dataset = new TimeTableXYDataset();
        DateAxis domain = new DateAxis("Time");
        NumberAxis range = new NumberAxis("Memory");
        domain.setTickLabelFont(new Font("SansSerif", Font.PLAIN, 12));
        range.setTickLabelFont(new Font("SansSerif", Font.PLAIN, 12));
        domain.setLabelFont(new Font("SansSerif", Font.PLAIN, 14));
        range.setLabelFont(new Font("SansSerif", Font.PLAIN, 14));

        XYItemRenderer renderer = new StackedXYBarRenderer();
        renderer.setSeriesPaint(0, Color.red);
        renderer.setSeriesPaint(1, Color.green);
        XYPlot plot = new XYPlot(this.dataset, domain, range, renderer);
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);
        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
        domain.setAutoRange(true);
        domain.setLowerMargin(0.0);
        domain.setUpperMargin(0.0);
        domain.setFixedAutoRange(24 * 60 * 60 * 1000L);
        domain.setTickLabelsVisible(true);

        range.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        JFreeChart chart = new JFreeChart(
            "JVM Memory Usage", 
            new Font("SansSerif", Font.BOLD, 24),
            plot, 
            true
        );
        chart.setBackgroundPaint(Color.white);
        ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createEmptyBorder(4, 4, 4, 4),
            BorderFactory.createLineBorder(Color.black))
        );
        add(chartPanel);

    }

    /**
     * Adds an observation to the 'total memory' time series.
     *
     * @param y  the total memory used.
     */
    private void addObservations(double v1, double v2) {
        this.dataset.add(this.t, v1, "Used");
        this.dataset.add(this.t, v2, "Free");
        this.t = this.t.next();
    }

    /**
     * The data generator.
     */
    class DataGenerator extends Timer implements ActionListener {

        /**
         * Constructor.
         * 
         * @param interval  the interval (in milliseconds)
         */
        DataGenerator(int interval) {
            super(interval, null);
            addActionListener(this);
        }

        /**
         * Adds a new free/total memory reading to the dataset.
         *
         * @param event  the action event.
         */
        public void actionPerformed(ActionEvent event) {
            long f = Runtime.getRuntime().freeMemory();
            long t = Runtime.getRuntime().totalMemory();
            addObservations(t - f, f);
        }

    }

    /**
     * Entry point for the sample application.
     *
     * @param args  ignored.
     */
    public static void main(String[] args) {

        JFrame frame = new JFrame("Dynamic Stacked Bar Chart Demo");
        DynamicStackedBarChartDemo panel = new DynamicStackedBarChartDemo(24);
        frame.getContentPane().add(panel, BorderLayout.CENTER);
        frame.setBounds(200, 120, 600, 280);
        frame.setVisible(true);
        panel.new DataGenerator(100).start();

        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }

}
David Gilbert
JFreeChart Project Leader

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

Locked