com.rapidminer.gui.plotter.charts.ParallelPlotter2.java Source code

Java tutorial

Introduction

Here is the source code for com.rapidminer.gui.plotter.charts.ParallelPlotter2.java

Source

/**
 * Copyright (C) 2001-2015 by RapidMiner and the contributors
 *
 * Complete list of developers available at our web site:
 *
 *      http://rapidminer.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/.
 */
package com.rapidminer.gui.plotter.charts;

import com.rapidminer.datatable.DataTable;
import com.rapidminer.datatable.DataTableRow;
import com.rapidminer.gui.plotter.LocalNormalizationPlotterAdapter;
import com.rapidminer.gui.plotter.PlotterConfigurationModel;
import com.rapidminer.tools.Tools;
import com.rapidminer.tools.math.MathFunctions;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.geom.Rectangle2D;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JComponent;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.LegendItem;
import org.jfree.chart.LegendItemCollection;
import org.jfree.chart.LegendItemSource;
import org.jfree.chart.axis.SymbolAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.block.BlockBorder;
import org.jfree.chart.block.BlockResult;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.HorizontalAlignment;
import org.jfree.ui.RectangleEdge;

/**
 * This is the new parallel plotter.
 * 
 * @author Ingo Mierswa
 */
public class ParallelPlotter2 extends LocalNormalizationPlotterAdapter {

    private static final long serialVersionUID = -8763693366081949249L;

    /** The currently used data table object. */
    private transient DataTable dataTable;

    /** The data set used for the plotter. */
    private XYSeriesCollection dataset = null;

    /** The column which is used for the values. */
    private int colorColumn = -1;

    private String[] domainAxisMap = null;

    private ChartPanel panel = new ChartPanel(null);

    private double[] colorMap = null;

    public ParallelPlotter2(final PlotterConfigurationModel settings) {
        super(settings);
        setBackground(Color.white);
    }

    public ParallelPlotter2(PlotterConfigurationModel settings, DataTable dataTable) {
        this(settings);
        setDataTable(dataTable);
    }

    @Override
    public JComponent getPlotter() {
        return panel;
    }

    private static JFreeChart createChart(XYDataset dataset) {

        // create the chart...
        JFreeChart chart = ChartFactory.createXYLineChart(null, // chart title
                null, // x axis label
                null, // y axis label
                dataset, // data
                PlotOrientation.VERTICAL, false, // include legend
                true, // tooltips
                false // urls
        );

        chart.setBackgroundPaint(Color.white);

        // get a reference to the plot for further customization...
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setBackgroundPaint(Color.WHITE);

        ValueAxis valueAxis = plot.getRangeAxis();
        valueAxis.setLabelFont(LABEL_FONT_BOLD);
        valueAxis.setTickLabelFont(LABEL_FONT);

        return chart;
    }

    @Override
    public void setDataTable(DataTable dataTable) {
        super.setDataTable(dataTable);
        this.dataTable = dataTable;
        updatePlotter();
    }

    @Override
    public void setPlotColumn(int index, boolean plot) {
        if (plot) {
            this.colorColumn = index;
        } else {
            this.colorColumn = -1;
        }
        updatePlotter();
    }

    @Override
    public boolean getPlotColumn(int index) {
        return colorColumn == index;
    }

    @Override
    public String getPlotName() {
        return "Color Column";
    }

    @Override
    public int getNumberOfAxes() {
        return 0;
    }

    private void prepareData() {
        this.dataset = new XYSeriesCollection();

        // calculate min and max
        int columns = this.dataTable.getNumberOfColumns();
        double[] min = new double[columns];
        double[] max = new double[columns];
        if (isLocalNormalized()) {
            for (int c = 0; c < columns; c++) {
                min[c] = Double.POSITIVE_INFINITY;
                max[c] = Double.NEGATIVE_INFINITY;
            }

            synchronized (dataTable) {
                Iterator<DataTableRow> i = dataTable.iterator();
                while (i.hasNext()) {
                    DataTableRow row = i.next();
                    for (int c = 0; c < dataTable.getNumberOfColumns(); c++) {
                        double value = row.getValue(c);
                        min[c] = MathFunctions.robustMin(min[c], value);
                        max[c] = MathFunctions.robustMax(max[c], value);
                    }
                }
            }
        }

        this.domainAxisMap = null;
        synchronized (dataTable) {
            this.colorMap = new double[dataTable.getNumberOfRows()];

            Iterator<DataTableRow> i = this.dataTable.iterator();
            int idCounter = 0;

            while (i.hasNext()) {
                DataTableRow row = i.next();
                String id = row.getId();
                if (id == null) {
                    id = (idCounter + 1) + "";
                }

                XYSeries series = new XYSeries(id, false, false);
                int counter = 0;
                for (int column = 0; column < dataTable.getNumberOfColumns(); column++) {
                    if ((!dataTable.isSpecial(column)) && (column != colorColumn)) {
                        double value = row.getValue(column);
                        if (isLocalNormalized()) {
                            value = (value - min[column]) / (max[column] - min[column]);
                        }
                        series.add(counter, value);
                        counter++;
                    }
                }

                if (colorColumn >= 0) {
                    this.colorMap[idCounter] = row.getValue(colorColumn);
                }

                this.dataset.addSeries(series);
                idCounter++;
            }
        }

        if (domainAxisMap == null) {
            List<String> domainValues = new LinkedList<>();
            for (int column = 0; column < dataTable.getNumberOfColumns(); column++) {
                if ((!dataTable.isSpecial(column)) && (column != colorColumn)) {
                    domainValues.add(dataTable.getColumnName(column));
                }
            }
            this.domainAxisMap = new String[domainValues.size()];
            domainValues.toArray(this.domainAxisMap);
        }
    }

