use of org.jfree.data.general.SeriesException in project zm-mailbox by Zimbra.
the class ChartUtil method readCsvFiles.
private void readCsvFiles() throws Exception {
Date minDate = null;
Date maxDate = null;
// per-file--shouldn't happen much since this is only for groupplot
for (DataColumn c : mUniqueStringColumns) {
String inFilename = c.getInfile();
Reader reader = null;
StringSeries data = mStringSeries.get(c);
try {
reader = new MultipleDirsFileReader(inFilename, mSrcDirs);
} catch (FileNotFoundException e) {
System.out.printf("CSV file %s not found; Skipping...\n", inFilename);
continue;
}
CsvReader csv = null;
try {
csv = new CsvReader(reader);
int line = 1;
while (csv.hasNext()) {
line++;
String ctx = inFilename + ", line " + line;
Date ts = null;
try {
ts = readTS(csv, ctx);
} catch (ParseException e) {
if (e.getMessage().compareTo("Unparseable date: \"timestamp\"") != 0) {
// bug 54626, ignored the repeat timestamp header
System.out.println(ctx + ": " + e);
}
continue;
}
if (ts.before(mStartAt) || ts.after(mEndAt))
continue;
if (minDate == null) {
minDate = ts;
maxDate = ts;
} else {
if (ts.compareTo(minDate) < 0)
minDate = ts;
if (ts.compareTo(maxDate) > 0)
maxDate = ts;
}
String value = csv.getValue(c.getColumn());
data.AddEntry(ts, value);
}
} finally {
if (csv != null)
csv.close();
}
}
// Read CSVs and populate data series.
for (Iterator<Map.Entry<String, Set<Pair<String, DataSeries>>>> mapIter = mColumnsByInfile.entrySet().iterator(); mapIter.hasNext(); ) {
Map.Entry<String, Set<Pair<String, DataSeries>>> entry = mapIter.next();
String inFilename = entry.getKey();
Set<Pair<String, DataSeries>> columns = entry.getValue();
System.out.println("Reading CSV " + inFilename);
Reader reader = null;
try {
reader = new MultipleDirsFileReader(inFilename, mSrcDirs);
} catch (FileNotFoundException e) {
System.out.printf("CSV file %s not found; Skipping...\n", inFilename);
continue;
}
CsvReader csv = null;
try {
csv = new CsvReader(reader);
int line = 1;
while (csv.hasNext()) {
line++;
String context = inFilename + ", line " + line;
Date ts = null;
try {
ts = readTS(csv, context);
} catch (ParseException e) {
if (e.getMessage().compareTo("Unparseable date: \"timestamp\"") != 0) {
// bug 54626, ignored the repeat timestamp header
System.out.println(context + ": " + e);
}
continue;
}
if (ts.before(mStartAt) || ts.after(mEndAt))
continue;
// Set min/max date
if (minDate == null) {
minDate = ts;
maxDate = ts;
} else {
if (ts.compareTo(minDate) < 0) {
minDate = ts;
}
if (ts.compareTo(maxDate) > 0) {
maxDate = ts;
}
}
// Parse values
for (Iterator<Pair<String, DataSeries>> colIter = columns.iterator(); colIter.hasNext(); ) {
Pair<String, DataSeries> colSeries = colIter.next();
String column = colSeries.getFirst();
DataSeries series = colSeries.getSecond();
String val = csv.getValue(column);
if (!StringUtil.isNullOrEmpty(val)) {
try {
double d = Double.parseDouble(val);
try {
series.AddEntry(ts, d);
} catch (SeriesException e) {
System.out.printf("Can't add sample to series: timestamp=%s, value=%s\n", ts, val);
e.printStackTrace(System.out);
}
} catch (NumberFormatException e) {
System.out.println(String.format("%s: unable to parse value '%s' for %s: %s", context, val, column, e));
}
} else {
// default an entry to 0 if string is empty
series.AddEntry(ts, 0.0);
}
}
}
for (Iterator<Pair<String, DataSeries>> colIter = columns.iterator(); colIter.hasNext(); ) {
Pair<String, DataSeries> colSeries = colIter.next();
String column = colSeries.getFirst();
DataSeries series = colSeries.getSecond();
System.out.format("Adding %d %s points between %s and %s.\n\n", series.size(), column, minDate, maxDate);
}
} finally {
if (csv != null)
csv.close();
}
}
adustSampleRange(minDate, maxDate);
}
use of org.jfree.data.general.SeriesException in project SIMVA-SoS by SESoS.
the class TimeSeries method add.
/**
* Adds a data item to the series and sends a {@link SeriesChangeEvent} to
* all registered listeners.
*
* @param item the (timeperiod, value) pair (<code>null</code> not
* permitted).
* @param notify notify listeners?
*/
public void add(TimeSeriesDataItem item, boolean notify) {
ParamChecks.nullNotPermitted(item, "item");
item = (TimeSeriesDataItem) item.clone();
Class c = item.getPeriod().getClass();
if (this.timePeriodClass == null) {
this.timePeriodClass = c;
} else if (!this.timePeriodClass.equals(c)) {
StringBuilder b = new StringBuilder();
b.append("You are trying to add data where the time period class ");
b.append("is ");
b.append(item.getPeriod().getClass().getName());
b.append(", but the TimeSeries is expecting an instance of ");
b.append(this.timePeriodClass.getName());
b.append(".");
throw new SeriesException(b.toString());
}
// make the change (if it's not a duplicate time period)...
boolean added = false;
int count = getItemCount();
if (count == 0) {
this.data.add(item);
added = true;
} else {
RegularTimePeriod last = getTimePeriod(getItemCount() - 1);
if (item.getPeriod().compareTo(last) > 0) {
this.data.add(item);
added = true;
} else {
int index = Collections.binarySearch(this.data, item);
if (index < 0) {
this.data.add(-index - 1, item);
added = true;
} else {
StringBuilder b = new StringBuilder();
b.append("You are attempting to add an observation for ");
b.append("the time period ");
b.append(item.getPeriod().toString());
b.append(" but the series already contains an observation");
b.append(" for that time period. Duplicates are not ");
b.append("permitted. Try using the addOrUpdate() method.");
throw new SeriesException(b.toString());
}
}
}
if (added) {
updateBoundsForAddedItem(item);
// check if this addition will exceed the maximum item count...
if (getItemCount() > this.maximumItemCount) {
TimeSeriesDataItem d = (TimeSeriesDataItem) this.data.remove(0);
updateBoundsForRemovedItem(d);
}
// remove old items if necessary, but
removeAgedItems(false);
// happens next anyway...
if (notify) {
fireSeriesChanged();
}
}
}
use of org.jfree.data.general.SeriesException in project zm-mailbox by Zimbra.
the class ChartUtil method createJFReeChart.
private List<JFreeChart> createJFReeChart(ChartSettings cs) {
double minValue = Double.MAX_VALUE;
double maxValue = Double.MIN_VALUE;
double d = 0;
double count = 0;
double total = 0;
TimeSeriesCollection data = new TimeSeriesCollection();
ArrayList<ChartSettings> syntheticSettings = new ArrayList<ChartSettings>();
for (GroupPlotSettings gps : cs.getGroupPlots()) {
String groupBy = gps.getGroupBy();
DataColumn dc = new DataColumn(gps.getInfile(), groupBy);
StringSeries groupBySeries = mStringSeries.get(dc);
dc = new DataColumn(gps.getInfile(), gps.getDataColumn());
DataSeries ds = mDataSeries.get(dc);
int idx = 0;
Map<String, List<Integer>> groups = new HashMap<String, List<Integer>>();
for (StringEntry e : groupBySeries.dataCollection) {
String g = e.getVal();
List<Integer> indices = groups.get(g);
if (indices == null) {
indices = new ArrayList<Integer>();
groups.put(g, indices);
}
indices.add(idx);
idx++;
}
for (Map.Entry<String, List<Integer>> g : groups.entrySet()) {
String groupByValue = g.getKey();
if (gps.getIgnoreSet().contains(groupByValue))
continue;
List<Integer> indices = g.getValue();
DataSeries syntheticDS = new DataSeries();
DataColumn c = new DataColumn(gps.getInfile(), GROUP_PLOT_SYNTHETIC + groupByValue + ":" + gps.getDataColumn());
for (int i : indices) {
Entry e = ds.get(i);
syntheticDS.AddEntry(e.getTimestamp(), e.getVal());
}
mDataSeries.put(c, syntheticDS);
PlotSettings syntheticPlot = new PlotSettings(groupByValue, c.getInfile(), c.getColumn(), gps.getShowRaw(), gps.getShowMovingAvg(), gps.getMovingAvgPoints(), gps.getMultiplier(), gps.getDivisor(), gps.getNonNegative(), gps.getPercentTime(), gps.getDataFunction(), gps.getAggregateFunction(), gps.getOptional(), null, null);
cs.addPlot(syntheticPlot);
if (cs.getOutDocument() != null) {
ChartSettings s = new ChartSettings(String.format(cs.getTitle(), groupByValue), cs.getCategory(), String.format(cs.getOutfile(), groupByValue), cs.getXAxis(), cs.getYAxis(), cs.getAllowLogScale(), cs.getPlotZero(), cs.getWidth(), cs.getHeight(), null, cs.getTopPlots(), cs.getTopPlotsType());
s.addPlot(syntheticPlot);
syntheticSettings.add(s);
}
}
}
if (cs.getOutDocument() != null && cs.getGroupPlots().size() != 0) {
ArrayList<JFreeChart> charts = new ArrayList<JFreeChart>();
for (ChartSettings c : syntheticSettings) {
charts.addAll(createJFReeChart(c));
c.setOutDocument(cs.getOutDocument());
}
mSyntheticChartSettings.addAll(syntheticSettings);
return charts;
}
List<PlotSettings> plots = cs.getPlots();
if (cs.getTopPlots() > 0 && plots.size() > cs.getTopPlots()) {
String aggregateFunction = cs.getTopPlotsType().name().toLowerCase();
System.out.println(String.format("Reducing %d to %d plots for chart '%s'", plots.size(), cs.getTopPlots(), cs.getTitle()));
ArrayList<PlotAggregatePair> aggregates = new ArrayList<PlotAggregatePair>();
for (PlotSettings ps : plots) {
DataColumn dc = new DataColumn(ps.getInfile(), ps.getDataColumn());
String key = ps.getInfile() + ":" + ps.getDataColumn() + ":" + ps.getAggregateFunction();
PlotDataIterator pdIter = new PlotDataIterator(ps, mDataSeries.get(dc));
double aggregate = mAggregator.compute(pdIter, aggregateFunction, mAggregateStartAt, mAggregateEndAt, key);
aggregates.add(new PlotAggregatePair(ps, aggregate));
}
Collections.sort(aggregates);
while (aggregates.size() > cs.getTopPlots()) {
PlotAggregatePair pair = aggregates.remove(0);
plots.remove(pair.ps);
}
}
for (PlotSettings ps : plots) {
String columnName = ps.getDataColumn();
if (columnName == null) {
columnName = RATIO_PLOT_SYNTHETIC + ps.getRatioTop() + "/" + ps.getRatioBottom();
String infile = ps.getInfile();
String[] top = ps.getRatioTop().split("\\+");
String[] bottom = ps.getRatioBottom().split("\\+");
DataColumn[] ratioTop = new DataColumn[top.length];
DataColumn[] ratioBottom = new DataColumn[bottom.length];
for (int i = 0, j = top.length; i < j; i++) ratioTop[i] = new DataColumn(infile, top[i]);
for (int i = 0, j = bottom.length; i < j; i++) ratioBottom[i] = new DataColumn(infile, bottom[i]);
DataSeries[] topData = new DataSeries[ratioTop.length];
DataSeries[] bottomData = new DataSeries[ratioBottom.length];
for (int i = 0, j = ratioTop.length; i < j; i++) topData[i] = mDataSeries.get(ratioTop[i]);
for (int i = 0, j = ratioBottom.length; i < j; i++) bottomData[i] = mDataSeries.get(ratioBottom[i]);
DataSeries ds = new DataSeries();
for (int i = 0, j = topData[0].size(); i < j; i++) {
double topValue = 0.0;
double bottomValue = 0.0;
double ratio = 0.0;
Entry lastEntry = null;
for (int m = 0, n = topData.length; m < n; m++) {
Entry e = topData[m].get(i);
topValue += e.getVal();
}
for (int m = 0, n = bottomData.length; m < n; m++) {
Entry e = bottomData[m].get(i);
bottomValue += e.getVal();
lastEntry = e;
}
if (bottomValue != 0.0) {
ratio = topValue / bottomValue;
}
// should never be null
assert lastEntry != null;
ds.AddEntry(lastEntry.getTimestamp(), ratio);
}
mDataSeries.put(new DataColumn(infile, columnName), ds);
ps.setDataColumn(columnName);
}
DataColumn dc = new DataColumn(ps.getInfile(), ps.getDataColumn());
DataSeries ds = mDataSeries.get(dc);
TimeSeries ts = new TimeSeries(ps.getLegend(), FixedMillisecond.class);
int numSamples = 0;
for (PlotDataIterator pdIter = new PlotDataIterator(ps, ds); pdIter.hasNext(); numSamples++) {
Pair<Date, Double> entry = pdIter.next();
Date tstamp = entry.getFirst();
double val = entry.getSecond().doubleValue();
if (val != 0 || cs.getPlotZero()) {
if (d < minValue)
minValue = val;
if (d > maxValue)
maxValue = val;
count++;
total += val;
try {
ts.addOrUpdate(new FixedMillisecond(tstamp), val);
} catch (SeriesException e) {
e.printStackTrace(System.out);
}
}
}
if (numSamples == 0 && ps.getOptional()) {
System.out.format("Skipping optional plot %s (no data sample found)\n\n", ps.getLegend());
continue;
}
System.out.format("Adding %d %s points to %s.\n\n", ds.size(), ps.getLegend(), cs.getOutfile());
if (ps.getShowRaw()) {
data.addSeries(ts);
}
if (ps.getShowMovingAvg()) {
int numPoints = ps.getMovingAvgPoints();
if (numPoints == PlotSettings.DEFAULT_PLOT_MOVING_AVG_POINTS) {
// Display 200 points for moving average.
// Divide the total number of points by 200 to
// determine the number of samples to average
// for each point.
numPoints = ts.getItemCount() / 200;
}
if (numPoints >= 2) {
TimeSeries ma = MovingAverage.createPointMovingAverage(ts, ps.getLegend() + " (moving avg)", numPoints);
data.addSeries(ma);
} else {
System.out.println("Not enough data to display moving average for " + ps.getLegend());
data.addSeries(ts);
}
}
}
// Create chart
boolean legend = (data.getSeriesCount() > 1);
JFreeChart chart = ChartFactory.createTimeSeriesChart(null, cs.getXAxis(), cs.getYAxis(), data, legend, false, false);
// Make Y-axis logarithmic if a spike was detected
if (cs.getAllowLogScale() && (minValue > 0) && (maxValue > 0) && (maxValue > 20 * (total / count))) {
if (maxValue / minValue > 100) {
XYPlot plot = (XYPlot) chart.getPlot();
ValueAxis oldAxis = plot.getRangeAxis();
LogarithmicAxis newAxis = new LogarithmicAxis(oldAxis.getLabel());
plot.setRangeAxis(newAxis);
}
}
mChartMap.put(cs, chart);
return Arrays.asList(chart);
}
use of org.jfree.data.general.SeriesException in project SIMVA-SoS by SESoS.
the class TimePeriodValues method createCopy.
/**
* Creates a new instance by copying a subset of the data in this
* collection.
*
* @param start the index of the first item to copy.
* @param end the index of the last item to copy.
*
* @return A copy of a subset of the items.
*
* @throws CloneNotSupportedException if there is a cloning problem.
*/
public TimePeriodValues createCopy(int start, int end) throws CloneNotSupportedException {
TimePeriodValues copy = (TimePeriodValues) super.clone();
copy.data = new ArrayList();
if (this.data.size() > 0) {
for (int index = start; index <= end; index++) {
TimePeriodValue item = (TimePeriodValue) this.data.get(index);
TimePeriodValue clone = (TimePeriodValue) item.clone();
try {
copy.add(clone);
} catch (SeriesException e) {
System.err.println("Failed to add cloned item.");
}
}
}
return copy;
}
use of org.jfree.data.general.SeriesException in project SIMVA-SoS by SESoS.
the class TimeSeries method addOrUpdate.
/**
* Adds or updates an item in the times series and sends a
* {@link SeriesChangeEvent} to all registered listeners.
*
* @param item the data item (<code>null</code> not permitted).
*
* @return A copy of the overwritten data item, or <code>null</code> if no
* item was overwritten.
*
* @since 1.0.14
*/
public TimeSeriesDataItem addOrUpdate(TimeSeriesDataItem item) {
ParamChecks.nullNotPermitted(item, "item");
Class periodClass = item.getPeriod().getClass();
if (this.timePeriodClass == null) {
this.timePeriodClass = periodClass;
} else if (!this.timePeriodClass.equals(periodClass)) {
String msg = "You are trying to add data where the time " + "period class is " + periodClass.getName() + ", but the TimeSeries is expecting an instance of " + this.timePeriodClass.getName() + ".";
throw new SeriesException(msg);
}
TimeSeriesDataItem overwritten = null;
int index = Collections.binarySearch(this.data, item);
if (index >= 0) {
TimeSeriesDataItem existing = (TimeSeriesDataItem) this.data.get(index);
overwritten = (TimeSeriesDataItem) existing.clone();
// figure out if we need to iterate through all the y-values
// to find the revised minY / maxY
boolean iterate = false;
Number oldYN = existing.getValue();
double oldY = oldYN != null ? oldYN.doubleValue() : Double.NaN;
if (!Double.isNaN(oldY)) {
iterate = oldY <= this.minY || oldY >= this.maxY;
}
existing.setValue(item.getValue());
if (iterate) {
updateMinMaxYByIteration();
} else if (item.getValue() != null) {
double yy = item.getValue().doubleValue();
this.minY = minIgnoreNaN(this.minY, yy);
this.maxY = maxIgnoreNaN(this.maxY, yy);
}
} else {
item = (TimeSeriesDataItem) item.clone();
this.data.add(-index - 1, item);
updateBoundsForAddedItem(item);
// check if this addition will exceed the maximum item count...
if (getItemCount() > this.maximumItemCount) {
TimeSeriesDataItem d = (TimeSeriesDataItem) this.data.remove(0);
updateBoundsForRemovedItem(d);
}
}
// remove old items if necessary, but
removeAgedItems(false);
// don't notify anyone, because that
// happens next anyway...
fireSeriesChanged();
return overwritten;
}
Aggregations