/* * RapidMiner * * Copyright (C) 2001-2011 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.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; import java.awt.event.MouseEvent; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.swing.JComponent; import org.jfree.chart.JFreeChart; import org.jfree.data.Range; import com.rapidminer.datatable.DataTable; import com.rapidminer.gui.plotter.charts.AbstractChartPanel; import com.rapidminer.gui.plotter.charts.ChartPanelShiftController; import com.rapidminer.gui.plotter.charts.AbstractChartPanel.Selection; import com.rapidminer.gui.plotter.charts.AbstractChartPanel.SelectionListener; import com.rapidminer.operator.ports.InputPort; import com.rapidminer.operator.ports.metadata.ExampleSetMetaData; import com.rapidminer.operator.ports.metadata.MetaData; import com.rapidminer.operator.ports.metadata.ModelMetaData; import com.rapidminer.parameter.ParameterType; import com.rapidminer.parameter.ParameterTypeAttribute; import com.rapidminer.parameter.ParameterTypeDouble; import com.rapidminer.parameter.ParameterTypeList; import com.rapidminer.parameter.ParameterTypeString; import com.rapidminer.parameter.ParameterTypeTupel; import com.rapidminer.tools.container.Pair; /** * Plotter extending this adapter must be able to set their ranges during plotting if the * dimensions name is registered here. * * @author Sebastian Land * */ public abstract class RangeablePlotterAdapter extends LabelRotatingPlotterAdapter implements AxisNameResolver { private static final long serialVersionUID = 1L; public static final String PARAMETER_PREFIX_RANGE_LIST = "range_list"; public static final String PARAMETER_PREFIX_RANGE = "range_"; public static final String PARAMETER_DIMENSION_NAME = "dimension"; public static final String PARAMETER_PREFIX_RANGE_MIN = "range_min"; public static final String PARAMETER_PREFIX_RANGE_MAX = "range_max"; private Map<String, Range> nameRangeMap = new HashMap<String, Range>(); private DataTable dataTable; private CoordinateTransformation coordinateTransformation; private AbstractChartPanel panel = null; private List<SelectionListener> plotterSelectionListener = new LinkedList<SelectionListener>(); public RangeablePlotterAdapter(final PlotterConfigurationModel settings) { super(settings); // adding default zoom listener plotterSelectionListener.add(new SelectionListener() { @Override public void selected(Selection selection, MouseEvent selectionEvent) { for (Pair<String, Range> delimiter: selection.getDelimiters()) { setRange(delimiter.getFirst(), delimiter.getSecond()); } } }); } @Override public List<ParameterType> getAdditionalParameterKeys(InputPort inputPort) { List<ParameterType> types = super.getAdditionalParameterKeys(inputPort); boolean inputDeliversAttributes = false; if (inputPort != null) { MetaData metaData = inputPort.getMetaData(); if (metaData != null && (metaData instanceof ExampleSetMetaData || metaData instanceof ModelMetaData)) { inputDeliversAttributes = true; } } if (inputDeliversAttributes) { types.add(new ParameterTypeList(PARAMETER_PREFIX_RANGE_LIST, "Defines the ranges for the given attribute", new ParameterTypeAttribute(PARAMETER_DIMENSION_NAME, "This is the name of the dimension, the range should be applied onto.", inputPort), new ParameterTypeTupel(PARAMETER_PREFIX_RANGE , "Defines the range of the corresponding axis.", new ParameterTypeDouble(PARAMETER_PREFIX_RANGE_MIN, "Defines the lower bound of the axis.", Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), new ParameterTypeDouble(PARAMETER_PREFIX_RANGE_MAX, "Defines the upper bound of the axis.", Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY)))); } else { types.add(new ParameterTypeList(PARAMETER_PREFIX_RANGE_LIST, "Defines the ranges for the given attribute", new ParameterTypeString(PARAMETER_DIMENSION_NAME, "This is the name of the dimension, the range should be applied onto."), new ParameterTypeTupel(PARAMETER_PREFIX_RANGE , "Defines the range of the corresponding axis.", new ParameterTypeDouble(PARAMETER_PREFIX_RANGE_MIN, "Defines the lower bound of the axis.", Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), new ParameterTypeDouble(PARAMETER_PREFIX_RANGE_MAX, "Defines the upper bound of the axis.", Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY)))); } return types; } /** * This method returns the range for the axis if was defined by parameters or null if automatic ranging should be * used. */ public Range getRangeForDimension(int dimension) { if (dimension >= 0 && dimension < dataTable.getNumberOfColumns()) return nameRangeMap.get(PlotterAdapter.transformParameterName(dataTable.getColumnName(dimension))); return null; } public Range getRangeForName(String columnName) { return nameRangeMap.get(PlotterAdapter.transformParameterName(columnName)); } @Override public final void setDataTable(DataTable dataTable) { this.dataTable = dataTable; dataTableSet(); } public abstract void dataTableSet(); protected DataTable getDataTable() { return dataTable; } /** * This is a convenience method for setting the correct range parameter */ public void setRange(int dimension, Range range) { setRange(dataTable.getColumnName(dimension), range); } public void setRange(String columnName, Range range) { // inserting in map nameRangeMap.put(PlotterAdapter.transformParameterName(columnName), range); // translating current ranges to string List<String[]> entryList = new LinkedList<String[]>(); for (String dimensionName: nameRangeMap.keySet()) { Range currentRange = nameRangeMap.get(dimensionName); String[] entry = new String[2]; entry[0] = dimensionName; entry[1] = ParameterTypeTupel.transformTupel2String(new Pair<String, String>(currentRange.getLowerBound()+"", currentRange.getUpperBound()+"")); entryList.add(entry); } // finally set it in the settings settings.setParameterAsString(PARAMETER_PREFIX_RANGE_LIST, ParameterTypeList.transformList2String(entryList)); } @Override public void setAdditionalParameter(String key, String value) { super.setAdditionalParameter(key, value); if (key.startsWith(PARAMETER_PREFIX_RANGE_LIST)) { List<String[]> dimensionRangePairs = ParameterTypeList.transformString2List(value); for (String[] dimensionRangePair: dimensionRangePairs) { String[] rangeTupel = ParameterTypeTupel.transformString2Tupel(dimensionRangePair[1]); if (rangeTupel.length == 2) { try { Range range = new Range(Double.parseDouble(rangeTupel[0]), Double.parseDouble(rangeTupel[1])); nameRangeMap.put(PlotterAdapter.transformParameterName(dimensionRangePair[0]), range); updatePlotter(); } catch (NumberFormatException e) { } } } return; } } protected AbstractChartPanel createPanel(JFreeChart chart) { panel = new AbstractChartPanel(chart, getWidth(), getHeight() - MARGIN); panel.registerAxisNameResolver(this); if (coordinateTransformation != null) panel.setCoordinateTransformation(coordinateTransformation); // adding all listener for (SelectionListener listener: plotterSelectionListener) panel.registerSelectionListener(listener); panel.registerSelectionListener(new SelectionListener() { @Override public void selected(Selection selection, MouseEvent selectionEvent) { for (Pair<String, Range> delimiter: selection.getDelimiters()) { setRange(delimiter.getFirst(), delimiter.getSecond()); } dataTable.setSelection(selection); } }); final ChartPanelShiftController controller = new ChartPanelShiftController(panel); panel.addMouseListener(controller); panel.addMouseMotionListener(controller); return panel; } public void registerPlotterSelectionListener(SelectionListener listener) { this.plotterSelectionListener.add(listener); if (panel != null) panel.registerSelectionListener(listener); } public void clearPlotterSelectionListener() { this.plotterSelectionListener.clear(); if (panel != null) panel.clearSelectionListener(); } @Override public void setCoordinateTransformation(CoordinateTransformation transformation) { this.coordinateTransformation = transformation; if (panel != null) panel.setCoordinateTransformation(transformation); } @Override public final JComponent getPlotter() { if (panel == null) updatePlotter(); return panel; } public AbstractChartPanel getPlotterPanel() { return panel; } }