/** * Copyright (C) 2001-2017 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.viewer; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Component; import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTextPane; import com.rapidminer.datatable.SimpleDataTable; import com.rapidminer.datatable.SimpleDataTableRow; import com.rapidminer.gui.actions.export.PrintableComponent; import com.rapidminer.gui.look.Colors; import com.rapidminer.gui.plotter.PlotterConfigurationModel; import com.rapidminer.gui.tools.ExtendedJScrollPane; import com.rapidminer.report.Tableable; import com.rapidminer.tools.I18N; /** * This viewer class can be used to display performance criteria based on a multi class confusion * matrix. The viewer consists of two parts, first a part containing the general performance info * string and second a table with the complete confusion matrix. * * @author Ingo Mierswa */ public class ConfusionMatrixViewer extends JPanel implements Tableable, PrintableComponent { private static final long serialVersionUID = 3448880915145528006L; private ConfusionMatrixViewerTable table; private JComponent plotter; private String performanceName; public ConfusionMatrixViewer(String performanceName, String performanceString, String[] classNames, double[][] counter) { this.performanceName = performanceName; setLayout(new BorderLayout()); final JPanel mainPanel = new JPanel(); mainPanel.setOpaque(true); mainPanel.setBackground(Colors.WHITE); final CardLayout cardLayout = new CardLayout(); mainPanel.setLayout(cardLayout); add(mainPanel, BorderLayout.CENTER); // *** table panel *** JPanel tablePanel = new JPanel(new BorderLayout()); tablePanel.setOpaque(true); tablePanel.setBackground(Colors.WHITE); tablePanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); // info string JPanel infoPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); infoPanel.setOpaque(true); infoPanel.setBackground(Colors.WHITE); JTextPane infoText = new JTextPane(); infoText.setEditable(false); infoText.setBackground(infoPanel.getBackground()); infoText.setFont(infoText.getFont().deriveFont(Font.BOLD)); infoText.setText(performanceString); infoPanel.add(infoText); tablePanel.add(infoPanel, BorderLayout.NORTH); // table table = new ConfusionMatrixViewerTable(classNames, counter); table.setBorder(BorderFactory.createLineBorder(Colors.TABLE_CELL_BORDER)); JScrollPane scrollPane = new ExtendedJScrollPane(table); scrollPane.setBorder(null); scrollPane.setBackground(Colors.WHITE); scrollPane.getViewport().setBackground(Colors.WHITE); tablePanel.add(scrollPane, BorderLayout.CENTER); table.setTableHeader(null); // *** plot panel *** SimpleDataTable dataTable = new SimpleDataTable("Confusion Matrix", new String[] { "True Class", "Predicted Class", "Confusion Matrix (x: true class, y: pred. class, z: counters)" }); for (int row = 0; row < classNames.length; row++) { for (int column = 0; column < classNames.length; column++) { dataTable.add(new SimpleDataTableRow(new double[] { row, column, counter[row][column] })); } } PlotterConfigurationModel settings = new PlotterConfigurationModel(PlotterConfigurationModel.STICK_CHART_3D, dataTable); settings.setAxis(0, 0); settings.setAxis(1, 1); settings.enablePlotColumn(2); mainPanel.add(tablePanel, "table"); plotter = settings.getPlotter().getPlotter(); mainPanel.add(plotter, "plot"); // toggle radio button for views final JRadioButton metaDataButton = new JRadioButton("Table View", true); metaDataButton.setToolTipText("Changes to a table showing the confusion matrix."); metaDataButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (metaDataButton.isSelected()) { cardLayout.show(mainPanel, "table"); } } }); final JRadioButton plotButton = new JRadioButton("Plot View", false); plotButton.setToolTipText("Changes to a plot view of the confusion matrix."); plotButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (plotButton.isSelected()) { cardLayout.show(mainPanel, "plot"); } } }); ButtonGroup group = new ButtonGroup(); group.add(metaDataButton); group.add(plotButton); JPanel togglePanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); togglePanel.setOpaque(true); togglePanel.setBackground(Colors.WHITE); togglePanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 20, 0)); togglePanel.add(metaDataButton); togglePanel.add(plotButton); add(togglePanel, BorderLayout.NORTH); } @Override public void prepareReporting() { table.prepareReporting(); } @Override public void finishReporting() { table.finishReporting(); } @Override public boolean isFirstLineHeader() { return true; } @Override public boolean isFirstColumnHeader() { return true; } @Override public String getColumnName(int columnIndex) { return table.getColumnName(columnIndex); } @Override public String getCell(int row, int column) { return table.getCell(row, column); } @Override public int getColumnNumber() { return table.getColumnNumber(); } @Override public int getRowNumber() { return table.getRowNumber(); } @Override public Component getExportComponent() { return plotter; } @Override public String getExportName() { return I18N.getGUIMessage("gui.cards.result_view.confusion_matrix.title"); } @Override public String getIdentifier() { return performanceName; } @Override public String getExportIconName() { return I18N.getGUIMessage("gui.cards.result_view.confusion_matrix.icon"); } }