net.bioclipse.chart.ChartUtils.java Source code

Java tutorial

Introduction

Here is the source code for net.bioclipse.chart.ChartUtils.java

Source

/* ***************************************************************************
 * Copyright (c) 2008 Bioclipse Project
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 *****************************************************************************/

package net.bioclipse.chart;

import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import net.bioclipse.chart.events.CellChangeListener;
import net.bioclipse.chart.events.CellChangeProvider;
import net.bioclipse.chart.events.CellChangedEvent;
import net.bioclipse.chart.events.CellData;
import net.bioclipse.chart.events.CellSelection;
import net.bioclipse.model.ChartConstants;
import net.bioclipse.model.ChartDescriptor;
import net.bioclipse.model.ChartManager;
import net.bioclipse.model.ChartModelListener;
import net.bioclipse.model.ChartSelection;
import net.bioclipse.model.PcmLineChartDataset;
import net.bioclipse.plugins.views.ChartView;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.event.PlotChangeEvent;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.statistics.HistogramDataset;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.data.xy.XYDataset;

/**
 * This is a utility class with static methods for plotting data on the chart plugins
 * chart view. Charts generated with these methods are displayed in ChartView
 * 
 * This is the controller of the model and view
 * 
 * @see net.bioclipse.plugins.views.ChartView
 * @author EskilA
 *
 */
public class ChartUtils {
    public static JFreeChart chart;
    private final static String CHART_VIEW_ID = "net.bioclipse.plugins.views.ChartView";
    private static double[][] values;
    private static ChartView view;
    private static String[] nameOfObs;
    static String yColumn;
    static String xColumn;
    static ChartSelection cs;
    private static int currentPlotType = -1;
    static int[] indices;
    private static ChartManager chartManager = new ChartManager();

    private static List<CellChangeProvider> providers = new ArrayList<CellChangeProvider>();
    private static List<CellChangeListener> listeners = new ArrayList<CellChangeListener>();

    /**
     * Displays data in a line plot
     * 
     * @param xValues x values of points
     * @param yValues y values of points
     * @param xLabel X axis label
     * @param yLabel Y axis label
     * @param title Chart title
     * @param analysisMatrixEditor 
     * @param indices 
     */
    public static void linePlot(double[] xValues, double[] yValues, String xLabel, String yLabel, String title,
            int[] indices, IEditorPart dataSource) {
        setupData(xValues, yValues, xLabel, yLabel, title);

        PcmLineChartDataset dataset = new PcmLineChartDataset(values, nameOfObs, xLabel, yLabel, "", title, null);
        chart = ChartFactory.createXYLineChart(title, xLabel, yLabel, dataset, PlotOrientation.VERTICAL, true, true,
                false);

        ChartDescriptor cd = new ChartDescriptor(dataSource, indices, ChartConstants.LINE_PLOT, xLabel, yLabel);
        chartManager.put(chart, cd);

        view.display(chart);
    }

    public static void updateSelection(ChartSelection cs) {
        view.setSelection(cs);
    }

    /** If you want to map points on the plot to cells in a spreadsheet you need to
     *  set the columns from where you got your data
     * 
     * @param xColumn the label of the xColumn in the spreadsheet
     * @param yColumn the label of the yColumn in the spreadsheet
     * 
     * @throws IllegalArgumentException if xColumn or yColumn equals null
     */
    public static void setDataColumns(String xColumn, String yColumn) throws IllegalArgumentException {
        if (xColumn == null || yColumn == null)
            throw new IllegalArgumentException("xColumn or yColumn can not be null");
        ChartUtils.xColumn = xColumn;
        ChartUtils.yColumn = yColumn;
    }

    /**
     * Marks a plotted point
     * @param series
     * @param index
     * @deprecated
     */
    public static void markPoints(CellSelection cs) {
        if (chart != null && ChartUtils.currentPlotType == ChartConstants.SCATTER_PLOT) {
            ScatterPlotRenderer renderer = (ScatterPlotRenderer) chart.getXYPlot().getRenderer();
            Iterator<CellData> iter = cs.iterator();

            renderer.clearMarkedPoints();

            while (iter.hasNext()) {
                CellData cd = iter.next();
                if (cd.getColName().equals(ChartUtils.xColumn) || cd.getColName().equals(ChartUtils.yColumn)) {
                    renderer.addMarkedPoint(0, cd.getRowIndex());
                    chart.plotChanged(new PlotChangeEvent(chart.getPlot()));
                }
            }
        }
    }

    /**
     * Displays data in a scatter plot
     * 
     * @param xValues x values of points
     * @param yValues y values of points
     * @param xLabel X axis label
     * @param yLabel Y axis label
     * @param title plot title
     */
    public static void scatterPlot(double[] xValues, double[] yValues, String xLabel, String yLabel, String title) {
        setupData(xValues, yValues, xLabel, yLabel, title);
        DefaultXYDataset dataset = new DefaultXYDataset();
        dataset.addSeries(1, values);
        chart = ChartFactory.createScatterPlot(title, xLabel, yLabel, dataset, PlotOrientation.VERTICAL, false,
                false, false);
        view.display(chart);
        ChartUtils.currentPlotType = ChartConstants.SCATTER_PLOT;
    }

