/* * 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.operator.visualization.dependencies; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.NumberFormat; import javax.swing.ButtonGroup; import javax.swing.Icon; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JTable; import Jama.Matrix; import com.rapidminer.datatable.DataTable; import com.rapidminer.datatable.DataTablePairwiseMatrixExtractionAdapter; import com.rapidminer.datatable.DataTableSymmetricalMatrixAdapter; import com.rapidminer.example.Attribute; import com.rapidminer.example.ExampleSet; import com.rapidminer.gui.plotter.PlotterPanel; import com.rapidminer.gui.tools.CellColorProviderScaled; import com.rapidminer.gui.tools.ExtendedFixedColumnJTable; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.gui.viewer.DataTableViewer; import com.rapidminer.gui.viewer.SymmetricalMatrixViewerTableModel; import com.rapidminer.operator.IOContainer; import com.rapidminer.operator.ResultObjectAdapter; import com.rapidminer.tools.Tools; /** * A simple symmetrical matrix which can be used for correlation or covariance matrices. * A special constructor for the attributes of an example set is provided. * * @author Ingo Mierswa * @version $Id: SymmetricalMatrix.java,v 1.1 2008/08/25 08:10:33 ingomierswa Exp $ */ public class SymmetricalMatrix extends ResultObjectAdapter { private static final long serialVersionUID = -5498982791125720765L; private static final int MAX_NUMBER_OF_RESULT_STRING_ATTRIBUTES = 20; private static final String RESULT_ICON_NAME = "table.png"; private static Icon resultIcon = null; static { resultIcon = SwingTools.createIcon("16/" + RESULT_ICON_NAME); } private Matrix matrix; private String[] columnNames; private NumberFormat formatter; private String name; public SymmetricalMatrix(String name, String[] columnNames) { this(name, columnNames, new Matrix(columnNames.length, columnNames.length)); } public SymmetricalMatrix(String name, String[] columnNames, Matrix matrix) { this.name = name; formatter = NumberFormat.getInstance(); formatter.setMaximumFractionDigits(3); formatter.setMinimumFractionDigits(3); this.columnNames = columnNames; this.matrix = matrix; } public SymmetricalMatrix(String name, ExampleSet exampleSet) { this(name, getColumnNames(exampleSet)); } public String getColumnName(int index) { return this.columnNames[index]; } private static String[] getColumnNames(ExampleSet exampleSet) { String[] attributeNames = new String[exampleSet.getAttributes().size()]; int counter = 0; for (Attribute attribute : exampleSet.getAttributes()) { attributeNames[counter++] = attribute.getName(); } return attributeNames; } public void setValue(int i, int j, double value) { this.matrix.set(i, j, value); this.matrix.set(j, i, value); } public double getValue(int i, int j) { return matrix.get(i, j); } public int getNumberOfColumns() { return this.columnNames.length; } public String getName() { return name + " Matrix"; } public String toString() { StringBuffer result = new StringBuffer(name + " Matrix:" + Tools.getLineSeparator()); for (int i = 0; i < columnNames.length; i++) { if (i < MAX_NUMBER_OF_RESULT_STRING_ATTRIBUTES) { result.append("\t" + columnNames[i]); } else { result.append("..."); break; } } for (int i = 0; i < matrix.getRowDimension(); i++) { if (i < MAX_NUMBER_OF_RESULT_STRING_ATTRIBUTES) { result.append(Tools.getLineSeparator() + columnNames[i]); for (int j = 0; j < matrix.getColumnDimension(); j++) { if (j < MAX_NUMBER_OF_RESULT_STRING_ATTRIBUTES) { result.append("\t" + formatter.format(matrix.get(i, j))); } else { result.append("..."); break; } } } else { result.append(Tools.getLineSeparator() + "..."); break; } } return result.toString(); } public DataTable createMatrixDataTable() { return new DataTableSymmetricalMatrixAdapter(this, this.name, this.columnNames); } public DataTable createPairwiseDataTable() { return new DataTablePairwiseMatrixExtractionAdapter(this, this.columnNames, new String[] { "First Attribute", "Second Attribute", name } ); } public String getExtension() { return "cor"; } public String getFileDescription() { return name.toLowerCase() + " matrix"; } /** * Returns a label that displays the {@link #toResultString()} result * encoded as html. */ public java.awt.Component getVisualizationComponent(IOContainer container) { final JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); // matrix viewer double min = Double.POSITIVE_INFINITY; double max = Double.NEGATIVE_INFINITY; for (int x = 0; x < getNumberOfColumns(); x++) { for (int y = 0; y < getNumberOfColumns(); y++) { double value = Math.abs(getValue(x, y)); if (!Double.isNaN(value)) { min = Math.min(min, value); max = Math.max(max, value); } } } final ExtendedFixedColumnJTable matrixViewer = ExtendedFixedColumnJTable.createFixedColumnTable(new SymmetricalMatrixViewerTableModel(this)); matrixViewer.getMainDataTable().setCellColorProvider(new CellColorProviderScaled(matrixViewer.getMainDataTable(), true, min, max)); // pairwise viewer DataTable pairwiseDataTable = createPairwiseDataTable(); final DataTableViewer pairwiseTableViewer = new DataTableViewer(pairwiseDataTable, false); pairwiseTableViewer.getTable().setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); // pairwise plotter component final PlotterPanel plotterComponent = new PlotterPanel(pairwiseDataTable); // toggle radio button for views final JRadioButton matrixButton = new JRadioButton("Matrix View", true); matrixButton.setToolTipText("Changes to a table showing the " + name.toLowerCase() + "."); matrixButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (matrixButton.isSelected()) { mainPanel.remove(1); mainPanel.add(matrixViewer, BorderLayout.CENTER); mainPanel.repaint(); } } }); final JRadioButton pairwiseButton = new JRadioButton("Pairwise " + name, true); pairwiseButton.setToolTipText("Changes to a table showing the " + name.toLowerCase() + " for all pairs."); pairwiseButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (pairwiseButton.isSelected()) { mainPanel.remove(1); mainPanel.add(pairwiseTableViewer, BorderLayout.CENTER); mainPanel.repaint(); } } }); final JRadioButton plotButton = new JRadioButton("Plot View", false); plotButton.setToolTipText("Changes to a plot view of the " + name.toLowerCase()); plotButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (plotButton.isSelected()) { mainPanel.remove(1); mainPanel.add(plotterComponent, BorderLayout.CENTER); mainPanel.repaint(); } } }); ButtonGroup group = new ButtonGroup(); group.add(matrixButton); group.add(pairwiseButton); group.add(plotButton); JPanel togglePanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); togglePanel.add(matrixButton); togglePanel.add(pairwiseButton); togglePanel.add(plotButton); mainPanel.add(togglePanel, BorderLayout.NORTH); mainPanel.add(matrixViewer, BorderLayout.CENTER); return mainPanel; } public Icon getResultIcon() { return resultIcon; } }