Timing issue with plotting multiple graphs fast
Asked Answered
T

1

1

In the code below I am conducting an experiment for which I need to plot almost 10 graphs per second ( time interval 100) for total of 50. However when I decrease the time interval TIME INTERVAL ( line 120 down to the bottom) from 200 msec to 100 msec the code raises exception below.

I have tired invokeLater etc, yet I am not able to fix this. I pasted here the entire code which generates the graph below. Kindly take a look and let me know what to do. Thanks in advance

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Series index out of bounds
    at org.jfree.data.xy.XYSeriesCollection.getSeries(XYSeriesCollection.java:261)
    at org.jfree.data.xy.XYSeriesCollection.getSeriesKey(XYSeriesCollection.java:303)
    at org.jfree.chart.labels.AbstractXYItemLabelGenerator.createItemArray(AbstractXYItemLabelGenerator.java:268)
    at org.jfree.chart.labels.AbstractXYItemLabelGenerator.generateLabelString(AbstractXYItemLabelGenerator.java:238)
    at org.jfree.chart.labels.StandardXYToolTipGenerator.generateToolTip(StandardXYToolTipGenerator.java:165)
    at org.jfree.chart.renderer.xy.AbstractXYItemRenderer.addEntity(AbstractXYItemRenderer.java:1747)
    at org.jfree.chart.renderer.xy.XYLineAndShapeRenderer.drawSecondaryPass(XYLineAndShapeRenderer.java:1196)
    at org.jfree.chart.renderer.xy.XYLineAndShapeRenderer.drawItem(XYLineAndShapeRenderer.java:918)
    at org.jfree.chart.plot.XYPlot.render(XYPlot.java:3776)
    at org.jfree.chart.plot.XYPlot.draw(XYPlot.java:3337)
    at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1226)
    at org.jfree.chart.ChartPanel.paintComponent(ChartPanel.java:1612)
    at javax.swing.JComponent.paint(JComponent.java:1054)
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5221)
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1508)
    at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1439)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1236)
    at javax.swing.JComponent._paintImmediately(JComponent.java:5169)
    at javax.swing.JComponent.paintImmediately(JComponent.java:4980)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:796)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:784)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:784)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:757)
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:706)
    at javax.swing.RepaintManager.access$1000(RepaintManager.java:62)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1647)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.event.ChartChangeListener;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.util.ShapeUtilities;

public class FastChart extends JFrame {
   private XYSeries [] xySeries ;
   private XYPlot xyPlot;
   private XYSeriesCollection xySeriesCollection;
   private String title;

   private ChartPanel chartPanel;

   public  FastChart(String s) {
      super(s);
      init(s);
   }

   private void init(String s){
      title = s;
      xySeries = new XYSeries[12];
      for (int i = 0; i < xySeries.length; i++) {
         xySeries[i]    = new XYSeries("Plot "+i);  
      }
      xySeriesCollection = new XYSeriesCollection();
      JFreeChart chart = ChartFactory.createScatterPlot(
            title, "X", "Y", xySeriesCollection,
            PlotOrientation.VERTICAL, true, true, false);

      xyPlot =  chart.getXYPlot();
      xyPlot.setDomainCrosshairVisible(true);
      xyPlot.setRangeCrosshairVisible(true);

      chartPanel = createChartPanel(chart);

      add(chartPanel, BorderLayout.CENTER);
      JPanel control = new JPanel();

      add(control, BorderLayout.SOUTH);

      setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
      pack();
      setLocationRelativeTo(null);
      setVisible(true);
   }

   private ChartPanel createChartPanel(JFreeChart chart) {

      XYItemRenderer renderer = xyPlot.getRenderer();
      renderer.setSeriesPaint(0, Color.magenta);
      renderer.setSeriesPaint(1, Color.green);
      renderer.setSeriesPaint(2, Color.blue);
      renderer.setSeriesPaint(4, Color.black);
      renderer.setSeriesPaint(3, Color.yellow);
      Shape cross = ShapeUtilities.createDiagonalCross(3, 0);
      Shape plus = ShapeUtilities.createRegularCross(4,0);

      for (int i = 0; i <=3; i++) {
         renderer.setSeriesShape(0+i,    new Rectangle(-1, -1, 2, 2));
         renderer.setSeriesShape(4+i,    new Ellipse2D.Float(-2F, -2F, 5F, 5F));  
         renderer.setSeriesShape(8+i,    cross);
      }
      // X axis
      NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis();
      domain.setVerticalTickLabels(true);
      // Y axis
      return new ChartPanel(chart);
   }


