org.activequant.util.charting.Chart.java Source code

Java tutorial

Introduction

Here is the source code for org.activequant.util.charting.Chart.java

Source

/****
    
activequant - activestocks.eu
    
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
    
This program 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 General Public License for more details.
    
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    
       
   contact  : contact@activestocks.eu
homepage : http://www.activestocks.eu
    
 ****/
package org.activequant.util.charting;

import java.awt.Font;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

import org.activequant.core.types.TimeStamp;
import org.activequant.data.util.Tuple;
import org.apache.log4j.Logger;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.XYTextAnnotation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.SegmentedTimeline;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.time.TimeSeriesDataItem;

/**
 * 
 * Chart base class, based on JFreeChart<br>
 * <br>
 * <b>History:</b><br> 
 * - [14.08.2007] Created (Ulrich Staudinger)<br> 
 * - [29.09.2007] Removed warnings (Erik Nijkamp)<br>
 * - [31.10.2007] Cleanup and adding methods from derived classes (Ulrich Staudinger)<br>
 * 
 * @author ustaudinger
 */
public class Chart {

    protected final static Logger log = Logger.getLogger(Chart.class);

    /**
     * the underlying chart.
     */
    protected JFreeChart chart;
    /**
     * counter storing the amount of current data sets in use.
     */
    protected List<TimeSeries> datasets = new ArrayList<TimeSeries>();

    /**
     * plain constructor.
     */
    public Chart() {
        chart = ChartFactory.createTimeSeriesChart(null, "", "", null, true, false, false);
    }

    /**
     * overloaded constructor. 
     * @param timeAxisLabel
     * @param valueAxisLabel
     */
    public Chart(String timeAxisLabel, String valueAxisLabel) {
        chart = ChartFactory.createTimeSeriesChart(null, timeAxisLabel, valueAxisLabel, null, true, false, false);
    }

    /**
     * method to add a line series chart to the current chart. 
     * @param title
     * @param dateAndValues
     */
    public void addLineSeriesChart(String title, List<Tuple<TimeStamp, Double>> dateAndValues) {

        // creating a new jfree chart time series object. 
        final TimeSeries ts = new TimeSeries(title, Millisecond.class);

        // iterate over the incoming value tuples and add them.  
        for (Tuple<TimeStamp, Double> tuple : dateAndValues) {
            TimeSeriesDataItem item = new TimeSeriesDataItem(new Millisecond(tuple.getObject1().getDate()),
                    tuple.getObject2());
            ts.addOrUpdate(item.getPeriod(), item.getValue());
        }

        datasets.add(ts);

        // 
        final TimeSeriesCollection dataset = new TimeSeriesCollection(ts);

        // add it to the chart plot. 
        final XYPlot plot1 = chart.getXYPlot();

        // disable all shape rendering. 
        final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
        renderer.setDrawOutlines(false);
        renderer.setUseOutlinePaint(false);
        renderer.setShapesVisible(false);
        // finally add the data set to chart 
        plot1.setDataset(datasets.size(), dataset);
        plot1.setRenderer(datasets.size(), renderer);
    }

    /**
     * Adds or updates a point in the dataset.
     * 
     * @param datasetIndex dataset index (zero-based).
     * @param timeStamp time stamp of the event.
     * @param value event value.
     */
    public void addSeriesDataItem(int datasetIndex, TimeStamp timeStamp, double value) {
        if (datasetIndex >= datasets.size()) {
            throw new IllegalArgumentException(
                    "wrong dataset index: size=" + datasets.size() + ", index=" + datasetIndex);
        }
        TimeSeries ts = datasets.get(datasetIndex);
        ts.addOrUpdate(new Millisecond(timeStamp.getDate()), value);
    }

    /**
     * Deletes data points that are older than given time stamp from <em>all datasets</em>.
     * This allows to keep sliding window of the data with the given width.
     * 
     * @param datasetIndex index of the dataset to truncate.
     * 
     * @param timeStamp truncation threshold.
     */
    public void deleteBefore(TimeStamp timeStamp) {
        for (TimeSeries ts : datasets) {
            int index = ts.getIndex(new Millisecond(timeStamp.getDate()));
            if (index >= 0) {
                ts.delete(0, index);
            }
        }
    }

    /**
     * Deletes data points from a given dataset which are older than the time stamp.
     * This allows to keep sliding window of the data with the given width.
     * 
     * @param datasetIndex index of the dataset to truncate.
     * 
     * @param timeStamp truncation threshold.
     */
    public void deleteBefore(int datasetIndex, TimeStamp timeStamp) {
        if (datasetIndex >= datasets.size()) {
            throw new IllegalArgumentException(
                    "wrong dataset index: size=" + datasets.size() + ", index=" + datasetIndex);
        }
        TimeSeries ts = datasets.get(datasetIndex);
        int index = ts.getIndex(new Millisecond(timeStamp.getDate()));
        if (index >= 0) {
            ts.delete(0, index);
        }
    }

