List of usage examples for org.jfree.data.time TimeSeries add
public void add(TimeSeriesDataItem item)
From source file:org.geoserver.monitor.web.ActivityChartBasePanel.java
BufferedDynamicImageResource queryAndRenderChart(Monitor monitor, Date[] range) { Query q = new Query(); q.properties("startTime").between(range[0], range[1]); DataGatherer gatherer = new DataGatherer(); monitor.query(q, gatherer);//from w w w . j ava 2 s . c om HashMap<RegularTimePeriod, Integer> data = gatherer.getData(); Class timeUnitClass = getTimePeriod(range[0]).getClass(); TimeSeries series = new TimeSeries("foo", timeUnitClass); for (Map.Entry<RegularTimePeriod, Integer> d : data.entrySet()) { series.add(new TimeSeriesDataItem(d.getKey(), d.getValue())); } TimeSeriesCollection dataset = new TimeSeriesCollection(series); final JFreeChart chart = createTimeSeriesChart(getChartTitle(range), "Time (" + timeUnitClass.getSimpleName() + ")", "Requests", dataset); BufferedDynamicImageResource resource = new BufferedDynamicImageResource(); resource.setImage(chart.createBufferedImage(700, 500)); return resource; }
From source file:se.six.jmeter.visualizer.statagg.StatAggVisualizer.java
private void addValue(TimeSeries ts, TimeSeriesDataItem item) { if (item != null) { try {// w w w .j a v a2 s .co m ts.add(item); } catch (Exception e) { System.out.println("addValue(..): Error at: " + new Date()); e.printStackTrace(); } } }
From source file:edu.jhuapl.graphs.jfreechart.JFreeChartTimeSeriesGraphSource.java
private TimeSeries buildTimeSeries(TimeSeriesInterface series, int i) throws GraphException { Map<String, Object> metadata = series.getMetadata(); TimeResolution resolution;//from w ww .j a v a 2 s . c o m if (metadata.get(GraphSource.SERIES_TIME_RESOLUTION) instanceof TimeResolution) { resolution = (TimeResolution) metadata.get(GraphSource.SERIES_TIME_RESOLUTION); } else { resolution = DEFAULT_RESOLUTION; } String title = null; if (metadata.get(GraphSource.SERIES_TITLE) instanceof String) { title = (String) metadata.get(GraphSource.SERIES_TITLE); } else { title = "series" + i; } // This method will throw a graph exception if multiple points with the same resolved date are // present checkSeries(series, resolution); TimeSeries s = new TimeSeries(title); for (TimePointInterface point : series.getPoints()) { s.add(new MetadataTimeSeriesDataItem(makePeriod(point, resolution), point.getValue(), point.getMetadata())); } return s; }
From source file:Debrief.Tools.FilterOperations.ShowTimeVariablePlot3.java
/** * Collate the data points to plot/* w w w . j a v a2 s. c o m*/ * * @param primaryTrack * the primary track * @param myOperation * the calculation we're making * @param theTracks * the selected set of tracks * @param start_time * the start time selected * @param end_time * the end time selected * @param provider * the provider of the time offset used when plotting time-zero data * @return the dataset to plot * @see toteCalculation#isWrappableData * @see toteCalculation#calculate(Watchable primary,Watchable * secondary,HiResDate thisTime) * @see Debrief.Tools.FilterOperations.ShowTimeVariablePlot3.CalculationHolder#isARelativeCalculation * @see WatchableList#getItemsBetween(HiResDate start,HiResDate end) * @see TimeSeriesCollection#addSeries(BasicTimeSeries series) */ public static AbstractSeriesDataset getDataSeries(final WatchableList primaryTrack, final CalculationHolder myOperation, final Vector<WatchableList> theTracks, final HiResDate start_time, final HiResDate end_time, final ColouredDataItem.OffsetProvider provider) { final toteCalculation theCalculation = myOperation._theCalc; AbstractSeriesDataset theSeriesCollection = null; // ok, now collate the data VersatileSeriesAdder theAdder = null; // sort out the adder for what we're doing if (HiResDate.inHiResProcessingMode()) { theSeriesCollection = new TimeSeriesCollection(); theAdder = new VersatileSeriesAdder() { public void add(final Series thisSeries, final HiResDate theTime, final double data, final Color thisColor, final boolean connectToPrevious, final ColouredDataItem.OffsetProvider provider1) { // HI-RES NOT DONE - FixedMillisecond should be converted // some-how to // FixedMicroSecond final TimeSeriesDataItem newItem = new ColouredDataItem( new FixedMillisecond((long) (theTime.getMicros() / 1000d)), data, thisColor, connectToPrevious, provider1); // To change body of implemented methods use File | Settings // | File // Templates. final TimeSeries theSeries = (TimeSeries) thisSeries; theSeries.add(newItem); } public void addSeries(final AbstractSeriesDataset collection, final Series thisSeries, final Color defaultColor) { final TimeSeriesCollection coll = (TimeSeriesCollection) collection; coll.addSeries((TimeSeries) thisSeries); } }; } else { theSeriesCollection = new TimeSeriesCollection(); // right, just working with normal dates theAdder = new VersatileSeriesAdder() { public void add(final Series thisSeries, final HiResDate theTime, final double data, final Color thisColor, final boolean connectToPrevious, final ColouredDataItem.OffsetProvider provider1) { // HI-RES NOT DONE - FixedMillisecond should be converted // some-how to // FixedMicroSecond final ColouredDataItem newItem = new ColouredDataItem( new FixedMillisecond(theTime.getDate().getTime()), data, thisColor, connectToPrevious, provider1); // To change body of implemented methods use File | Settings // | File // Templates. final TimeSeries theSeries = (TimeSeries) thisSeries; theSeries.add(newItem); } public void addSeries(final AbstractSeriesDataset collection, final Series thisSeries, final Color defaultColor) { final TimeSeriesCollection coll = (TimeSeriesCollection) collection; coll.addSeries((TimeSeries) thisSeries); } }; } // calculate the data variables for our tracks final Enumeration<WatchableList> iter = theTracks.elements(); while (iter.hasMoreElements()) { final WatchableList thisSecondaryTrack = (WatchableList) iter.nextElement(); // is this a relative calculation? if (myOperation.isARelativeCalculation()) { // yes, but we don't bother with the primary track, see if this // is it if (thisSecondaryTrack == primaryTrack) { // just double check that we have primary data final Collection<Editable> ss = thisSecondaryTrack.getItemsBetween(start_time, end_time); if (ss == null) { Application.logError2(ToolParent.WARNING, "Insufficient points found in primary track." + "\nPlease check coverage of time controller bars", null); return null; } // drop out, and wait for the next cycle continue; } } // //////////////////////////////////////////////////// // step through the track // final Collection<Editable> ss = thisSecondaryTrack.getItemsBetween(start_time, end_time); // indicator for whether we join this data point to the previous one boolean connectToPrevious = false; // have we found any?. Hey, listen here. The "getItemsBetween" // method may return data items, but we may still not be able to do the calc // (such as if we have "NaN" for depth). So we still do a sanity check // at the end of this method to stop us adding empty data series to the collection. if (ss == null) { Application.logError2(ToolParent.WARNING, "Insufficient points found in primary track." + "\nPlease check coverage of time controller bars", null); return null; } else { // remember the default color for this series Color seriesColor; // ok, now collate the data Series thisSeries = null; // sort out the adder for what we're doing if (HiResDate.inHiResProcessingMode()) { thisSeries = new XYSeries(thisSecondaryTrack.getName()); } else { thisSeries = new TimeSeries(thisSecondaryTrack.getName()); } seriesColor = thisSecondaryTrack.getColor(); // split into separate processing here, depending on where we're // looking // at a relative calculation if (myOperation.isARelativeCalculation()) { // yes, it is a relative calculation. // Find out if it's a special case (where we don't have time // data) if (thisSecondaryTrack.getStartDTG() == null) { // do we have any primary data to fall back on (to // decide the times // for // data points) if (primaryTrack.getStartDTG() == null) { // //////////////////////////////////////////////// // CASE 1 - neither track has time data, relative // calc // //////////////////////////////////////////////// // so, we don't have primary or secondary data. // produce data // values at the start and end of the track // produce data points at the primary track // locations final Iterator<Editable> it = ss.iterator(); final Watchable theSecondaryPoint = (Watchable) it.next(); // get an iterator for the primary track final Collection<Editable> primaryPoints = primaryTrack.getItemsBetween(start_time, end_time); // do we have any primary data in this period if (primaryPoints != null) { final Iterator<Editable> throughPrimary = primaryPoints.iterator(); final Watchable thisPrimary = (Watchable) throughPrimary.next(); // ok, create the series with it's two points in produceTwoPointDataSeries(theCalculation, thisPrimary, theSecondaryPoint, thisSeries, start_time, end_time, provider, theAdder); } } else { // //////////////////////////////////////////////// // CASE 2 - secondary track has time data, relative // calc // //////////////////////////////////////////////// // so, we do have time data for the secondary track, // but not on // the primary track // therefore we produce data points at the primary // track locations final Watchable[] theSecondaryPoints = thisSecondaryTrack.getNearestTo(start_time); final Watchable theSecondaryPoint = theSecondaryPoints[0]; final Color thisColor = theSecondaryPoint.getColor(); // get an iterator for the primary track final Collection<Editable> primaryPoints = primaryTrack.getItemsBetween(start_time, end_time); if (primaryPoints != null) { final Iterator<Editable> throughPrimary = primaryPoints.iterator(); while (throughPrimary.hasNext()) { final Watchable thisPrimary = (Watchable) throughPrimary.next(); final HiResDate currentTime = thisPrimary.getTime(); // and add the new data point (if we have // to) connectToPrevious = createDataPoint(theCalculation, thisPrimary, theSecondaryPoint, currentTime, connectToPrevious, thisColor, thisSeries, provider, theAdder); } // stepping through the primary track } // whether we have primary points } } else // whether we have DTG data { // //////////////////////////////////////////////// // CASE 3 - both tracks have time data, relative calc // //////////////////////////////////////////////// // yes, we do have DTG data for this track - hooray! // ok, step through the list final Iterator<Editable> it = ss.iterator(); // remember the last point - used to check if we're // passing through // zero degs double lastSecondaryValue = Double.NaN; // we we're // using NaN but // it // was failing the equality // test HiResDate lastTime = null; throughThisTrack: while (it.hasNext()) { final Watchable thisSecondary = (Watchable) it.next(); final Color thisColor = thisSecondary.getColor(); // what's the current time? final HiResDate currentTime = thisSecondary.getTime(); // is this fix visible? if (thisSecondary.getVisible()) { // the point on the primary track we work with Watchable thisPrimary = null; // find the fix on the primary track which is // nearest in // time to this one (if we need to) Watchable[] nearList; // temp switch on interpolation Boolean oldInterp = null; if (primaryTrack instanceof ISecondaryTrack) { final ISecondaryTrack tw = (ISecondaryTrack) primaryTrack; oldInterp = tw.getInterpolatePoints(); tw.setInterpolatePoints(true); } // find it's nearest point on the primary track nearList = primaryTrack.getNearestTo(currentTime); // and restore the interpolate points setting if (oldInterp != null) { final ISecondaryTrack tw = (ISecondaryTrack) primaryTrack; tw.setInterpolatePoints(oldInterp.booleanValue()); } // yes. right, we only perform a calc if we have // primary data // for this point if (nearList.length == 0) { // remember that the next point doesn't // connect to it's // previous one // since we want to show the gap represented // by this datum connectToPrevious = false; // drop out, and wait for the next cycle continue throughThisTrack; } else { thisPrimary = nearList[0]; } // //////////////////////////////////////////////// // NOW PUT IN BIT TO WRAP THROUGH ZERO WHERE // APPLICABLE // //////////////////////////////////////////////// // produce the new calculated value final double thisVal = theCalculation.calculate(thisSecondary, thisPrimary, currentTime); // SPECIAL HANDLING - do we need to check if // this data passes // through 360 degs? if (theCalculation.isWrappableData()) { // add extra points, if we need to connectToPrevious = insertWrappingPoints(theCalculation, lastSecondaryValue, thisVal, lastTime, currentTime, thisColor, thisSeries, connectToPrevious, provider, theAdder, myOperation._clipMax); } // //////////////////////////////////////////////// // THANK YOU, WE'RE PLEASED TO RETURN YOU TO // YOUR NORMAL PROGRAM // //////////////////////////////////////////////// // and add the new data point (if we have to) connectToPrevious = createDataPoint(theCalculation, thisPrimary, thisSecondary, currentTime, connectToPrevious, thisColor, thisSeries, provider, theAdder); lastSecondaryValue = thisVal; lastTime = currentTime; } // whether this point is visible } // stepping through this track } // whether we have DTG data } else { // so, this is an absolute calculation - we don't need to // worry about // the primry // track // do we have time data for this secondary track? if (thisSecondaryTrack.getStartDTG() == null) { // //////////////////////////////////////////////// // CASE 4 - no time data, non-relative calculation // //////////////////////////////////////////////// // it's ok. It we don't have time related data for this // point we // just create // data points for it at the start & end of the track // ok, create the series with it's two points in // ok, step through the list final Iterator<Editable> it = ss.iterator(); final Watchable thisSecondary = (Watchable) it.next(); // and produceTwoPointDataSeries(theCalculation, null, thisSecondary, thisSeries, start_time, end_time, provider, theAdder); } else { // //////////////////////////////////////////////// // CASE 5 - with time data, non-relative calculation // //////////////////////////////////////////////// // ok, step through the list final Iterator<Editable> it = ss.iterator(); // remember the last point - used to check if we're // passing through // zero degs double lastSecondaryValue = Double.NaN; // we we're // using NaN but // it // was failing the equality // test HiResDate lastTime = null; while (it.hasNext()) { final Watchable thisSecondary = (Watchable) it.next(); // / get the colour final Color thisColor = thisSecondary.getColor(); // what's the time of this data point? final HiResDate currentTime = thisSecondary.getTime(); // produce the new calculated value final double thisVal = theCalculation.calculate(thisSecondary, null, currentTime); // SPECIAL HANDLING - do we need to check if this // data passes // through 360 degs? if (theCalculation.isWrappableData()) { // add extra points, if we need to connectToPrevious = insertWrappingPoints(theCalculation, lastSecondaryValue, thisVal, lastTime, currentTime, thisColor, thisSeries, connectToPrevious, provider, theAdder, myOperation._clipMax); } // is this fix visible? if (thisSecondary.getVisible()) { // the point on the primary track we work with final Watchable thisPrimary = null; // and add the new data point (if we have to) connectToPrevious = createDataPoint(theCalculation, thisPrimary, thisSecondary, currentTime, connectToPrevious, thisColor, thisSeries, provider, theAdder); lastSecondaryValue = thisVal; lastTime = new HiResDate(currentTime); } // whether this point is visible } // stepping through this secondary collection } // whether there was time-related data for this track } // whether this was a relative calculation // if the series if empty, set it to null, rather than create // one of // empty length if (thisSeries instanceof XYSeries) { final XYSeries ser = (XYSeries) thisSeries; if (ser.getItemCount() == 0) thisSeries = null; } else if (thisSeries instanceof TimeSeries) { final TimeSeries ser = (TimeSeries) thisSeries; if (ser.getItemCount() == 0) thisSeries = null; } // did we find anything? if (thisSeries != null) { theAdder.addSeries(theSeriesCollection, thisSeries, seriesColor); } } // if this collection actually had data } // looping through the tracks if (theSeriesCollection.getSeriesCount() == 0) theSeriesCollection = null; return theSeriesCollection; }
From source file:org.jfree.data.time.junit.TimeSeriesTest.java
/** * Create a TimeSeriesDataItem, add it to a TimeSeries. Now, modifying * the original TimeSeriesDataItem should NOT affect the TimeSeries. *//*from ww w . j a va 2 s .co m*/ public void testAdd_TimeSeriesDataItem() { TimeSeriesDataItem item = new TimeSeriesDataItem(new Year(2009), 1.0); TimeSeries series = new TimeSeries("S1"); series.add(item); assertTrue(item.equals(series.getDataItem(0))); item.setValue(new Double(99.9)); assertFalse(item.equals(series.getDataItem(0))); }
From source file:com.bdb.weather.display.summary.TemperatureDeviationPlotPanel.java
public void loadData(List<SummaryRecord> list, WeatherAverages averagesCollection) { TimeSeriesCollection lowCollection = new TimeSeriesCollection(); TimeSeriesCollection meanCollection = new TimeSeriesCollection(); TimeSeriesCollection highCollection = new TimeSeriesCollection(); TimeSeries highSeries = new TimeSeries(HIGH_SERIES_NAME); TimeSeries meanSeries = new TimeSeries(MEAN_SERIES_NAME); TimeSeries lowSeries = new TimeSeries(LOW_SERIES_NAME); int n = 0;//w ww . j ava 2 s. c om //tableModel.setRowCount(list.size()); DateTimeFormatter dateFormat = interval.getFormat(); for (SummaryRecord record : list) { WeatherAverage averages = averagesCollection.getAverage(record.getDate()); String dateString = dateFormat.format(record.getDate()); //tableModel.setValueAt(dateString, n, DATE_COLUMN); Temperature deviation = supporter.retrieveLowOutdoorTemperature(record) .subtract(averages.getLowTemperature()); RegularTimePeriod period = RegularTimePeriod.createInstance(interval.getFreeChartClass(), TimeUtils.localDateTimeToDate(record.getDate().atStartOfDay()), TimeZone.getDefault()); TimeSeriesDataItem item = new TimeSeriesDataItem(period, deviation.get()); lowSeries.add(item); //tableModel.setValueAt(deviation, n, LOW_COLUMN); deviation = supporter.retrieveAvgOutdoorTemperature(record).subtract(averages.getMeanTemperature()); item = new TimeSeriesDataItem(period, deviation.get()); meanSeries.add(item); //tableModel.setValueAt(deviation, n, MEAN_COLUMN); deviation = supporter.retrieveHighOutdoorTemperature(record).subtract(averages.getHighTemperature()); item = new TimeSeriesDataItem(period, deviation.get()); highSeries.add(item); //tableModel.setValueAt(deviation, n, HIGH_COLUMN); n++; } lowCollection.addSeries(lowSeries); meanCollection.addSeries(meanSeries); highCollection.addSeries(highSeries); deviationPlot.setDataset(LOW_SERIES_INDEX, lowCollection); deviationPlot.setDataset(MEAN_SERIES_INDEX, meanCollection); deviationPlot.setDataset(HIGH_SERIES_INDEX, highCollection); deviationPlot.setRenderer(LOW_SERIES_INDEX, lowRenderer); deviationPlot.setRenderer(MEAN_SERIES_INDEX, meanRenderer); deviationPlot.setRenderer(HIGH_SERIES_INDEX, highRenderer); }
From source file:org.jfree.data.time.TimeSeriesTest.java
/** * Create a TimeSeriesDataItem, add it to a TimeSeries. Now, modifying * the original TimeSeriesDataItem should NOT affect the TimeSeries. */// w ww . ja va2s . co m @Test public void testAdd_TimeSeriesDataItem() { TimeSeriesDataItem item = new TimeSeriesDataItem(new Year(2009), 1.0); TimeSeries series = new TimeSeries("S1"); series.add(item); assertTrue(item.equals(series.getDataItem(0))); item.setValue(new Double(99.9)); assertFalse(item.equals(series.getDataItem(0))); }
From source file:org.jfree.data.time.TimeSeries.java
/** * Adds or updates data from one series to another. Returns another series * containing the values that were overwritten. * * @param series the series to merge with this. * * @return A series containing the values that were overwritten. *///from www. ja va 2 s . co m public TimeSeries addAndOrUpdate(TimeSeries series) { TimeSeries overwritten = new TimeSeries("Overwritten values from: " + getKey()); for (int i = 0; i < series.getItemCount(); i++) { TimeSeriesDataItem item = series.getRawDataItem(i); TimeSeriesDataItem oldItem = addOrUpdate(item.getPeriod(), item.getValue()); if (oldItem != null) { overwritten.add(oldItem); } } return overwritten; }
From source file:org.mwc.debrief.track_shift.views.StackedDotHelper.java
/** * ok, our track has been dragged, calculate the new series of offsets * //ww w. ja v a2 s .c o m * @param linePlot * @param dotPlot * @param onlyVis * @param holder * @param logger * * @param currentOffset * how far the current track has been dragged */ public void updateFrequencyData(final XYPlot dotPlot, final XYPlot linePlot, final TrackDataProvider tracks, final boolean onlyVis, final Composite holder, final ErrorLogger logger, final boolean updateDoublets) { // do we have anything? if (_primaryTrack == null) return; // ok, find the track wrappers if (_secondaryTrack == null) initialise(tracks, false, onlyVis, holder, logger, "Frequency", false, true); // ok - the tracks have moved. better update the doublets if (updateDoublets) updateDoublets(onlyVis, false, true); // aah - but what if we've ditched our doublets? // aah - but what if we've ditched our doublets? if ((_primaryDoublets == null) || (_primaryDoublets.size() == 0)) { // better clear the plot dotPlot.setDataset(null); linePlot.setDataset(null); return; } // create the collection of series final TimeSeriesCollection errorSeries = new TimeSeriesCollection(); final TimeSeriesCollection actualSeries = new TimeSeriesCollection(); // produce a dataset for each track final TimeSeries errorValues = new TimeSeries(_primaryTrack.getName()); final TimeSeries measuredValues = new TimeSeries("Measured"); final TimeSeries correctedValues = new TimeSeries("Corrected"); final TimeSeries predictedValues = new TimeSeries("Predicted"); final TimeSeries baseValues = new TimeSeries("Base"); // ok, run through the points on the primary track final Iterator<Doublet> iter = _primaryDoublets.iterator(); while (iter.hasNext()) { final Doublet thisD = iter.next(); try { final Color thisColor = thisD.getColor(); final double measuredFreq = thisD.getMeasuredFrequency(); final HiResDate currentTime = thisD.getDTG(); final FixedMillisecond thisMilli = new FixedMillisecond(currentTime.getDate().getTime()); final ColouredDataItem mFreq = new ColouredDataItem(thisMilli, measuredFreq, thisColor, false, null); // final ColouredDataItem corrFreq = new ColouredDataItem( // new FixedMillisecond(currentTime.getDate().getTime()), // correctedFreq, thisColor, false, null); measuredValues.add(mFreq); // do we have target data? if (thisD.getTarget() != null) { final double correctedFreq = thisD.getCorrectedFrequency(); final double baseFreq = thisD.getBaseFrequency(); final Color calcColor = thisD.getTarget().getColor(); final ColouredDataItem corrFreq = new ColouredDataItem(thisMilli, correctedFreq, thisColor, true, null); // did we get a base frequency? We may have a track // with a section of data that doesn't have frequency, you see. if (baseFreq != Doublet.INVALID_BASE_FREQUENCY) { final double predictedFreq = thisD.getPredictedFrequency(); final double thisError = thisD.calculateFreqError(measuredFreq, predictedFreq); final ColouredDataItem bFreq = new ColouredDataItem(thisMilli, baseFreq, thisColor, true, null); final ColouredDataItem pFreq = new ColouredDataItem(thisMilli, predictedFreq, calcColor, false, null); final ColouredDataItem eFreq = new ColouredDataItem(thisMilli, thisError, thisColor, false, null); baseValues.add(bFreq); predictedValues.add(pFreq); errorValues.add(eFreq); } correctedValues.add(corrFreq); } } catch (final SeriesException e) { CorePlugin.logError(Status.INFO, "some kind of trip whilst updating frequency plot", e); } } // ok, add these new series if (errorValues.getItemCount() > 0) errorSeries.addSeries(errorValues); actualSeries.addSeries(measuredValues); actualSeries.addSeries(correctedValues); if (predictedValues.getItemCount() > 0) actualSeries.addSeries(predictedValues); if (baseValues.getItemCount() > 0) actualSeries.addSeries(baseValues); dotPlot.setDataset(errorSeries); linePlot.setDataset(actualSeries); }
From source file:org.jfree.data.time.TimeSeries.java
/** * Creates a new timeseries by copying a subset of the data in this time * series.//from w ww.j a v a 2 s . c o m * * @param start the index of the first time period to copy. * @param end the index of the last time period to copy. * * @return A series containing a copy of this times series from start until * end. * * @throws CloneNotSupportedException if there is a cloning problem. */ public TimeSeries createCopy(int start, int end) throws CloneNotSupportedException { if (start < 0) { throw new IllegalArgumentException("Requires start >= 0."); } if (end < start) { throw new IllegalArgumentException("Requires start <= end."); } TimeSeries copy = (TimeSeries) super.clone(); copy.minY = Double.NaN; copy.maxY = Double.NaN; copy.data = new java.util.ArrayList(); if (this.data.size() > 0) { for (int index = start; index <= end; index++) { TimeSeriesDataItem item = (TimeSeriesDataItem) this.data.get(index); TimeSeriesDataItem clone = (TimeSeriesDataItem) item.clone(); try { copy.add(clone); } catch (SeriesException e) { throw new RuntimeException(e); } } } return copy; }