/* * RapidMiner * * Copyright (C) 2001-2008 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.Color; import java.awt.Graphics; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; import com.rapidminer.datatable.DataTable; import com.rapidminer.datatable.DataTableRow; import com.rapidminer.gui.MainFrame; import com.rapidminer.tools.LogService; import com.rapidminer.tools.math.MathFunctions; /** This plotter can be used to create 2D histogram plots for a single column colorized by * another column. * * @author Ingo Mierswa * @version $Id: ColorHistogramPlotter.java,v 1.7 2008/07/03 19:17:12 ingomierswa Exp $ */ public class ColorHistogramPlotter extends HistogramPlotter { private static final long serialVersionUID = -2185573642487757891L; private int columnIndex = -1; private int colorIndex = -1; public ColorHistogramPlotter() { super(); } public ColorHistogramPlotter(DataTable dataTable) { super(dataTable); } public int getNumberOfAxes() { return 1; } public int getAxis(int axis) { return columnIndex; } public String getAxisName(int index) { if (index == 0) return "Histogram"; else return "empty"; } public void setAxis(int index, int dimension) { if (this.columnIndex != dimension) { this.columnIndex = dimension; this.currentXPlotterColumn = this.columnIndex; repaint(); } } public void setPlotColumn(int index, boolean plot) { colorIndex = index; repaint(); } public String getPlotName() { return "Color"; } public boolean getPlotColumn(int index) { return index == colorIndex; } /** Overrides the method of the super type HistogramPlotter which allows for multiple plot selections. */ public int getValuePlotSelectionType() { return SINGLE_SELECTION; } public void prepareData() { minX = Double.POSITIVE_INFINITY; maxX = Double.NEGATIVE_INFINITY; minY = Double.POSITIVE_INFINITY; maxY = Double.NEGATIVE_INFINITY; allPlots.clear(); if ((columnIndex != -1) && (colorIndex != -1)) { // create value map Map<Double,List<Double>> valueMap = new TreeMap<Double,List<Double>>(); synchronized (dataTable) { Iterator<DataTableRow> i = dataTable.iterator(); while (i.hasNext()) { DataTableRow row = i.next(); double columnValue = row.getValue(columnIndex); this.minX = MathFunctions.robustMin(minX, columnValue); this.maxX = MathFunctions.robustMax(maxX, columnValue); double colorValue = row.getValue(colorIndex); List<Double> values = valueMap.get(colorValue); if (values == null) { values = new LinkedList<Double>(); values.add(columnValue); valueMap.put(colorValue, values); } else { values.add(columnValue); } } String maxClassesProperty = System.getProperty(MainFrame.PROPERTY_RAPIDMINER_GUI_PLOTTER_COLORS_CLASSLIMIT); int maxClasses = 10; try { if (maxClassesProperty != null) maxClasses = Integer.parseInt(maxClassesProperty); } catch (NumberFormatException e) { LogService.getGlobal().log("Color histogram: cannot parse property 'rapidminer.gui.plotter.colors.classlimit', using maximal 10 different classes.", LogService.WARNING); } if (valueMap.size() <= maxClasses) { // collect actual data and create a histogram for each different color value Iterator<Map.Entry<Double,List<Double>>> it = valueMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry<Double,List<Double>> e = it.next(); Double key = e.getKey(); int colorValue = (int)key.doubleValue(); Color color = getPointColor(colorValue / (valueMap.size() - 1.0d)); color = new Color(color.getRed(), color.getGreen(), color.getBlue(), RectangleStyle.ALPHA); RectangleStyle style = new RectangleStyle(color); Bins bins = new Bins(style, minX, maxX, this.binNumber); allPlots.put(colorValue, bins); List<Double> values = e.getValue(); Iterator<Double> v = values.iterator(); while (v.hasNext()) { bins.addPoint(v.next()); this.maxY = Math.max(bins.getMaxCounter(), this.maxY); } } } else { // too many classes --> super method in order to create usual non-colored histogram super.prepareData(); LogService.getGlobal().log("Color histogram: cannot create colored histogram since the number of different values (" + valueMap.size() + ") is too large. Allowed are " + maxClassesProperty + " different values (edit this limit in the properties dialog).", LogService.WARNING); } } } else { // no plots selected --> do nothing this.maxY = 1; } // rescale counters for logscale? if (isLogScale()) { this.maxY = 0.0d; for (Bins bins : allPlots.values()) { for (Bin bin : bins) { double counter = bin.getCounter(); if (counter > 0.0d) { double newValue = Math.log(counter); bin.setCounter(newValue); this.maxY = Math.max(newValue, this.maxY); } } } } this.minY = 0; if (dataTable.getNumberOfRows() == 0) { minX = 0; maxX = 1; minY = 0; maxY = 1; } if (minX == maxX) { minX -= 0.5; maxX += 0.5; } if (minY == maxY) { minY -= 0.5; maxY += 0.5; } xTicSize = getTicSize(dataTable, columnIndex, minX, maxX); yTicSize = getNumericalTicSize(minY, maxY); minX = Math.floor(minX / xTicSize) * xTicSize; maxX = Math.ceil(maxX / xTicSize) * xTicSize; minY = Math.floor(minY / yTicSize) * yTicSize; maxY = Math.ceil(maxY / yTicSize) * yTicSize; } public void paintComponent(Graphics g) { super.paintComponent(g); if (drawLegend && (allPlots.size() > 0)) drawLegend(g, dataTable, colorIndex, 50, RectangleStyle.ALPHA); } }