   public  void plot2d( final int iSeriesN,  final double [] dX,  final double [] dY, final String sT){

      if (dY.length != dX.length){
         throw new IllegalArgumentException("Error! inputs x and y have to be of same size.");
      }
      chartPanel.getChart().removeChangeListener((ChartChangeListener) chartPanel);

      xySeries[iSeriesN].clear();
      xySeriesCollection.removeAllSeries();
      xySeries[iSeriesN]= addXY(iSeriesN,  dX, dY);
      xySeries[iSeriesN].setKey(sT);
      for (int i = 0; i < xySeries.length; i++) {
         xySeriesCollection.addSeries(xySeries[i]);
      }

      chartPanel.getChart().addChangeListener((ChartChangeListener) chartPanel);
      xyPlot.setDataset(xySeriesCollection);
   }

   public XYSeries addXY(final int iSeriesN, final double [] dX, final double [] dY){
      XYSeries series = new XYSeries("Plot ");

      for (int i = 0; i < dX.length; i++) {
         series.add(dX[i], dY[i]);
      }
      return series;
   }
   public  void animatePlot(){
      Thread thread = null;
      thread = new Thread (){
         public void run() {
            final double [] x = new double[1000];
            final double [] y = new double[1000];

            try{    
               for (int k = 1; k < 50; k++) {
                  try {
                     Thread.sleep(200);  //**** TIME INTERVAL *****
                  } catch (InterruptedException e) {
                     e.printStackTrace();
                  }
                  for (int i = 0; i < y.length; i++) {
                     x[i] = i;
                     y[i] = i*i*k;
                  }
                  plot2d(k % 12, x, y,"plot#"+k);
               }
            } catch (Exception e){
               System.out.println();
            }     
         }
      };
      thread.start();
   }

   public static void main(String args[]) {
      FastChart  demo = new FastChart("X Y Plot");
      demo.animatePlot();
   }
}
Ticktock answered 18/11, 2013 at 19:56 Comment(2)
Can you post this in such a way that your graph DOESN'T obscure the important part of your stack trace? Posting the stack trace as text, rather than as a graphic, would be best.Frontality
I just posted the entire stack trace. ThanksTicktock
W
2

You're updating the model from Thread thread. To update on the EDT, use a javax.swing.Timer, as shown here, or SwingWorker, as shown here.

Addendum: To verify the hypothesis, I added the following javax.swing.Timer to init().

Timer t = new Timer(200, new ActionListener() {
    int k = 0;

    @Override
    public void actionPerformed(ActionEvent e) {
        if (k++ < 19) {
            final double[] x = new double[1000];
            final double[] y = new double[1000];
            for (int i = 0; i < y.length; i++) {
                x[i] = i;
                y[i] = i * i * k;
            }
            plot2d(k % 12, x, y, "plot#" + k);
        }
    }
});
t.start();

I also used invokeLater() in main().

EventQueue.invokeLater(new Runnable() {

    @Override
    public void run() {
        FastChart demo = new FastChart("X Y Plot");
    }
});

image

Wench answered 18/11, 2013 at 21:11 Comment(9)
Ooh, very good point. I didn't even notice this, but I think you've hit the nail on the head. This answer would be even better if you could explain why this makes a difference.Frontality
@DavidWallace makes a good point. There's actually three threads racing: the initial thread, the thread started in animatePlot() and the EDT itself that starts near setVisible(). I get a different result each time!Wench
@Wench Thanks-I am trying to implement it using SwingWorker, it is a bit tricky thoughTicktock
@Wench I failed implementing it successfully, Is there anyway to catch those errors or somehow suppress them! For some reason they dont even get caught in try -catch (Exception e) block!Ticktock
As @DavidWallace suggested, I've elaborate above.Wench
Yeah, that's not quite what I meant when I said "explain why this makes a difference", but never mind. I can have a go at explaining it if you like. Would you mind if I edit an explanation into your answer? If you don't want me to, I can post it in an alternative/supplementary answer.Frontality
@David: Please do add an answer giving your perspective, and ping me; I'm collecting testimonials. :-)Wench
@DavidWallace An alternative answer with SwingWorker would be perfect+Ticktock
@Wench I very much appreciate it if you could take a look at this one too: #20086941Ticktock

© 2022 - 2024 — McMap. All rights reserved.