package hep.aida.ref.plotter.adapter; import jas.hist.CustomOverlay; import jas.hist.DataSource; import jas.hist.JASHist1DHistogramStyle; import jas.hist.JASHistData; import jas.hist.JASHistStyle; import jas.hist.XYDataSource; import jas.plot.CoordinateTransformation; import jas.plot.DateCoordinateTransformation; import jas.plot.DoubleCoordinateTransformation; import jas.plot.MutableLegendEntry; import jas.plot.OverlayContainer; import jas.plot.PlotGraphics; import java.awt.BasicStroke; /** * Overlay that can be used with XYDataSource to represent time scalers * It jusr connects points with straight lines */ public class ScalerOverlay implements CanSetData, CustomOverlay, MutableLegendEntry { private XYDataSource source; private OverlayContainer container; private JASHistData data; private JASHist1DHistogramStyle style; private String[] labels; private double[] xPoly; private double[] yPoly; private double xmax; private double xmin; private int oldn = 0; private static final float[][] lineStyles = {null, { 1, 5 },{ 4, 6 },{ 6, 4, 2, 4 }}; public ScalerOverlay() { } public void setData(JASHistData data) { this.data = data; } public void setStyle(JASHistStyle s) { this.style = (JASHist1DHistogramStyle) s; if (style != null) { style.setShowHistogramBars(false); style.setShowLinesBetweenPoints(true); } } public JASHist1DHistogramStyle getStyle() { return style; } // LegendEntry methods public String getTitle() { return source.getTitle(); } public void paintIcon(PlotGraphics g, int width, int height) { if (style == null) setStyle((JASHist1DHistogramStyle) data.getStyle()); if (style.getShowDataPoints()) { g.setColor(style.getDataPointColor()); g.drawSymbol( width / 2, height / 2, width / 2, style.getDataPointStyle()); } else if (style.getShowHistogramBars()) { if ( style.getHistogramFill() ) { g.setColor(style.getHistogramBarColor()); g.fillRect(1, 1, width - 2, height - 2); } else { g.setColor(style.getHistogramBarLineColor()); BasicStroke s = new BasicStroke(style.getHistogramBarLineWidth(),BasicStroke.CAP_SQUARE,BasicStroke.JOIN_ROUND,10,lineStyles[style.getHistogramBarLineStyle()],0); g.setStroke(s); g.drawLine(1, height/2, width-2, height/2); g.setStroke(null); } } else if (style.getShowLinesBetweenPoints()) { g.setColor(style.getLineColor()); BasicStroke s = new BasicStroke(style.getLinesBetweenPointsWidth(),BasicStroke.CAP_SQUARE,BasicStroke.JOIN_ROUND,10,lineStyles[style.getLinesBetweenPointsStyle()],0); g.setStroke(s); g.drawLine(1, height/2, width-2, height/2); g.setStroke(null); } else if (style.getShowErrorBars()) { g.setColor(style.getErrorBarColor()); BasicStroke s = new BasicStroke(style.getErrorBarWidth(),BasicStroke.CAP_SQUARE,BasicStroke.JOIN_ROUND,10,lineStyles[style.getErrorBarStyle()],0); g.setStroke(s); g.drawLine(1, height/2, width-2, height/2); g.setStroke(null); } else if (style.getHistogramFill()) { g.setColor(style.getHistogramBarColor()); g.fillRect(1, 1, width - 2, height - 2); } } // MutableLegendEntry methods public void setTitle(String newTitle) { } public boolean titleIsChanged() { return false; //source.isLegendChanged(); } // CustomOverlay mathods public void setDataSource(DataSource sr) { if (sr instanceof XYDataSource) this.source = (XYDataSource) sr; else throw new IllegalArgumentException("DataSource is not XYDataSource, DataSource="+sr.toString()); } // Overlay methods public void containerNotify(OverlayContainer c) { this.container = c; } public void paint(PlotGraphics g, boolean isPrinting) { if (style == null) setStyle((JASHist1DHistogramStyle) data.getStyle()); CoordinateTransformation xp = container.getXTransformation(); final CoordinateTransformation yp = container.getYTransformation(data.getYAxis()); if (xp instanceof DateCoordinateTransformation) { xp = new DateTransformationConverter((DateCoordinateTransformation) xp); } if (xp instanceof DoubleCoordinateTransformation && yp instanceof DoubleCoordinateTransformation) { final DoubleCoordinateTransformation xt = (DoubleCoordinateTransformation) xp; final DoubleCoordinateTransformation yt = (DoubleCoordinateTransformation) yp; xmin = xt.getPlotMin(); xmax = xt.getPlotMax(); final int bins = source.getNPoints(); final double binWidth = (xmax - xmin) / bins; final double pixelWidth = (xt.convert(xmax) - xt.convert(xmin)) / bins; final boolean outline = pixelWidth > 5; final double errorBarWidth = Math.min(binWidth, (3 * binWidth) / pixelWidth); g.setTransformation(xt, yt); double x = xmin; double oldx = xmin; // y0 is used as the base of histogram bars. It should // be 0 unless there is a suppressed 0 on the Y axis. double y0 = 0; if (yt.getPlotMin() > y0) { y0 = yt.getPlotMin(); } if (yt.getPlotMax() < y0) { y0 = yt.getPlotMax(); } if ((style.getShowLinesBetweenPoints() || style.getShowDataPoints()) && bins != oldn) { xPoly = new double[bins]; yPoly = new double[bins]; oldn = bins; } int index = 0; double y = source.getY(index); x = source.getX(index); double oldy = y; xPoly[index] = x; yPoly[index] = y; for (int i = 0; i < bins; i++) { y = source.getY(i); x = source.getX(i); //System.out.println("N="+i+"\ty="+y+"\tx="+x); // skip point if X or Y == Double.NaN if (Double.isNaN(y) || Double.isNaN(x)) continue; xPoly[index] = x; yPoly[index] = y; BasicStroke s = new BasicStroke(style.getHistogramBarLineWidth(),BasicStroke.CAP_SQUARE,BasicStroke.JOIN_ROUND,10,lineStyles[style.getHistogramBarLineStyle()],0); g.setStroke(s); if (style.getShowHistogramBars()) { g.setColor(style.getHistogramBarColor()); if (style.getHistogramFill()) { g.setColor(style.getHistogramBarLineColor()); if (i > 0) g.fillRect(oldx, y0, x, oldy); if (outline) { g.drawRect(oldx, y0, x, oldy); } else { if (i > 0) g.drawLine(oldx, oldy, x, oldy); g.drawLine(x, oldy, x, y); } } else { g.setColor(style.getHistogramBarLineColor()); g.drawLine(oldx, oldy, x, oldy); g.drawLine(x, oldy, x, y); } } if (style.getShowErrorBars()) { g.setColor(style.getErrorBarColor()); s = new BasicStroke(style.getErrorBarWidth(),BasicStroke.CAP_SQUARE,BasicStroke.JOIN_ROUND,10,lineStyles[style.getErrorBarStyle()],0); g.setStroke(s); //final double xm = (binWidth == 0) ? x : (oldx + (binWidth / 2)); final double xm = x; final double xe = errorBarWidth; final double yplus = y + source.getPlusError(i); final double yminus = y - source.getMinusError(i); if (!Double.isNaN(yplus) && !Double.isNaN(yminus) && yminus != yplus) { //System.out.println("***** xm="+xm+", xe="+xe+", y="+y+", yminus="+yminus+", yplus="+yplus); g.drawLine(xm, yplus, xm, yminus); if (outline) { BasicStroke ss = new BasicStroke(style.getErrorBarWidth(),BasicStroke.CAP_SQUARE,BasicStroke.JOIN_ROUND,10); g.setStroke(ss); g.drawLine(xm - xe, yplus, xm + xe, yplus); g.drawLine(xm - xe, yminus, xm + xe, yminus); } } } oldx = x; oldy = y; index++; } // end for if (index > 0) { if (style.getShowLinesBetweenPoints()) { g.setColor(style.getLineColor()); BasicStroke s = new BasicStroke(style.getLinesBetweenPointsWidth(),BasicStroke.CAP_SQUARE,BasicStroke.JOIN_ROUND,10,lineStyles[style.getLinesBetweenPointsStyle()],0); g.setStroke(s); g.drawPolyLine(xPoly, yPoly, index); } if (style.getShowDataPoints()) { g.setColor(style.getDataPointColor()); g.drawPolySymbol(xPoly, yPoly, style.getDataPointSize(), style.getDataPointStyle(), index); } } } } private class DateTransformationConverter implements DoubleCoordinateTransformation { private DateCoordinateTransformation dateCT; DateTransformationConverter(DateCoordinateTransformation dateCT) { this.dateCT = dateCT; } public double convert(double d) { return dateCT.convert((long) (d*1000)); } public double unConvert(double i) { return dateCT.map(i)/1000.; } public double getPlotMin() { return dateCT.getAxisMin()/1000.; } public double getPlotMax() { return dateCT.getAxisMax()/1000.; } } }