/* * Author: tdanford * Date: Jul 18, 2008 */ package org.seqcode.viz.paintable; import java.util.*; import java.awt.*; import org.seqcode.viz.paintable.*; import org.seqcode.viz.paintable.layout.InsetPaintable; import org.seqcode.viz.paintable.layout.LayeredPaintable; import org.seqcode.viz.paintable.layout.StackedPaintable; public class BoxAndWhiskersPlot extends AbstractPaintable implements PaintableScaleListener { /** * Testing whether the BoxAndWhiskersPlot works, along with the Scale painters. */ public static void main(String[] args) { double min = 0.0, max = 100.0; Random rand = new Random(); int count = 5; double[][] bounds = new double[count][]; for(int i = 0; i < count; i++) { double[] b = randomBounds(rand, min, max); bounds[i] = b; } PaintableScale scale = new PaintableScale(min, max); Paintable p = createBoxAndWhiskersPlots(scale, bounds, null); PaintableFrame pf = new PaintableFrame("Box and Whiskers", p); } public static Paintable createBoxAndWhiskersPlots(PaintableScale scale, double[][] bounds, double[][] pts) { int count = bounds.length; Paintable[] plots = new Paintable[count]; for(int i = 0; i < count; i++) { double[] b = bounds[i]; BoxAndWhiskersPlot pp = new BoxAndWhiskersPlot(scale, b[0], b[1], b[2], b[3], b[4]); if(pts != null && pts[i] != null) { for(int j = 0; j < pts[i].length; j++) { pp.addPointValue(pts[i][j]); } } plots[i] = new InsetPaintable(0.25, 0.0, pp); } Paintable plot = new StackedPaintable(false, plots); plot = new InsetPaintable(30, 0, plot); VerticalScalePainter scalePainter = new VerticalScalePainter(scale); Paintable p = new LayeredPaintable(scalePainter, plot); return p; } private static double[] randomBounds(Random rand, double min, double max) { double[] a = new double[5]; for(int i = 0; i < a.length; i++) { a[i] = rand.nextDouble(); } Arrays.sort(a); double range = max-min; for(int i = 0; i < a.length; i++) { a[i] = min + a[i] * range; } return a; } private PaintableScale scale; private double min, max, lowerBox, upperBox, middle; private LinkedList<Double> pointValues; public BoxAndWhiskersPlot(PaintableScale s, double min, double lower, double middle, double upper, double max) { scale = s; this.min = min; this.max = max; this.lowerBox = lower; this.upperBox = upper; this.middle = middle; if(min > lower || lower > middle || middle > upper || upper > max) { throw new IllegalArgumentException(String.format("%f < %f < %f < %f < %f", min, lower, middle, upper, max)); } scale.addPaintableScaleListener(this); pointValues = new LinkedList<Double>(); } public BoxAndWhiskersPlot(PaintableScale s, double[] a) { this(s, a[0], a[1], a[2], a[3], a[4]); } public void addPointValue(Double pt) { pointValues.add(pt); } public void paintItem(Graphics g, int x1, int y1, int x2, int y2) { scale.updateScale(min); scale.updateScale(max); int w = x2 - x1, h = y2 - y1; double f1 = scale.fractionalOffset(min); double f2 = scale.fractionalOffset(lowerBox); double f3 = scale.fractionalOffset(middle); double f4 = scale.fractionalOffset(upperBox); double f5 = scale.fractionalOffset(max); int xline = x1 + w/2; int fy1 = y2 - (int)Math.round(f1 * (double)h); int fy2 = y2 - (int)Math.round(f2 * (double)h); int fy3 = y2 - (int)Math.round(f3 * (double)h); int fy4 = y2 - (int)Math.round(f4 * (double)h); int fy5 = y2 - (int)Math.round(f5 * (double)h); System.out.println(String.format("%.3f %.3f %.3f %.3f %.3f", f1, f2, f3, f4 ,f5)); g.setColor(Color.black); g.drawLine(xline, fy1, xline, fy5); // the middle line. g.drawLine(x1, fy1, x2, fy1); // the top line (maximum) g.drawLine(x1, fy5, x2, fy5); // the bottom line (minimum) g.setColor(Color.white); g.fillRect(x1, fy4, x2-x1, Math.abs(fy4-fy2)); g.setColor(Color.black); g.drawRect(x1, fy4, x2-x1, Math.abs(fy4-fy2)); g.drawLine(x1, fy3, x2, fy3); for(Double pt : pointValues) { double fpt = scale.fractionalOffset(pt); int fypt = y2 - (int)Math.round(fpt * (double)h); int rad = 3; int diam = rad*2; g.setColor(Color.black); g.fillOval(xline-rad, fypt-rad, diam, diam); } } public void paintableScaleChanged(PaintableScaleChangedEvent evt) { dispatchChangedEvent(); } }