    /**
     * method to add a line series drawing to this chart. 
     * @param title
     * @param dates
     * @param values
     */
    public void addLineSeriesChart(String title, TimeStamp[] dates, double[] values) {
        assert (dates.length == values.length);
        final List<Tuple<TimeStamp, Double>> vals = new ArrayList<Tuple<TimeStamp, Double>>();
        for (int i = 0; i < dates.length; i++) {
            Tuple<TimeStamp, Double> tuple = new Tuple<TimeStamp, Double>(dates[i], values[i]);
            vals.add(tuple);
        }
        this.addLineSeriesChart(title, vals);
    }

    /**
     * use this to add a text annotation to this chart. 
     * @param date
     * @param yValue the vertical position of the text
     * @param text
     */
    public void addTextAnnotation(TimeStamp date, double yValue, String text) {
        chart.getXYPlot().addAnnotation(new XYTextAnnotation(text, date.getDate().getTime(), yValue));
    }

    /**
     * method to add a dot chart.
     * @param title
     * @param dateAndValues
     */
    public void addDotSeriesChart(String title, List<Tuple<TimeStamp, Double>> dateAndValues) {

        if (chart != null) {
            //
            final TimeSeries ts = new TimeSeries(title, Millisecond.class);
            for (Tuple<TimeStamp, Double> tuple : dateAndValues) {
                //
                TimeSeriesDataItem item = new TimeSeriesDataItem(new Millisecond(tuple.getObject1().getDate()),
                        tuple.getObject2());
                ts.addOrUpdate(item.getPeriod(), item.getValue());
            }

            datasets.add(ts);
            final TimeSeriesCollection dataset = new TimeSeriesCollection(ts);

            final XYPlot plot1 = chart.getXYPlot();

            final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
            renderer.setShapesVisible(true);
            renderer.setLinesVisible(false);
            plot1.setDataset(datasets.size(), dataset);
            plot1.setRenderer(datasets.size(), renderer);
        }
    }

    /**
     * Persistencifies this chart to a png file. 
     * 
     * created on 07.05.2006
     * 
     * @param filename
     * @param w
     * @param h
     * @throws Exception
     */
    public void renderToPng(String filename, int w, int h) throws Exception {
        FileOutputStream f = new FileOutputStream(filename);
        ChartUtilities.writeChartAsPNG(f, chart, w, h);
    }

    /**
     * Creates a JFrame that can be displayed on the screen. The returned JFrame
     * is not yet visible. To actually show it, do the following:
     * <ul>
     *   <li><code>setBounds()</code> to set frame bounds.
     *   <li><code>setVisible(true)</code> to show it.
     * </ul> 
     * 
     * @param title frame title.
     * @param scrollPane true is scroll pane is needed.
     * 
     * @return JFrame
     */
    public JFrame getJFrame(String title, boolean scrollPane) {
        return new ChartFrame(title, this.getChart(), scrollPane);
    }

    /**
     * Creates a JFrame that can be displayed on the screen. The returned JFrame
     * is not yet visible. To actually show it, do the following:
     * <ul>
     *   <li><code>setBounds()</code> to set frame bounds.
     *   <li><code>setVisible(true)</code> to show it.
     * </ul> 
     * 
     * @param title frame title.
     * 
     * @return JFrame
     */
    public JFrame getJFrame(String title) {
        return getJFrame(title, false);
    }

    /**
     * helper method to indicate a monday to friday timeline. 
     */
    public void setSuppressWeekends() {
        SegmentedTimeline timeline = SegmentedTimeline.newMondayThroughFridayTimeline();
        final DateAxis axis = (DateAxis) chart.getXYPlot().getDomainAxis();
        axis.setAutoRange(true);
        axis.setTimeline(timeline);
    }

    public XYTextAnnotation getUpArrow(double x, double y) {
        XYTextAnnotation arrow = new XYTextAnnotation(">", x, y);
        arrow.setRotationAngle(Math.PI * 1.5);
        arrow.setFont(new Font("SansSerif", Font.BOLD, 9));
        return arrow;
    }

    public XYTextAnnotation getDownArrow(double x, double y) {
        XYTextAnnotation arrow = new XYTextAnnotation(">", x, y);
        arrow.setRotationAngle(Math.PI * 0.5);
        arrow.setFont(new Font("SansSerif", Font.BOLD, 9));
        return arrow;
    }

    public JFreeChart getChart() {
        return chart;
    }

    public void setChart(JFreeChart chart) {
        this.chart = chart;
    }

}