package com.indago.iddea.view.plot; import java.awt.*; import java.util.ArrayList; import java.util.Collections; import de.erichseifert.gral.data.DataSeries; import de.erichseifert.gral.data.DataSource; import de.erichseifert.gral.data.DataTable; import de.erichseifert.gral.data.EnumeratedData; import de.erichseifert.gral.data.filters.Convolution; import de.erichseifert.gral.data.filters.Filter; import de.erichseifert.gral.data.filters.Kernel; import de.erichseifert.gral.data.filters.KernelUtils; import de.erichseifert.gral.data.statistics.Histogram1D; import de.erichseifert.gral.graphics.DrawableContainer; import de.erichseifert.gral.graphics.TableLayout; import de.erichseifert.gral.plots.XYPlot; import de.erichseifert.gral.plots.areas.AreaRenderer; import de.erichseifert.gral.plots.areas.DefaultAreaRenderer2D; import de.erichseifert.gral.plots.areas.LineAreaRenderer2D; import de.erichseifert.gral.plots.lines.DefaultLineRenderer2D; import de.erichseifert.gral.plots.lines.LineRenderer; import de.erichseifert.gral.ui.InteractivePanel; import de.erichseifert.gral.util.GraphicsUtils; import de.erichseifert.gral.util.Insets2D; import de.erichseifert.gral.util.Orientation; import javax.swing.*; import com.indago.iddea.model.util.DoubleArrayList; import com.indago.iddea.model.util.LongArrayList; /** * Draw HistogramPlot Panel with Foreground list and Background list * * @version 0.1beta * @since 3/25/14 1:59 PM * @author HongKee Moon */ public class HistogramPlot extends JPanel { /** First corporate color used for foreground color */ protected static final Color COLOR1 = new Color(200, 80, 75); /** Second corporate color used for background color */ protected static final Color COLOR2 = new Color(55 , 170, 200); /** Maximum Sample Size */ static final int SAMPLE = 100; XYPlot foreground = null; XYPlot background = null; /** * Performs basic initialization of HistogramPlot for LongArrayList */ public HistogramPlot(LongArrayList foregroundList, LongArrayList backgroundList) { super(new BorderLayout()); setPreferredSize(new Dimension(800, 600)); setBackground(Color.WHITE); if(foregroundList.size() > 0) foreground = createXYPlot("Foreground", foregroundList, COLOR1, Long.class); if(backgroundList.size() > 0) background = createXYPlot("Background", backgroundList, COLOR2, Long.class); DrawableContainer plots = new DrawableContainer(new TableLayout(1)); if(foreground != null) plots.add(foreground); if(background != null) plots.add(background); // Connect the two plots, i.e. user (mouse) actions affect both plots //foreground.getNavigator().connect(background.getNavigator()); // Add plot to Swing component InteractivePanel panel = new InteractivePanel(plots); add(panel); showInFrame(); } /** * Performs basic initialization of HistogramPlot for DoubleArrayList */ public HistogramPlot(DoubleArrayList foregroundList, DoubleArrayList backgroundList) { super(new BorderLayout()); setPreferredSize(new Dimension(800, 600)); setBackground(Color.WHITE); if(foregroundList.size() > 0) foreground = createXYPlot("Foreground", foregroundList, COLOR1, Double.class); if(backgroundList.size() > 0) background = createXYPlot("Background", backgroundList, COLOR2, Double.class); DrawableContainer plots = new DrawableContainer(new TableLayout(1)); if(foreground != null) plots.add(foreground); if(background != null) plots.add(background); // Connect the two plots, i.e. user (mouse) actions affect both plots //foreground.getNavigator().connect(background.getNavigator()); // Add plot to Swing component InteractivePanel panel = new InteractivePanel(plots); add(panel); showInFrame(); } /** * Get a DataSource from Long type ArrayList * @param list * @return data */ private DataSource getLongHistogramDataSource(ArrayList<Long> list) { // Create example data Long max = Collections.max(list); Long min = Collections.min(list); int bin = max.intValue() - min.intValue() + 1; Double gap = 1d; DataTable data = new DataTable(Long.class); System.out.println("Bin: " + bin + " SAMPLE:" + SAMPLE); System.out.println("Max: " + max + " Min: " + min + " Gap:" + 1); if(bin > SAMPLE) { bin = SAMPLE; gap = (max.doubleValue() - min.doubleValue()) / bin; } Number[] number = null; if(!min.equals(max)) { number = new Number[bin + 1]; for (int i = 0; i <= bin; i++) number[i] = min + i * gap; } else { number = new Number[3]; min = min - 1; number[0] = min; number[1] = min + 1; number[2] = min + 2; } for (Long d : list) { data.add(d); } // Create histogram from data Histogram1D histogram = new Histogram1D(data, Orientation.VERTICAL, number); // Create a second dimension (x axis) for plotting return new EnumeratedData(histogram, min, gap); } /** * Get a DataSource for Double type ArrayList * @param list * @return data */ private DataSource getDoubleHistogramDataSource(ArrayList<Double> list) { // Create example data DataTable data = new DataTable(Double.class); Double max = Collections.max(list); Double min = Collections.min(list); Double gap = (max.doubleValue() - min.doubleValue()) / SAMPLE; min -= gap; System.out.println("NBin: " + SAMPLE); System.out.println("Max: " + max + " Min: " + min + " Gap:" + gap); Number[] number = null; if(min != max) { number = new Number[SAMPLE + 3]; for (int i = 0; i < number.length; i++) number[i] = min + i * gap; } else { number = new Number[3]; min -= gap; number[0] = min; number[1] = min + gap; number[2] = min + gap; } for (Double d : list) { data.add(d); } // Create histogram from data Histogram1D histogram = new Histogram1D(data, Orientation.VERTICAL, number); // Create a second dimension (x axis) for plotting return new EnumeratedData(histogram, min, gap); } /** * creates a Plot for ctor() * @param title * @param list * @param color * @param clazz * @return */ private XYPlot createXYPlot(String title, ArrayList<?> list, Color color, Class clazz) { // Create example data DataSource histogram2d = null; if(clazz == Long.class) { histogram2d = getLongHistogramDataSource((ArrayList<Long>)list); } else if(clazz == Double.class) { histogram2d = getDoubleHistogramDataSource((ArrayList<Double>)list); } DataSeries ds = new DataSeries("Data", histogram2d, 0, 1); // Create new bar plot XYPlot plot = new XYPlot(ds); plot.getAxis(plot.AXIS_X).setAutoscaled(false); plot.getAxis(plot.AXIS_Y).setAutoscaled(false); // Format plot plot.setInsets(new Insets2D.Double(20.0, 65.0, 50.0, 40.0)); plot.getTitle().setText( String.format("%s (%d) pixels", title, list.size())); final double KERNEL_VARIANCE = 3.0; // Create a smoothed data series from a binomial (near-gaussian) convolution filter Kernel kernelLowpass = KernelUtils.getBinomial(KERNEL_VARIANCE).normalize(); Filter dataLowpass = new Convolution(histogram2d, kernelLowpass, Filter.Mode.REPEAT, 1); DataSeries dsLowpass = new DataSeries("Lowpass", dataLowpass, 0, 1); plot.add(dsLowpass); formatLineArea(plot, ds, color); formatFilledArea(plot, dsLowpass, GraphicsUtils.deriveDarker(color)); return plot; } private static void formatFilledArea(XYPlot plot, DataSource data, Color color) { plot.setPointRenderer(data, null); LineRenderer line = new DefaultLineRenderer2D(); line.setColor(color); line.setGap(3.0); line.setGapRounded(true); plot.setLineRenderer(data, line); AreaRenderer area = new DefaultAreaRenderer2D(); area.setColor(GraphicsUtils.deriveWithAlpha(color, 64)); plot.setAreaRenderer(data, area); } private static void formatLineArea(XYPlot plot, DataSource data, Color color) { // PointRenderer point = new DefaultPointRenderer2D(); // point.setColor(new Color(1f, 1f, 1f, 1f)); // point.setValueVisible(true); plot.setPointRenderer(data, null); plot.setLineRenderer(data, null); LineAreaRenderer2D area = new LineAreaRenderer2D(); area.setGap(3.0); area.setColor(color); area.setStroke(new BasicStroke(5)); plot.setAreaRenderer(data, area); } public JFrame showInFrame() { JFrame frame = new JFrame("Histogram"); frame.getContentPane().add(this, BorderLayout.CENTER); //frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(getPreferredSize()); frame.setVisible(true); return frame; } }