    @Override
    public void updatePlotter() {
        prepareData();

        JFreeChart chart = createChart(this.dataset);

        // set the background color for the chart...
        chart.setBackgroundPaint(Color.white);

        // general plot settings
        XYPlot plot = chart.getXYPlot();
        plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
        plot.setRangeGridlinePaint(Color.LIGHT_GRAY);

        // domain axis
        SymbolAxis axis = null;
        if (this.dataTable.isSupportingColumnWeights()) {
            List<Double> weightList = new LinkedList<>();
            for (int column = 0; column < dataTable.getNumberOfColumns(); column++) {
                if ((!dataTable.isSpecial(column)) && (column != colorColumn)) {
                    weightList.add(this.dataTable.getColumnWeight(column));
                }
            }
            double[] weights = new double[weightList.size()];
            int index = 0;
            for (Double d : weightList) {
                weights[index++] = d;
            }
            axis = new WeightBasedSymbolAxis(null, domainAxisMap, weights);
        } else {
            axis = new SymbolAxis(null, domainAxisMap);
        }
        axis.setTickLabelFont(LABEL_FONT);
        axis.setLabelFont(LABEL_FONT_BOLD);

        // rotate labels
        if (isLabelRotating()) {
            axis.setTickLabelsVisible(true);
            axis.setVerticalTickLabels(true);
        }

        chart.getXYPlot().setDomainAxis(axis);

        // renderer
        final ColorizedLineAndShapeRenderer renderer = new ColorizedLineAndShapeRenderer(this.colorMap);
        plot.setRenderer(renderer);

        // legend settings
        if ((colorColumn >= 0) && (this.dataTable.isNominal(colorColumn))) {
            final LegendItemCollection legendItemCollection = new LegendItemCollection();
            for (int i = 0; i < this.dataTable.getNumberOfValues(colorColumn); i++) {
                legendItemCollection.add(new LegendItem(this.dataTable.mapIndex(colorColumn, i), null, null, null,
                        new Rectangle2D.Double(0, 0, 7, 7),
                        getColorProvider()
                                .getPointColor(i / (double) (this.dataTable.getNumberOfValues(colorColumn) - 1)),
                        new BasicStroke(0.75f), Color.GRAY));
            }
            chart.addLegend(new LegendTitle(new LegendItemSource() {

                @Override
                public LegendItemCollection getLegendItems() {
                    return legendItemCollection;
                }
            }));

            LegendTitle legend = chart.getLegend();
            if (legend != null) {
                legend.setPosition(RectangleEdge.TOP);
                legend.setFrame(BlockBorder.NONE);
                legend.setHorizontalAlignment(HorizontalAlignment.LEFT);
                legend.setItemFont(LABEL_FONT);
            }
        } else if (colorColumn >= 0) {
            chart.addLegend(new LegendTitle(new LegendItemSource() {

                @Override
                public LegendItemCollection getLegendItems() {
                    LegendItemCollection itemCollection = new LegendItemCollection();
                    itemCollection.add(new LegendItem("Dummy"));
                    return itemCollection;
                }
            }) {

                private static final long serialVersionUID = 1288380309936848376L;

                @Override
                public Object draw(java.awt.Graphics2D g2, java.awt.geom.Rectangle2D area,
                        java.lang.Object params) {
                    if (dataTable.isDate(colorColumn) || dataTable.isTime(colorColumn)
                            || dataTable.isDateTime(colorColumn)) {
                        drawSimpleDateLegend(g2, (int) (area.getCenterX() - 170), (int) (area.getCenterY() + 7),
                                dataTable, colorColumn, renderer.getMinColorValue(), renderer.getMaxColorValue());
                        return new BlockResult();
                    } else {
                        final String minColorString = Tools.formatNumber(renderer.getMinColorValue());
                        final String maxColorString = Tools.formatNumber(renderer.getMaxColorValue());
                        drawSimpleNumericalLegend(g2, (int) (area.getCenterX() - 90), (int) (area.getCenterY() + 7),
                                dataTable.getColumnName(colorColumn), minColorString, maxColorString);
                        return new BlockResult();
                    }
                }

                @Override
                public void draw(java.awt.Graphics2D g2, java.awt.geom.Rectangle2D area) {
                    draw(g2, area, null);
                }

            });
        }

        // chart panel
        if (panel instanceof AbstractChartPanel) {
            panel.setChart(chart);
        } else {
            panel = new AbstractChartPanel(chart, getWidth(), getHeight() - MARGIN);
            final ChartPanelShiftController controller = new ChartPanelShiftController(panel);
            panel.addMouseListener(controller);
            panel.addMouseMotionListener(controller);
        }

        // ATTENTION: WITHOUT THIS WE GET SEVERE MEMORY LEAKS!!!
        panel.getChartRenderingInfo().setEntityCollection(null);
    }

    @Override
    public JComponent getOptionsComponent(int index) {
        if (index == 0) {
            return getLocalNormalizationComponent();
        } else if (index == 1) {
            return getRotateLabelComponent();
        } else {
            return null;
        }
    }

    @Override
    public String getPlotterName() {
        return PlotterConfigurationModel.PARALLEL_PLOT;
    }
}