    /**
     * Displays data in a scatter plot
     * 
     * @param xValues x values of points
     * @param yValues y values of points
     * @param xLabel X axis label
     * @param yLabel Y axis label
     * @param title plot title
     * @param indices 
     * @param dataSource The editor from which the charts data comes from, used so indices are mapped to the right editor 
     */
    public static void scatterPlot(double[] xValues, double[] yValues, String xLabel, String yLabel, String title,
            int[] indices, IEditorPart dataSource) {
        setupData(xValues, yValues, xLabel, yLabel, title);
        DefaultXYDataset dataset = new DefaultXYDataset();
        dataset.addSeries(1, values);

        chart = ChartFactory.createScatterPlot(title, xLabel, yLabel, dataset, PlotOrientation.VERTICAL, false,
                false, false);

        ChartDescriptor descriptor = new ChartDescriptor(dataSource, indices, ChartConstants.SCATTER_PLOT, xLabel,
                yLabel);

        chartManager.put(chart, descriptor);

        view.display(chart);
    }

    /**
     * Displays histogram of the values in ChartView
     * 
     * @param values Data values
     * @param bins Number of bins to use
     * @param xLabel X axis label
     * @param yLabel Y axis label
     * @param title Histogram title
     */
    public static void histogram(double[] values, int bins, String xLabel, String yLabel, String title,
            IEditorPart dataSource) {
        setupData(values, null, xLabel, yLabel, title);
        HistogramDataset histogramData = new HistogramDataset();
        histogramData.addSeries(1, values, bins);
        chart = ChartFactory.createHistogram(title, xLabel, yLabel, histogramData, PlotOrientation.VERTICAL, false,
                false, false);

        ChartDescriptor descriptor = new ChartDescriptor(dataSource, null, ChartConstants.HISTOGRAM, xLabel,
                yLabel);

        chartManager.put(chart, descriptor);

        view.display(chart);
        ChartUtils.currentPlotType = ChartConstants.HISTOGRAM;
    }

    /**
     * Sets up common data
     * @param xValues   
     * @param yValues
     * @param xLabel X axis label
     * @param yLabel Y axis label
     * @param title Chart title
     */
    private static void setupData(double[] xValues, double[] yValues, String xLabel, String yLabel, String title) {
        values = new double[2][];
        values[0] = xValues;
        values[1] = yValues;

        view = null;

        nameOfObs = new String[xValues.length];
        for (int i = 0; i < xValues.length; i++) {
            nameOfObs[i] = "" + i;
        }

        try {
            view = (ChartView) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
                    .showView(CHART_VIEW_ID);
        } catch (PartInitException e) {
            e.printStackTrace();
        }
    }

    /**
     * Plot time series
     * 
     * @param dataValues
     * @param timeValues
     * @param xLabel X axis label
     * @param yLabel Y axis label
     * @param title Chart title
     * @param dataSource 
     * @param indices 
     */
    public static void timeSeries(double[] dataValues, double[] timeValues, String xLabel, String yLabel,
            String title, int[] indices, IEditorPart dataSource) {
        setupData(dataValues, timeValues, xLabel, yLabel, title);
        DefaultXYDataset dataset = new DefaultXYDataset();
        dataset.addSeries(1, values);
        chart = ChartFactory.createTimeSeriesChart(title, xLabel, yLabel, (XYDataset) dataset, false, false, false);

        ChartDescriptor descriptor = new ChartDescriptor(dataSource, indices, ChartConstants.TIME_SERIES, xLabel,
                yLabel);
        chartManager.put(chart, descriptor);

        view.display(chart);
        ChartUtils.currentPlotType = ChartConstants.TIME_SERIES;
    }

    /**
     * Creates a bar plot and displays it in ChartView
     * 
     * @param dataValues MxN matrix containing series x categories
     * @param seriesLabels text labels for the series
     * @param categoryLabels text labels for the categories
     * @param xLabel Domain label
     * @param yLabel Range label
     * @param title Title of the plot
     */
    public static void barPlot(double[][] dataValues, String[] seriesLabels, String[] categoryLabels, String xLabel,
            String yLabel, String title) {
        DefaultCategoryDataset dataSet = new DefaultCategoryDataset();

        //Load data into the data set
        for (int i = 0; i < dataValues.length; i++) {
            for (int j = 0; j < dataValues[i].length; j++) {
                dataSet.addValue(dataValues[i][j], i < seriesLabels.length ? seriesLabels[i] : "N/A",
                        j < categoryLabels.length ? categoryLabels[j] : "N/A");
            }
        }

        //Use the chart factory to set up our bar chart
        JFreeChart chart = ChartFactory.createBarChart(title, xLabel, yLabel, dataSet, PlotOrientation.VERTICAL,
                true, //Legend
                true, //Tooltips
                false); //URLS

        view.display(chart);
    }

