Java tutorial
/* Copyright 2013,2016 Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. Distributed under the BSD-3 license. See the file LICENSE for details. */ package gov.sandia.umf.platform.ui.jobs; import java.awt.Color; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; 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.CrosshairState; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.PlotRenderingInfo; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYDotRenderer; import org.jfree.chart.renderer.xy.XYItemRendererState; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import org.jfree.ui.RectangleEdge; /** Create a spike-raster plot. The parsing functions in this class are similar to Plot, but they can be implemented more efficiently because we have simpler needs. **/ public class Raster { public XYSeriesCollection dataset; public int availableHeight; public Raster(String path, int height) { availableHeight = height - 50; // Allow for estimated size of stuff around the plot. parsePrnFile(new File(path)); } public JPanel createGraphPanel() { JFreeChart chart = createChart(dataset); return new ChartPanel(chart); } public void parsePrnFile(File f) { dataset = new XYSeriesCollection(); XYSeries series = new XYSeries("Spikes"); dataset.addSeries(series); int columns = 1; try { int row = 0; int timeColumn = -1; // It's possible that there might not be a time column. In that case, we use raw row index; BufferedReader br = new BufferedReader(new FileReader(f)); while (true) { String line = br.readLine(); if (line == null) break; // indicates end of stream line = line.trim(); if (line.length() == 0) continue; if (line.startsWith("End of")) continue; String[] parts = line.split("\t"); // TODO: does Xyce output tabs or spaces? May have to switch regexp here, depending on source. columns = Math.max(columns, parts.length); char firstCharacter = parts[0].charAt(0); if (firstCharacter < '0' || firstCharacter > '9') // column header { if (timeColumn >= 0) continue; int timeMatch = 0; // goodness of match for (int p = 0; p < parts.length; p++) { int potentialMatch = 0; String columnName = parts[p]; if (columnName.equals("TIME")) potentialMatch = 1; else if (columnName.equals("$t")) potentialMatch = 2; if (potentialMatch > timeMatch) { timeMatch = potentialMatch; timeColumn = p; } } } else { int p = timeColumn; double time = row; if (p >= 0) time = Double.parseDouble(parts[timeColumn]); p++; for (; p < parts.length; p++) { if (!parts[p].isEmpty() && Double.parseDouble(parts[p]) != 0) series.add(time, p); } row++; } } br.close(); } catch (IOException e) { } availableHeight = Math.min(20, Math.max(1, Math.round((float) availableHeight / columns))); } public JFreeChart createChart(final XYDataset dataset) { final JFreeChart chart = ChartFactory.createScatterPlot(null, // chart title null, // x axis label null, // y axis label dataset, // data PlotOrientation.VERTICAL, false, // include legend true, // tooltips false // urls ); chart.setBackgroundPaint(Color.white); XYPlot plot = chart.getXYPlot(); plot.setBackgroundPaint(Color.white); plot.setRangeGridlinePaint(Color.lightGray); plot.setDomainPannable(true); plot.setRangePannable(true); plot.setRenderer(new XYDotRenderer() { public void drawItem(java.awt.Graphics2D g2, XYItemRendererState state, java.awt.geom.Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { // Copied from org.jfree.chart.renderer.xy.XYDotRenderer.java and modified. // This would only need to be a couple of lines if they authors of jfreechart had not made dotWidth and dotHeight private members. // Yet another example of textbook OO programming gone awry. (Can anyone hear me scream?) if (!getItemVisible(series, item)) return; int dotWidth = 1; double rasterLines = rangeAxis.getRange().getLength(); int pixels = g2.getClipBounds().height; double height = pixels / rasterLines; if (height > 10) height -= 2; else if (height > 2) height -= 1; int dotHeight = (int) Math.min(20, Math.max(1, Math.floor(height))); double x = dataset.getXValue(series, item); double y = dataset.getYValue(series, item); if (Double.isNaN(y)) return; double adjx = (dotWidth - 1) / 2.0; double adjy = (dotHeight - 1) / 2.0; RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); double transX = domainAxis.valueToJava2D(x, dataArea, xAxisLocation) - adjx; double transY = rangeAxis.valueToJava2D(y, dataArea, yAxisLocation) - adjy; g2.setPaint(Color.black); PlotOrientation orientation = plot.getOrientation(); if (orientation == PlotOrientation.HORIZONTAL) g2.fillRect((int) transY, (int) transX, dotHeight, dotWidth); else g2.fillRect((int) transX, (int) transY, dotWidth, dotHeight); int domainAxisIndex = plot.getDomainAxisIndex(domainAxis); int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis); updateCrosshairValues(crosshairState, x, y, domainAxisIndex, rangeAxisIndex, transX, transY, orientation); } }); NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); // Integer units only return chart; } }