/* * JTraceChart.java * * Copyright (C) 2002-2009 Alexei Drummond and Andrew Rambaut * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package dr.app.tracer.traces; import dr.app.gui.chart.Axis; import dr.app.gui.chart.DiscreteJChart; import dr.app.gui.chart.Plot; import dr.stats.Variate; import java.awt.*; import java.awt.geom.GeneralPath; import java.util.ArrayList; import java.util.List; public class JTraceChart extends DiscreteJChart { private static final int SAMPLE_POINTS = 1000; private boolean useSample = false; private boolean isLinePlot = true; private static final int BURNIN_TRANSLUCENCY = 72; private class Trace { int stateStart; int stateStep; int sampleCount; int sampleStep; List<Double> states = new ArrayList<Double>(); List<Double> values; Trace(int stateStart, int stateStep, List<Double> values) { this.stateStart = stateStart; this.stateStep = stateStep; this.values = values; sampleCount = values.size(); sampleStep = 1; while (sampleCount > SAMPLE_POINTS) { sampleStep *= 2; sampleCount = values.size() / sampleStep; } double ix = stateStart; for (int j = 0; j < values.size(); j++) { this.states.add(j, ix); ix += stateStep; } } } private final ArrayList<Trace> traces = new ArrayList<Trace>(); private final ArrayList<Trace> burninTraces = new ArrayList<Trace>(); public JTraceChart(Axis xAxis, Axis yAxis) { super(xAxis, yAxis); } public void setUseSample(boolean useSample) { this.useSample = useSample; } public void setIsLinePlot(boolean isLinePlot) { this.isLinePlot = isLinePlot; } public void addTrace(String name, int stateStart, int stateStep, List<Double> values, List<Double> burninValues, Paint paint) { Variate.D yd = new Variate.D(values); xAxis.addRange(0, stateStart + (values.size() * stateStep) - stateStep); yAxis.addRange(yd.getMin(), yd.getMax()); traces.add(new Trace(stateStart, stateStep, values)); if (burninValues != null) { burninTraces.add(new Trace(0, stateStep, burninValues)); } Plot plot = new Plot.AbstractPlot() { // create a dummy plot to store paint styles protected void paintData(Graphics2D g2, Variate.N xData, Variate.N yData) { } }; plot.setLineColor(paint); plot.setName(name); addPlot(plot); recalibrate(); repaint(); } public List<Double> getTraceStates(int index) { Trace trace = traces.get(index); return trace.states; } public List<Double> getTraceValues(int index) { Trace trace = traces.get(index); return trace.values; } public void removeAllTraces() { traces.clear(); burninTraces.clear(); xAxis.setRange(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY); yAxis.setRange(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY); removeAllPlots(); recalibrate(); repaint(); } protected void calibrate(Graphics2D g2, Dimension size) { } protected boolean hasContents() { return traces.size() > 0; } protected void paintContents(Graphics2D g2) { if (!isLinePlot) { g2.setStroke(new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)); } else { g2.setStroke(new BasicStroke(0.5f)); } for (int i = 0; i < traces.size(); i++) { Trace trace = traces.get(i); int sampleFrequency = 1; if (useSample) { sampleFrequency = trace.states.size() / trace.sampleCount; } paintTrace(g2, trace, getPlot(i).getLineColor(), sampleFrequency); if (i < burninTraces.size()) { Trace burninTrace = burninTraces.get(i); Color colour = (Color)getPlot(i).getLineColor(); Color burninColor = new Color(colour.getRed(), colour.getGreen(), colour.getBlue(), BURNIN_TRANSLUCENCY); paintTrace(g2, burninTrace, burninColor, sampleFrequency); } } } private void paintTrace(Graphics2D g2, Trace trace, Paint paint, int sampleFrequency) { float x = (float) transformX(trace.states.get(0)); float y = (float) transformY(trace.values.get(0)); GeneralPath path = new GeneralPath(); path.moveTo(x, y); if (!isLinePlot) { path.lineTo(x, y); } int k = sampleFrequency; for (int j = 1; j < trace.states.size(); j++) { x = (float) transformX(trace.states.get(k)); y = (float) transformY(trace.values.get(k)); if (!isLinePlot) { path.moveTo(x, y); } path.lineTo(x, y); k += sampleFrequency; if (k >= trace.states.size()) { break; } } g2.setPaint(paint); g2.draw(path); } }