    /**
     * Utility method for converting JFreeChart to an image
     * @param parent used for color correction 
     * @param chart the chart to be made into an image
     * @param width image width
     * @param height image height
     * @return SWT Image of the chart 
     */
    public static Image createChartImage(Composite parent, JFreeChart chart, int width, int height) {
        // Color adjustment

        Color swtBackground = parent.getBackground();
        java.awt.Color awtBackground = new java.awt.Color(swtBackground.getRed(), swtBackground.getGreen(),
                swtBackground.getRed());
        chart.setBackgroundPaint(awtBackground);

        // Draw the chart in an AWT buffered image
        BufferedImage bufferedImage = chart.createBufferedImage(width, height, null);

        // Get the data buffer of the image
        DataBuffer buffer = bufferedImage.getRaster().getDataBuffer();
        DataBufferInt intBuffer = (DataBufferInt) buffer;

        // Copy the data from the AWT buffer to a SWT buffer
        PaletteData paletteData = new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF);
        ImageData imageData = new ImageData(width, height, 32, paletteData);
        for (int bank = 0; bank < intBuffer.getNumBanks(); bank++) {
            int[] bankData = intBuffer.getData(bank);
            imageData.setPixels(0, bank, bankData.length, bankData, 0);
        }

        // Create an SWT image
        return new Image(parent.getDisplay(), imageData);
    }

    public static void registerCellChangeProvider(CellChangeProvider provider) {
        if (!providers.contains(provider)) {
            providers.add(provider);
        }
    }

    public static void registerCellChangeListener(CellChangeListener listener) {
        if (!listeners.contains(listener)) {
            listeners.add(listener);
        }
    }

    //These methods delegate to the model
    //TODO:  Write general Interface/Abstract class for model so its not hardwired to ChartManager
    public static ChartDescriptor getChartDescriptor(JFreeChart key) {
        return chartManager.get(key);
    }

    public static JFreeChart getActiveChart() {
        return chartManager.getActiveChart();
    }

    public static ChartDescriptor put(JFreeChart chart, ChartDescriptor descriptor) {
        return chartManager.put(chart, descriptor);
    }

    public static void setActiveChart(JFreeChart chart) {
        chartManager.setActiveChart(chart);
    }

    public static void addListener(ChartModelListener listener) {
        chartManager.addListener(listener);
    }

    public static void removeListener(ChartModelListener listener) {
        chartManager.removeListener(listener);
    }

    public static ChartDescriptor remove(Object arg0) {
        return chartManager.remove(arg0);
    }

    public static Collection<ChartDescriptor> values() {
        return chartManager.values();
    }

    public static Set<JFreeChart> keySet() {
        return chartManager.keySet();
    }

    public static void handleCellChangeEvent(CellChangedEvent e) {
        //      Iterator<CellChangeListener> iterator = listeners.iterator();
        //      while( iterator.hasNext() )
        //      {
        //         CellChangeListener listener = iterator.next();
        //         listener.handleCellChangeEvent(e);
        //      }
        Set<JFreeChart> keySet = chartManager.keySet();
        Iterator<JFreeChart> iterator = keySet.iterator();
        while (iterator.hasNext()) {
            JFreeChart chart = iterator.next();

            ChartDescriptor desc = chartManager.get(chart);

            String domainLabel = desc.getXLabel();
            String rangeLabel = desc.getYLabel();
            CellData data = e.getCellData();

            if (domainLabel.equals(data.getColName()) || rangeLabel.equals(data.getColName())) {
                DefaultXYDataset dataset = (DefaultXYDataset) chart.getXYPlot().getDataset();
                int itemCount = dataset.getItemCount(0);
                double[] yValues = new double[itemCount];
                double[] xValues = new double[itemCount];
                for (int i = 0; i < itemCount; i++) {
                    double x = dataset.getXValue(0, i);
                    double y = dataset.getYValue(0, i);
                    xValues[i] = x;
                    yValues[i] = y;
                }
                int indices[] = desc.getSourceIndices();
                if (domainLabel.equals(e.getCellData().getColName())) {
                    int rowIndex = data.getRowIndex();
                    for (int i = 0; i < indices.length; i++) {
                        if (indices[i] == rowIndex) {
                            xValues[i] = data.getValue();
                        }
                    }
                } else if (rangeLabel.equals(e.getCellData().getColName())) {
                    int rowIndex = data.getRowIndex();
                    for (int i = 0; i < indices.length; i++) {
                        if (indices[i] == rowIndex) {
                            yValues[i] = data.getValue();
                        }
                    }
                }
                double[][] chartData = new double[2][];
                chartData[0] = xValues;
                chartData[1] = yValues;

                dataset.getSeriesKey(0);
                Comparable seriesKey = dataset.getSeriesKey(0);

                dataset.removeSeries(seriesKey);
                dataset.addSeries(seriesKey, chartData);
            }
        }
    }
}