weka.gui.explorer.PreprocessPanel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weka-dev Show documentation
Show all versions of weka-dev Show documentation
The Waikato Environment for Knowledge Analysis (WEKA), a machine
learning workbench. This version represents the developer version, the
"bleeding edge" of development, you could say. New functionality gets added
to this version.
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* PreprocessPanel.java
* Copyright (C) 2003-2013 University of Waikato, Hamilton, New Zealand
*
*/
package weka.gui.explorer;
import weka.core.Capabilities;
import weka.core.CapabilitiesHandler;
import weka.core.Defaults;
import weka.core.Environment;
import weka.core.Instances;
import weka.core.OptionHandler;
import weka.core.Settings;
import weka.core.Utils;
import weka.core.converters.AbstractFileLoader;
import weka.core.converters.AbstractFileSaver;
import weka.core.converters.ConverterUtils;
import weka.core.converters.Loader;
import weka.core.converters.SerializedInstancesLoader;
import weka.core.converters.URLSourcedLoader;
import weka.datagenerators.DataGenerator;
import weka.experiment.InstanceQuery;
import weka.filters.AllFilter;
import weka.filters.Filter;
import weka.filters.SupervisedFilter;
import weka.filters.unsupervised.attribute.Remove;
import weka.gui.AbstractPerspective;
import weka.gui.AttributeSelectionPanel;
import weka.gui.AttributeSummaryPanel;
import weka.gui.AttributeVisualizationPanel;
import weka.gui.ConverterFileChooser;
import weka.gui.GenericObjectEditor;
import weka.gui.InstancesSummaryPanel;
import weka.gui.Logger;
import weka.gui.Perspective;
import weka.gui.PerspectiveInfo;
import weka.gui.PropertyDialog;
import weka.gui.PropertyPanel;
import weka.gui.SysErrLog;
import weka.gui.TaskLogger;
import weka.gui.ViewerDialog;
import weka.gui.WekaFileChooser;
import weka.gui.WorkbenchApp;
import weka.gui.explorer.Explorer.CapabilitiesFilterChangeEvent;
import weka.gui.explorer.Explorer.CapabilitiesFilterChangeListener;
import weka.gui.explorer.Explorer.ExplorerPanel;
import weka.gui.explorer.Explorer.LogHandler;
import weka.gui.sql.SqlViewerDialog;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.TableModel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.ObjectOutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* This panel controls simple preprocessing of instances. Summary information on
* instances and attributes is shown. Filters may be configured to alter the set
* of instances. Altered instances may also be saved.
*
* @author Richard Kirkby ([email protected])
* @author Len Trigg ([email protected])
* @version $Revision: 15682 $
*/
@PerspectiveInfo(ID = "weka.gui.explorer.preprocesspanel",
title = "Preprocess", toolTipText = "Preprocess data",
iconPath = "weka/gui/weka_icon_new_small.png")
public class PreprocessPanel extends AbstractPerspective implements
CapabilitiesFilterChangeListener, ExplorerPanel, LogHandler {
/** for serialization */
private static final long serialVersionUID = 6764850273874813049L;
/** Displays simple stats on the working instances */
protected InstancesSummaryPanel m_InstSummaryPanel =
new InstancesSummaryPanel();
/** Click to load base instances from a file */
protected JButton m_OpenFileBut = new JButton("Open file...");
/** Click to load base instances from a URL */
protected JButton m_OpenURLBut = new JButton("Open URL...");
/** Click to load base instances from a Database */
protected JButton m_OpenDBBut = new JButton("Open DB...");
/** Click to generate artificial data */
protected JButton m_GenerateBut = new JButton("Generate...");
/** Click to revert back to the last saved point */
protected JButton m_UndoBut = new JButton("Undo");
/** Click to open the current instances in a viewer */
protected JButton m_EditBut = new JButton("Edit...");
protected JMenuItem m_EditM = new JMenuItem("Edit...");
/** For sending instances to various perspectives/tabs */
protected JMenu m_sendToPerspective;
/** Click to apply filters and save the results */
protected JButton m_SaveBut = new JButton("Save...");
/** Panel to let the user toggle attributes */
protected AttributeSelectionPanel m_AttPanel = new AttributeSelectionPanel();
/** Button for removing attributes */
protected JButton m_RemoveButton = new JButton("Remove");
/** Displays summary stats on the selected attribute */
protected AttributeSummaryPanel m_AttSummaryPanel =
new AttributeSummaryPanel();
/** Lets the user configure the filter */
protected GenericObjectEditor m_FilterEditor = new GenericObjectEditor();
/** Filter configuration */
protected PropertyPanel m_FilterPanel = new PropertyPanel(m_FilterEditor);
/** Click to apply filters and save the results */
protected JButton m_ApplyFilterBut = new JButton("Apply");
/** Click to stop a running filter */
protected JButton m_StopBut = new JButton("Stop");
/** The file chooser for selecting data files */
protected ConverterFileChooser m_FileChooser;
/** Stores the last URL that instances were loaded from */
protected String m_LastURL = "http://";
/** Stores the last sql query executed */
protected String m_SQLQ = new String("SELECT * FROM ?");
/** The working instances */
protected Instances m_Instances;
/** The last generator that was selected */
protected DataGenerator m_DataGenerator = null;
/** The visualization of the attribute values */
protected AttributeVisualizationPanel m_AttVisualizePanel =
new AttributeVisualizationPanel();
/** Keeps track of undo points */
protected File[] m_tempUndoFiles = new File[20]; // set number of undo ops
// here
/** The next available slot for an undo point */
protected int m_tempUndoIndex = 0;
/**
* Manages sending notifications to people when we change the set of working
* instances.
*/
protected PropertyChangeSupport m_Support = new PropertyChangeSupport(this);
/** A thread for loading/saving instances from a file or URL */
protected Thread m_IOThread;
/** The message logger */
protected Logger m_Log = new SysErrLog();
/** the parent frame */
protected Explorer m_Explorer = null;
/** True after settings have been applied the first time */
protected boolean m_initialSettingsSet;
/** Menus provided by this perspective */
protected List m_menus = new ArrayList();
/**
* Creates the instances panel with no initial instances.
*/
public PreprocessPanel() {
String initialDir = ExplorerDefaults.getInitialDirectory();
m_FileChooser = new ConverterFileChooser(new File(initialDir));
// Create/Configure/Connect components
m_FilterEditor.setClassType(weka.filters.Filter.class);
if (ExplorerDefaults.getFilter() != null)
m_FilterEditor.setValue(ExplorerDefaults.getFilter());
m_FilterEditor.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
m_ApplyFilterBut.setEnabled(getInstances() != null);
Capabilities currentCapabilitiesFilter =
m_FilterEditor.getCapabilitiesFilter();
Filter filter = (Filter) m_FilterEditor.getValue();
Capabilities currentFilterCapabilities = null;
if (filter != null && currentCapabilitiesFilter != null
&& (filter instanceof CapabilitiesHandler)) {
currentFilterCapabilities =
((CapabilitiesHandler) filter).getCapabilities();
if (!currentFilterCapabilities
.supportsMaybe(currentCapabilitiesFilter)
&& !currentFilterCapabilities.supports(currentCapabilitiesFilter)) {
try {
filter.setInputFormat(getInstances());
} catch (Exception ex) {
m_ApplyFilterBut.setEnabled(false);
}
}
}
}
});
JMenu fileMenu = new JMenu();
fileMenu.setText("File");
m_menus.add(fileMenu);
m_OpenFileBut.setToolTipText("Open a set of instances from a file");
JMenuItem openFileM = new JMenuItem("Open file...");
openFileM.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F,
InputEvent.CTRL_DOWN_MASK));
fileMenu.add(openFileM);
m_OpenURLBut.setToolTipText("Open a set of instances from a URL");
JMenuItem openURLM = new JMenuItem("Open URL...");
openURLM.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U,
InputEvent.CTRL_DOWN_MASK));
fileMenu.add(openURLM);
m_OpenDBBut.setToolTipText("Open a set of instances from a database");
JMenuItem openDBM = new JMenuItem("Open DB...");
openDBM.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D,
InputEvent.CTRL_DOWN_MASK));
fileMenu.add(openDBM);
m_GenerateBut.setToolTipText("Generates artificial data");
JMenuItem generateM = new JMenuItem("Generate...");
generateM.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G,
InputEvent.CTRL_DOWN_MASK));
m_UndoBut.setToolTipText("Undo the last change to the dataset");
fileMenu.add(generateM);
m_UndoBut.setEnabled(ExplorerDefaults.get("enableUndo", "true")
.equalsIgnoreCase("true"));
if (!m_UndoBut.isEnabled()) {
m_UndoBut.setToolTipText("Undo is disabled - "
+ "see weka.gui.explorer.Explorer.props to enable");
}
m_EditBut
.setToolTipText("Open the current dataset in a Viewer for editing");
JMenu editMenu = new JMenu();
editMenu.add(m_EditM);
m_EditM.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E,
InputEvent.CTRL_DOWN_MASK));
m_EditM.setEnabled(false);
editMenu.setText("Edit");
m_menus.add(editMenu);
m_SaveBut.setToolTipText("Save the working relation to a file");
m_ApplyFilterBut.setToolTipText("Apply the current filter to the data");
m_StopBut.setToolTipText("Stop the filtering process");
m_FileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
m_OpenURLBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setInstancesFromURLQ();
}
});
openURLM.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setInstancesFromURLQ();
}
});
m_OpenDBBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFrame frame = null;
Window window = SwingUtilities.getWindowAncestor(PreprocessPanel.this);
if (window instanceof JFrame) {
frame = (JFrame)window;
}
SqlViewerDialog dialog = new SqlViewerDialog(frame);
dialog.pack();
dialog.setSize(800, 700);
dialog.setIconImage(((Frame) SwingUtilities.getWindowAncestor(PreprocessPanel.this)).getIconImage());
dialog.setLocationRelativeTo(SwingUtilities.getWindowAncestor(PreprocessPanel.this));
dialog.setVisible(true);
if (dialog.getReturnValue() == JOptionPane.OK_OPTION)
setInstancesFromDBQ(dialog.getURL(), dialog.getUser(),
dialog.getPassword(), dialog.getQuery(),
dialog.getGenerateSparseData());
}
});
m_OpenFileBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setInstancesFromFileQ();
}
});
openFileM.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setInstancesFromFileQ();
}
});
m_GenerateBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
generateInstances();
}
});
generateM.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
generateInstances();
}
});
m_UndoBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
undo();
}
});
m_EditBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
edit();
}
});
m_EditM.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
edit();
}
});
m_SaveBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveWorkingInstancesToFileQ();
}
});
m_ApplyFilterBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
applyFilter((Filter) m_FilterEditor.getValue());
}
});
m_StopBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (m_IOThread != null) {
m_IOThread.stop();
m_StopBut.setEnabled(false);
m_IOThread = null;
if (m_Log instanceof TaskLogger) {
((TaskLogger) m_Log).taskFinished();
}
m_Log.statusMessage("Filtering process stopped prematurely");
}
}
});
m_AttPanel.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
ListSelectionModel lm = (ListSelectionModel) e.getSource();
for (int i = e.getFirstIndex(); i <= e.getLastIndex(); i++) {
if (lm.isSelectedIndex(i)) {
m_AttSummaryPanel.setAttribute(i);
m_AttVisualizePanel.setAttribute(i);
break;
}
}
}
}
});
m_InstSummaryPanel.setBorder(BorderFactory
.createTitledBorder("Current relation"));
JPanel attStuffHolderPanel = new JPanel();
attStuffHolderPanel.setBorder(BorderFactory
.createTitledBorder("Attributes"));
attStuffHolderPanel.setLayout(new BorderLayout());
attStuffHolderPanel.add(m_AttPanel, BorderLayout.CENTER);
m_RemoveButton.setEnabled(false);
m_RemoveButton.setToolTipText("Remove selected attributes.");
m_RemoveButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
Remove r = new Remove();
int[] selected = m_AttPanel.getSelectedAttributes();
if (selected.length == 0) {
return;
}
if (selected.length == m_Instances.numAttributes()) {
// Pop up an error optionpane
JOptionPane.showMessageDialog(PreprocessPanel.this,
"Can't remove all attributes from data!\n", "Remove Attributes",
JOptionPane.ERROR_MESSAGE);
m_Log.logMessage("Can't remove all attributes from data!");
m_Log.statusMessage("Problem removing attributes");
return;
}
r.setAttributeIndicesArray(selected);
applyFilter(r);
m_RemoveButton.setEnabled(false);
} catch (Exception ex) {
if (m_Log instanceof TaskLogger) {
((TaskLogger) m_Log).taskFinished();
}
// Pop up an error optionpane
JOptionPane.showMessageDialog(PreprocessPanel.this,
"Problem filtering instances:\n" + ex.getMessage(),
"Remove Attributes", JOptionPane.ERROR_MESSAGE);
m_Log.logMessage("Problem removing attributes: " + ex.getMessage());
m_Log.statusMessage("Problem removing attributes");
ex.printStackTrace();
}
}
});
JPanel p1 = new JPanel();
p1.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
p1.setLayout(new BorderLayout());
p1.add(m_RemoveButton, BorderLayout.CENTER);
attStuffHolderPanel.add(p1, BorderLayout.SOUTH);
m_AttSummaryPanel.setBorder(BorderFactory
.createTitledBorder("Selected attribute"));
m_UndoBut.setEnabled(false);
m_EditBut.setEnabled(false);
m_SaveBut.setEnabled(false);
m_ApplyFilterBut.setEnabled(false);
m_StopBut.setEnabled(false);
// Set up the GUI layout
JPanel buttons = new JPanel();
buttons.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
buttons.setLayout(new GridLayout(1, 6, 5, 5));
buttons.add(m_OpenFileBut);
buttons.add(m_OpenURLBut);
buttons.add(m_OpenDBBut);
buttons.add(m_GenerateBut);
buttons.add(m_UndoBut);
buttons.add(m_EditBut);
buttons.add(m_SaveBut);
JPanel attInfo = new JPanel();
attInfo.setLayout(new BorderLayout());
attInfo.add(attStuffHolderPanel, BorderLayout.CENTER);
JPanel filter = new JPanel();
filter.setBorder(BorderFactory.createTitledBorder("Filter"));
filter.setLayout(new BorderLayout());
filter.add(m_FilterPanel, BorderLayout.CENTER);
JPanel ssButs = new JPanel();
ssButs.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
ssButs.setLayout(new GridLayout(1, 2, 2, 0));
ssButs.add(m_ApplyFilterBut);
ssButs.add(m_StopBut);
filter.add(ssButs, BorderLayout.EAST);
JPanel attVis = new JPanel();
attVis.setLayout(new GridLayout(2, 1));
attVis.add(m_AttSummaryPanel);
JComboBox colorBox = m_AttVisualizePanel.getColorBox();
colorBox.setToolTipText("The chosen attribute will also be used as the "
+ "class attribute when a filter is applied.");
colorBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ie) {
if (ie.getStateChange() == ItemEvent.SELECTED) {
updateCapabilitiesFilter(m_FilterEditor.getCapabilitiesFilter());
}
}
});
final JButton visAllBut = new JButton("Visualize All");
visAllBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (m_Instances != null) {
try {
final weka.gui.beans.AttributeSummarizer as =
new weka.gui.beans.AttributeSummarizer();
as.setColoringIndex(m_AttVisualizePanel.getColoringIndex());
as.setInstances(m_Instances);
final javax.swing.JFrame jf = Utils.getWekaJFrame("All attributes", PreprocessPanel.this);
jf.getContentPane().setLayout(new java.awt.BorderLayout());
jf.getContentPane().add(as, java.awt.BorderLayout.CENTER);
jf.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
visAllBut.setEnabled(true);
jf.dispose();
}
});
jf.pack();
jf.setSize(1000, 600);
jf.setLocationRelativeTo(SwingUtilities.getWindowAncestor(PreprocessPanel.this));
jf.setVisible(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});
JPanel histoHolder = new JPanel();
histoHolder.setLayout(new BorderLayout());
histoHolder.add(m_AttVisualizePanel, BorderLayout.CENTER);
JPanel histoControls = new JPanel();
histoControls.setLayout(new BorderLayout());
histoControls.add(colorBox, BorderLayout.CENTER);
histoControls.add(visAllBut, BorderLayout.EAST);
histoHolder.add(histoControls, BorderLayout.NORTH);
attVis.add(histoHolder);
JPanel lhs = new JPanel();
lhs.setLayout(new BorderLayout());
lhs.add(m_InstSummaryPanel, BorderLayout.NORTH);
lhs.add(attInfo, BorderLayout.CENTER);
JPanel rhs = new JPanel();
rhs.setLayout(new BorderLayout());
rhs.add(attVis, BorderLayout.CENTER);
JPanel relation = new JPanel();
relation.setLayout(new GridLayout(1, 2));
relation.add(lhs);
relation.add(rhs);
JPanel middle = new JPanel();
middle.setLayout(new BorderLayout());
middle.add(filter, BorderLayout.NORTH);
middle.add(relation, BorderLayout.CENTER);
setLayout(new BorderLayout());
add(buttons, BorderLayout.NORTH);
add(middle, BorderLayout.CENTER);
}
/**
* We can accept instances
*
* @return true
*/
@Override
public boolean acceptsInstances() {
return true;
}
/**
* We've been instantiated and now have access to the main application and
* PerspectiveManager
*/
@Override
public void instantiationComplete() {
// overridden here so that we know if we're operating within
// a non-legacy UI, and can thus set up our send data to perspective
// menu (if necessary)
boolean sendToAll =
getMainApplication().getApplicationSettings().getSetting(
getPerspectiveID(),
PreprocessDefaults.ALWAYS_SEND_INSTANCES_TO_ALL_KEY,
PreprocessDefaults.ALWAYS_SEND_INSTANCES_TO_ALL,
Environment.getSystemWide());
// install a menu item to allow the user to choose to send to all or
// send to a specific perspective
final List perspectivesThatAcceptInstances =
new ArrayList();
List visiblePerspectives =
getMainApplication().getPerspectiveManager().getVisiblePerspectives();
for (Perspective p : visiblePerspectives) {
if (p.acceptsInstances()
&& !p.getPerspectiveID().equals(getPerspectiveID())) {
perspectivesThatAcceptInstances.add(p);
}
}
if (perspectivesThatAcceptInstances.size() > 0) {
JMenu fileMenu = m_menus.get(0);
m_sendToPerspective = new JMenu();
m_sendToPerspective.setText("Send to perspective");
fileMenu.add(m_sendToPerspective);
if (!sendToAll) {
m_sendToPerspective.setEnabled(false);
}
JMenuItem sendToAllItem = new JMenuItem("All perspectives");
sendToAllItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for (Perspective p : perspectivesThatAcceptInstances) {
if (getInstances() != null && p.acceptsInstances()) {
p.setInstances(getInstances());
getMainApplication().getPerspectiveManager()
.setEnablePerspectiveTab(p.getPerspectiveID(), true);
}
}
}
});
m_sendToPerspective.add(sendToAllItem);
for (final Perspective p : perspectivesThatAcceptInstances) {
JMenuItem item = new JMenuItem(p.getPerspectiveTitle());
m_sendToPerspective.add(item);
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (getInstances() != null) {
p.setInstances(getInstances());
getMainApplication().getPerspectiveManager()
.setEnablePerspectiveTab(p.getPerspectiveID(), true);
getMainApplication().getPerspectiveManager()
.setActivePerspective(p.getPerspectiveID());
}
}
});
}
}
}
/**
* Sets the Logger to receive informational messages
*
* @param newLog the Logger that will now get info messages
*/
public void setLog(Logger newLog) {
m_Log = newLog;
}
@Override
public boolean requiresLog() {
return true;
}
/**
* Tells the panel to use a new base set of instances.
*
* @param inst a set of Instances
*/
public void setInstances(Instances inst) {
m_Instances = inst;
try {
Runnable r = new Runnable() {
public void run() {
boolean first = (m_AttPanel.getTableModel() == null);
m_InstSummaryPanel.setInstances(m_Instances);
m_AttPanel.setInstances(m_Instances);
if (first) {
TableModel model = m_AttPanel.getTableModel();
model.addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
if (m_AttPanel.getSelectedAttributes() != null
&& m_AttPanel.getSelectedAttributes().length > 0) {
m_RemoveButton.setEnabled(true);
} else {
m_RemoveButton.setEnabled(false);
}
}
});
}
// m_RemoveButton.setEnabled(true);
m_AttSummaryPanel.setInstances(m_Instances);
m_AttVisualizePanel.setInstances(m_Instances);
// select the first attribute in the list
m_AttPanel.getSelectionModel().setSelectionInterval(0, 0);
m_AttSummaryPanel.setAttribute(0);
m_AttVisualizePanel.setAttribute(0);
m_ApplyFilterBut.setEnabled(true);
m_StopBut.setEnabled(false);
m_Log.logMessage("Base relation is now " + m_Instances.relationName()
+ " (" + m_Instances.numInstances() + " instances)");
m_SaveBut.setEnabled(true);
m_EditBut.setEnabled(true);
m_EditM.setEnabled(true);
m_Log.statusMessage("OK");
// Fire a propertychange event
m_Support.firePropertyChange("", null, null);
boolean sendToAll =
getExplorer() != null
|| getMainApplication().getApplicationSettings().getSetting(
getPerspectiveID(),
PreprocessDefaults.ALWAYS_SEND_INSTANCES_TO_ALL_KEY,
PreprocessDefaults.ALWAYS_SEND_INSTANCES_TO_ALL,
Environment.getSystemWide());
if (m_sendToPerspective != null) {
m_sendToPerspective.setEnabled(!sendToAll);
}
if (getMainApplication() != null) {
if (sendToAll) {
List perspectiveList =
getMainApplication().getPerspectiveManager()
.getVisiblePerspectives();
for (Perspective p : perspectiveList) {
if (p.acceptsInstances()
&& !p.getPerspectiveID().equals(getPerspectiveID())) {
p.setInstances(m_Instances);
}
}
}
}
// notify GOEs about change
if (getExplorer() != null || getMainApplication() != null) {
Explorer explorer = getExplorer();
WorkbenchApp app = (WorkbenchApp) getMainApplication();
try {
// get rid of old filter settings
if (explorer != null) {
explorer.notifyCapabilitiesFilterListener(null);
} else {
app.notifyCapabilitiesFilterListeners(null);
// enable all perspectives
if (sendToAll) {
app.getPerspectiveManager().enableAllPerspectiveTabs();
}
}
int oldIndex = m_Instances.classIndex();
m_Instances.setClassIndex(m_AttVisualizePanel.getColorBox()
.getSelectedIndex() - 1);
// send new ones
if (ExplorerDefaults.getInitGenericObjectEditorFilter()) {
if (explorer != null) {
explorer.notifyCapabilitiesFilterListener(Capabilities
.forInstances(m_Instances));
} else {
if (sendToAll) {
app.notifyCapabilitiesFilterListeners(Capabilities
.forInstances(m_Instances));
}
}
} else {
if (explorer != null) {
explorer.notifyCapabilitiesFilterListener(Capabilities
.forInstances(new Instances(m_Instances, 0)));
} else {
if (sendToAll) {
app.notifyCapabilitiesFilterListeners(Capabilities
.forInstances(new Instances(m_Instances, 0)));
}
}
}
m_Instances.setClassIndex(oldIndex);
} catch (Exception e) {
e.printStackTrace();
m_Log.logMessage(e.toString());
}
}
}
};
if (SwingUtilities.isEventDispatchThread()) {
r.run();
} else {
SwingUtilities.invokeAndWait(r);
}
} catch (Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this, "Problem setting base instances:\n"
+ ex, "Instances", JOptionPane.ERROR_MESSAGE);
}
}
/**
* Gets the working set of instances.
*
* @return the working instances
*/
public Instances getInstances() {
return m_Instances;
}
/**
* Adds a PropertyChangeListener who will be notified of value changes.
*
* @param l a value of type 'PropertyChangeListener'
*/
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
if (m_Support != null && l != null) {
m_Support.addPropertyChangeListener(l);
}
}
/**
* Removes a PropertyChangeListener.
*
* @param l a value of type 'PropertyChangeListener'
*/
@Override
public void removePropertyChangeListener(PropertyChangeListener l) {
if (m_Support != null && l != null) {
m_Support.removePropertyChangeListener(l);
}
}
/**
* Passes the dataset through the filter that has been configured for use.
*
* @param filter the filter to apply
*/
protected void applyFilter(final Filter filter) {
if (m_IOThread == null) {
m_IOThread = new Thread() {
@Override
public void run() {
try {
if (filter != null) {
m_FilterPanel.addToHistory();
if (m_Log instanceof TaskLogger) {
((TaskLogger) m_Log).taskStarted();
}
m_Log.statusMessage("Passing dataset through filter "
+ filter.getClass().getName());
String cmd = filter.getClass().getName();
if (filter instanceof OptionHandler)
cmd +=
" "
+ Utils.joinOptions(((OptionHandler) filter).getOptions());
m_Log.logMessage("Command: " + cmd);
int classIndex = m_AttVisualizePanel.getColoringIndex();
if ((classIndex < 0) && (filter instanceof SupervisedFilter)) {
throw new IllegalArgumentException("Class (colour) needs to "
+ "be set for supervised " + "filter.");
}
Instances copy = new Instances(m_Instances);
copy.setClassIndex(classIndex);
m_StopBut.setEnabled(true);
Filter filterCopy = Filter.makeCopy(filter);
filterCopy.setInputFormat(copy);
Instances newInstances = Filter.useFilter(copy, filterCopy);
m_StopBut.setEnabled(false);
if (newInstances == null || newInstances.numAttributes() < 1) {
throw new Exception("Dataset is empty.");
}
m_Log.statusMessage("Saving undo information");
addUndoPoint();
m_AttVisualizePanel.setColoringIndex(copy.classIndex());
// if class was not set before, reset it again after use of filter
/* if (m_Instances.classIndex() < 0)
newInstances.setClassIndex(-1); */
newInstances.setClassIndex(-1);
m_Instances = newInstances;
setInstances(m_Instances);
if (m_Log instanceof TaskLogger) {
((TaskLogger) m_Log).taskFinished();
}
}
} catch (Exception ex) {
if (m_Log instanceof TaskLogger) {
((TaskLogger) m_Log).taskFinished();
}
// Pop up an error optionpane
JOptionPane.showMessageDialog(PreprocessPanel.this,
"Problem filtering instances:\n" + ex.getMessage(),
"Apply Filter", JOptionPane.ERROR_MESSAGE);
m_Log.logMessage("Problem filtering instances: " + ex.getMessage());
m_Log.statusMessage("Problem filtering instances");
ex.printStackTrace();
}
m_IOThread = null;
}
};
m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
m_IOThread.start();
} else {
JOptionPane.showMessageDialog(this, "Can't apply filter at this time,\n"
+ "currently busy with other IO", "Apply Filter",
JOptionPane.WARNING_MESSAGE);
}
}
/**
* Queries the user for a file to save instances as, then saves the instances
* in a background process. This is done in the IO thread, and an error
* message is popped up if the IO thread is busy.
*/
public void saveWorkingInstancesToFileQ() {
if (m_IOThread == null) {
m_FileChooser.setCapabilitiesFilter(m_FilterEditor
.getCapabilitiesFilter());
m_FileChooser.setAcceptAllFileFilterUsed(false);
int returnVal = m_FileChooser.showSaveDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
Instances inst = new Instances(m_Instances);
inst.setClassIndex(m_AttVisualizePanel.getColoringIndex());
saveInstancesToFile(m_FileChooser.getSaver(), inst);
}
FileFilter temp = m_FileChooser.getFileFilter();
m_FileChooser.setAcceptAllFileFilterUsed(true);
m_FileChooser.setFileFilter(temp);
} else {
JOptionPane.showMessageDialog(this, "Can't save at this time,\n"
+ "currently busy with other IO", "Save Instances",
JOptionPane.WARNING_MESSAGE);
}
}
/**
* saves the data with the specified saver
*
* @param saver the saver to use for storing the data
* @param inst the data to save
*/
public void saveInstancesToFile(final AbstractFileSaver saver,
final Instances inst) {
if (m_IOThread == null) {
m_IOThread = new Thread() {
@Override
public void run() {
try {
m_Log.statusMessage("Saving to file...");
saver.setInstances(inst);
saver.writeBatch();
m_Log.statusMessage("OK");
} catch (Exception ex) {
ex.printStackTrace();
m_Log.logMessage(ex.getMessage());
}
m_IOThread = null;
}
};
m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
m_IOThread.start();
} else {
JOptionPane.showMessageDialog(this, "Can't save at this time,\n"
+ "currently busy with other IO", "Saving instances",
JOptionPane.WARNING_MESSAGE);
}
}
/**
* Queries the user for a file to load instances from, then loads the
* instances in a background process. This is done in the IO thread, and an
* error message is popped up if the IO thread is busy.
*/
public void setInstancesFromFileQ() {
if (m_IOThread == null) {
int returnVal = m_FileChooser.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
try {
addUndoPoint();
} catch (Exception ignored) {
// ignored
}
if (m_FileChooser.getLoader() == null) {
JOptionPane.showMessageDialog(this,
"Cannot determine file loader automatically, please choose one.",
"Load Instances", JOptionPane.ERROR_MESSAGE);
converterQuery(m_FileChooser.getSelectedFile());
} else {
setInstancesFromFile(m_FileChooser.getLoader());
}
}
} else {
JOptionPane.showMessageDialog(this, "Can't load at this time,\n"
+ "currently busy with other IO", "Load Instances",
JOptionPane.WARNING_MESSAGE);
}
}
/**
* Loads (non-sparse) instances from an SQL query the user provided with the
* SqlViewerDialog, then loads the instances in a background process. This is
* done in the IO thread, and an error message is popped up if the IO thread
* is busy.
*
* @param url the database URL
* @param user the user to connect as
* @param pw the password of the user
* @param query the query for retrieving instances from
*/
public void setInstancesFromDBQ(String url, String user, String pw,
String query) {
setInstancesFromDBQ(url, user, pw, query, false);
}
/**
* Loads instances from an SQL query the user provided with the
* SqlViewerDialog, then loads the instances in a background process. This is
* done in the IO thread, and an error message is popped up if the IO thread
* is busy.
*
* @param url the database URL
* @param user the user to connect as
* @param pw the password of the user
* @param query the query for retrieving instances from
* @param sparse whether to create sparse or non-sparse instances
*/
public void setInstancesFromDBQ(String url, String user, String pw,
String query, boolean sparse) {
if (m_IOThread == null) {
try {
InstanceQuery InstQ = new InstanceQuery();
InstQ.setDatabaseURL(url);
InstQ.setUsername(user);
InstQ.setPassword(pw);
InstQ.setQuery(query);
InstQ.setSparseData(sparse);
// we have to disconnect, otherwise we can't change the DB!
if (InstQ.isConnected())
InstQ.disconnectFromDatabase();
InstQ.connectToDatabase();
try {
addUndoPoint();
} catch (Exception ignored) {
}
setInstancesFromDB(InstQ);
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, "Problem connecting to database:\n"
+ ex.getMessage(), "Load Instances", JOptionPane.ERROR_MESSAGE);
}
} else {
JOptionPane.showMessageDialog(this, "Can't load at this time,\n"
+ "currently busy with other IO", "Load Instances",
JOptionPane.WARNING_MESSAGE);
}
}
/**
* Queries the user for a URL to load instances from, then loads the instances
* in a background process. This is done in the IO thread, and an error
* message is popped up if the IO thread is busy.
*/
public void setInstancesFromURLQ() {
if (m_IOThread == null) {
try {
String urlName =
(String) JOptionPane.showInputDialog(this, "Enter the source URL",
"Load Instances", JOptionPane.QUESTION_MESSAGE, null, null,
m_LastURL);
if (urlName != null) {
m_LastURL = urlName;
URL url = new URL(urlName);
try {
addUndoPoint();
} catch (Exception ignored) {
}
setInstancesFromURL(url);
}
} catch (Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this,
"Problem with URL:\n" + ex.getMessage(), "Load Instances",
JOptionPane.ERROR_MESSAGE);
}
} else {
JOptionPane.showMessageDialog(this, "Can't load at this time,\n"
+ "currently busy with other IO", "Load Instances",
JOptionPane.WARNING_MESSAGE);
}
}
/**
* sets Instances generated via DataGenerators (pops up a Dialog)
*/
public void generateInstances() {
if (m_IOThread == null) {
m_IOThread = new Thread() {
@Override
public void run() {
try {
// create dialog
final DataGeneratorPanel generatorPanel = new DataGeneratorPanel();
final JDialog dialog = new JDialog();
final JButton generateButton = new JButton("Generate");
final JCheckBox showOutputCheckBox =
new JCheckBox("Show generated data as text, incl. comments");
showOutputCheckBox.setMnemonic('S');
generatorPanel.setLog(m_Log);
generatorPanel.setGenerator(m_DataGenerator);
generatorPanel.setPreferredSize(new Dimension(300,
(int) generatorPanel.getPreferredSize().getHeight()));
generateButton.setMnemonic('G');
generateButton
.setToolTipText("Generates the dataset according the settings.");
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
boolean showOutput = showOutputCheckBox.isSelected();
// generate
generatorPanel.execute(showOutput);
boolean generated = (generatorPanel.getInstances() != null);
if (generated) {
Instances genInst = generatorPanel.getInstances();
// unset any class, to be consistent with filter behaviour
genInst.setClassIndex(-1);
setInstances(genInst);
}
// close dialog
dialog.dispose();
// get last generator
m_DataGenerator = generatorPanel.getGenerator();
// display output?
if ((generated) && (showOutput))
showGeneratedInstances(generatorPanel.getOutput());
generatorPanel.setLog(null);
}
};
generateButton.addActionListener(al);
WindowListener wl = new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent w) {
dialog.dispose();
}
@Override
public void windowClosed(WindowEvent w) {
dialog.removeWindowListener(this);
dialog.setContentPane(new JPanel());
generateButton.removeActionListener(al);
}
};
dialog.addWindowListener(wl);
dialog.setTitle("DataGenerator");
dialog.getContentPane().add(generatorPanel, BorderLayout.CENTER);
dialog.getContentPane().add(generateButton, BorderLayout.EAST);
dialog.getContentPane().add(showOutputCheckBox, BorderLayout.SOUTH);
dialog.pack();
dialog.setSize(1000,130);
dialog.setIconImage(((Frame) SwingUtilities.getWindowAncestor(PreprocessPanel.this)).getIconImage());
dialog.setLocationRelativeTo(SwingUtilities.getWindowAncestor(PreprocessPanel.this));
// display dialog
dialog.setVisible(true);
} catch (Exception ex) {
ex.printStackTrace();
m_Log.logMessage(ex.getMessage());
}
m_IOThread = null;
}
};
m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
m_IOThread.start();
} else {
JOptionPane.showMessageDialog(this, "Can't generate data at this time,\n"
+ "currently busy with other IO", "Generate Data",
JOptionPane.WARNING_MESSAGE);
}
}
/**
* displays a dialog with the generated instances from the DataGenerator
*
* @param data the data to display
*/
protected void showGeneratedInstances(String data) {
final JDialog dialog = new JDialog(SwingUtilities.getWindowAncestor(PreprocessPanel.this));
final JButton saveButton = new JButton("Save");
final JButton closeButton = new JButton("Close");
final JTextArea textData = new JTextArea(data);
final JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
textData.setEditable(false);
textData.setFont(new Font("Monospaced", Font.PLAIN, textData.getFont()
.getSize()));
saveButton.setMnemonic('S');
saveButton.setToolTipText("Saves the output to a file");
saveButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
WekaFileChooser filechooser = new WekaFileChooser();
int result = filechooser.showSaveDialog(dialog);
if (result == JFileChooser.APPROVE_OPTION) {
try {
BufferedWriter writer =
new BufferedWriter(new FileWriter(filechooser.getSelectedFile()));
writer.write(textData.getText());
writer.flush();
writer.close();
JOptionPane.showMessageDialog(
dialog,
"Output successfully saved to file '"
+ filechooser.getSelectedFile() + "'!", "Information",
JOptionPane.INFORMATION_MESSAGE);
} catch (Exception e) {
e.printStackTrace();
}
dialog.dispose();
}
}
});
closeButton.setMnemonic('C');
closeButton.setToolTipText("Closes the dialog");
closeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
dialog.dispose();
}
});
panel.add(saveButton);
panel.add(closeButton);
dialog.setTitle("Generated Instances (incl. comments)");
dialog.getContentPane().add(new JScrollPane(textData), BorderLayout.CENTER);
dialog.getContentPane().add(panel, BorderLayout.SOUTH);
dialog.pack();
// make sure, it's not bigger than 80% of the screen
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int width =
dialog.getWidth() > screen.getWidth() * 0.8 ? (int) (screen.getWidth() * 0.8)
: dialog.getWidth();
int height =
dialog.getHeight() > screen.getHeight() * 0.8 ? (int) (screen.getHeight() * 0.8)
: dialog.getHeight();
dialog.setSize(width, height);
dialog.pack();
dialog.setLocationRelativeTo(SwingUtilities.getWindowAncestor(PreprocessPanel.this));
// display dialog
dialog.setVisible(true);
}
/**
* Pops up generic object editor with list of conversion filters
*
* @param f the File
*/
private void converterQuery(final File f) {
final GenericObjectEditor convEd = new GenericObjectEditor(true);
try {
convEd.setClassType(weka.core.converters.Loader.class);
convEd.setValue(new weka.core.converters.CSVLoader());
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
tryConverter((Loader) convEd.getValue(), f);
}
};
((GenericObjectEditor.GOEPanel) convEd.getCustomEditor()).addOkListener(al);
PropertyDialog pd;
if (PropertyDialog.getParentDialog(this) != null)
pd =
new PropertyDialog(PropertyDialog.getParentDialog(this), convEd, -1, -1);
else
pd =
new PropertyDialog(PropertyDialog.getParentFrame(this), convEd, -1, -1);
pd.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
((GenericObjectEditor.GOEPanel) convEd.getCustomEditor()).removeOkListener(al);
pd.dispose();
}
@Override
public void windowClosed(WindowEvent e) {
pd.setContentPane(new JPanel());
pd.removeWindowListener(this);
}
});
pd.setVisible(true);
} catch (Exception ex) {
}
}
/**
* Applies the selected converter
*
* @param cnv the converter to apply to the input file
* @param f the input file
*/
private void tryConverter(final Loader cnv, final File f) {
if (m_IOThread == null) {
m_IOThread = new Thread() {
@Override
public void run() {
try {
cnv.setSource(f);
Instances inst = cnv.getDataSet();
setInstances(inst);
} catch (Exception ex) {
m_Log.statusMessage(cnv.getClass().getName() + " failed to load "
+ f.getName());
JOptionPane.showMessageDialog(PreprocessPanel.this, cnv.getClass()
.getName()
+ " failed to load '"
+ f.getName()
+ "'.\n"
+ "Reason:\n" + ex.getMessage(), "Convert File",
JOptionPane.ERROR_MESSAGE);
m_IOThread = null;
converterQuery(f);
}
m_IOThread = null;
}
};
m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
m_IOThread.start();
}
}
/**
* Loads results from a set of instances retrieved with the supplied loader.
* This is started in the IO thread, and a dialog is popped up if there's a
* problem.
*
* @param loader the loader to use
*/
public void setInstancesFromFile(final AbstractFileLoader loader) {
if (m_IOThread == null) {
m_IOThread = new Thread() {
@Override
public void run() {
try {
m_Log.statusMessage("Reading from file...");
Instances inst = loader.getDataSet();
setInstances(inst);
} catch (Exception ex) {
m_Log.statusMessage("File '" + loader.retrieveFile()
+ "' not recognised as an '" + loader.getFileDescription()
+ "' file.");
m_IOThread = null;
if (JOptionPane.showOptionDialog(
PreprocessPanel.this,
"File '" + loader.retrieveFile() + "' not recognised as an '"
+ loader.getFileDescription() + "' file.\n" + "Reason:\n"
+ ex.getMessage(), "Load Instances", 0,
JOptionPane.ERROR_MESSAGE, null, new String[] { "OK",
"Use Converter" }, null) == 1) {
converterQuery(loader.retrieveFile());
}
}
m_IOThread = null;
}
};
m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
m_IOThread.start();
} else {
JOptionPane.showMessageDialog(this, "Can't load at this time,\n"
+ "currently busy with other IO", "Load Instances",
JOptionPane.WARNING_MESSAGE);
}
}
/**
* Loads instances from a database
*
* @param iq the InstanceQuery object to load from (this is assumed to have
* been already connected to a valid database).
*/
public void setInstancesFromDB(final InstanceQuery iq) {
if (m_IOThread == null) {
m_IOThread = new Thread() {
@Override
public void run() {
try {
m_Log.statusMessage("Reading from database...");
final Instances i = iq.retrieveInstances();
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
setInstances(new Instances(i));
}
});
iq.disconnectFromDatabase();
} catch (Exception ex) {
m_Log.statusMessage("Problem executing DB query " + m_SQLQ);
JOptionPane.showMessageDialog(PreprocessPanel.this,
"Couldn't read from database:\n" + ex.getMessage(),
"Load Instances", JOptionPane.ERROR_MESSAGE);
}
m_IOThread = null;
}
};
m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
m_IOThread.start();
} else {
JOptionPane.showMessageDialog(this, "Can't load at this time,\n"
+ "currently busy with other IO", "Load Instances",
JOptionPane.WARNING_MESSAGE);
}
}
/**
* Loads instances from a URL.
*
* @param u the URL to load from.
*/
public void setInstancesFromURL(final URL u) {
if (m_IOThread == null) {
m_IOThread = new Thread() {
@Override
public void run() {
try {
m_Log.statusMessage("Reading from URL...");
AbstractFileLoader loader =
ConverterUtils.getURLLoaderForFile(u.toString());
if (loader == null)
throw new Exception(
"No suitable URLSourcedLoader found for URL!\n" + u);
((URLSourcedLoader) loader).setURL(u.toString());
setInstances(loader.getDataSet());
} catch (Exception ex) {
ex.printStackTrace();
m_Log.statusMessage("Problem reading " + u);
JOptionPane.showMessageDialog(PreprocessPanel.this,
"Couldn't read from URL:\n" + u + "\n" + ex.getMessage(),
"Load Instances", JOptionPane.ERROR_MESSAGE);
}
m_IOThread = null;
}
};
m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
m_IOThread.start();
} else {
JOptionPane.showMessageDialog(this, "Can't load at this time,\n"
+ "currently busy with other IO", "Load Instances",
JOptionPane.WARNING_MESSAGE);
}
}
/**
* Backs up the current state of the dataset, so the changes can be undone.
*
* @throws Exception if an error occurs
*/
public void addUndoPoint() throws Exception {
if (!ExplorerDefaults.get("enableUndo", "true").equalsIgnoreCase("true")) {
return;
}
if (getMainApplication() != null) {
boolean undoEnabled =
getMainApplication().getApplicationSettings().getSetting(
getPerspectiveID(), PreprocessDefaults.ENABLE_UNDO_KEY,
PreprocessDefaults.ENABLE_UNDO, Environment.getSystemWide());
if (!undoEnabled) {
return;
}
}
if (m_Instances != null) {
// create temporary file
File tempFile =
File.createTempFile("weka", SerializedInstancesLoader.FILE_EXTENSION);
tempFile.deleteOnExit();
boolean nonDefaultTmpDir = false;
String dir = "";
if (getMainApplication() != null) {
dir =
getMainApplication()
.getApplicationSettings()
.getSetting(getPerspectiveID(), PreprocessDefaults.UNDO_DIR_KEY,
PreprocessDefaults.UNDO_DIR).toString();
if (Environment.getSystemWide().containsEnvVariables(dir)) {
dir = Environment.getSystemWide().substitute(dir);
}
if (!dir.equals(PreprocessDefaults.UNDO_DIR)) {
nonDefaultTmpDir = true;
}
} else if (!ExplorerDefaults.get("undoDirectory", "%t").equalsIgnoreCase(
"%t")) {
nonDefaultTmpDir = true;
dir = ExplorerDefaults.get("undoDirectory", "%t");
}
if (nonDefaultTmpDir) {
File undoDir = new File(dir);
if (undoDir.exists()) {
String fileName = tempFile.getName();
File newFile = new File(dir + File.separator + fileName);
if (undoDir.canWrite()) {
newFile.deleteOnExit();
tempFile = newFile;
} else {
System.err
.println("Explorer: it doesn't look like we have permission"
+ " to write to the user-specified undo directory " + "'" + dir
+ "'");
}
} else {
System.err.println("Explorer: user-specified undo directory '" + dir
+ "' does not exist!");
}
}
ObjectOutputStream oos =
new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(
tempFile)));
oos.writeObject(m_Instances);
oos.flush();
oos.close();
// update undo file list
if (m_tempUndoFiles[m_tempUndoIndex] != null) {
// remove undo points that are too old
m_tempUndoFiles[m_tempUndoIndex].delete();
}
m_tempUndoFiles[m_tempUndoIndex] = tempFile;
if (++m_tempUndoIndex >= m_tempUndoFiles.length) {
// wrap pointer around
m_tempUndoIndex = 0;
}
m_UndoBut.setEnabled(true);
}
}
/**
* Reverts to the last backed up version of the dataset.
*/
public void undo() {
if (--m_tempUndoIndex < 0) {
// wrap pointer around
m_tempUndoIndex = m_tempUndoFiles.length - 1;
}
if (m_tempUndoFiles[m_tempUndoIndex] != null) {
// load instances from the temporary file
AbstractFileLoader loader =
ConverterUtils.getLoaderForFile(m_tempUndoFiles[m_tempUndoIndex]);
try {
loader.setFile(m_tempUndoFiles[m_tempUndoIndex]);
setInstancesFromFile(loader);
} catch (Exception e) {
e.printStackTrace();
m_Log.logMessage(e.toString());
JOptionPane.showMessageDialog(PreprocessPanel.this,
"Cannot perform undo operation!\n" + e.toString(), "Undo",
JOptionPane.ERROR_MESSAGE);
}
// update undo file list
m_tempUndoFiles[m_tempUndoIndex] = null;
}
// update undo button
int temp = m_tempUndoIndex - 1;
if (temp < 0) {
temp = m_tempUndoFiles.length - 1;
}
m_UndoBut.setEnabled(m_tempUndoFiles[temp] != null);
}
/**
* edits the current instances object in the viewer
*/
public void edit() {
ViewerDialog dialog;
int result;
Instances copy;
Instances newInstances;
final int classIndex = m_AttVisualizePanel.getColoringIndex();
copy = new Instances(m_Instances);
copy.setClassIndex(classIndex);
dialog = new ViewerDialog(null);
dialog.pack();
dialog.setSize(1000, 600);
dialog.setIconImage(((Frame) SwingUtilities.getWindowAncestor(PreprocessPanel.this)).getIconImage());
dialog.setLocationRelativeTo(SwingUtilities.getWindowAncestor(PreprocessPanel.this));
result = dialog.showDialog(copy);
if (result == ViewerDialog.APPROVE_OPTION) {
try {
addUndoPoint();
} catch (Exception e) {
e.printStackTrace();
}
// if class was not set before, reset it again after use of filter
newInstances = dialog.getInstances();
if (m_Instances.classIndex() < 0)
newInstances.setClassIndex(-1);
setInstances(newInstances);
}
}
/**
* Sets the Explorer to use as parent frame (used for sending notifications
* about changes in the data)
*
* @param parent the parent frame
*/
public void setExplorer(Explorer parent) {
m_Explorer = parent;
}
/**
* returns the parent Explorer frame
*
* @return the parent
*/
public Explorer getExplorer() {
return m_Explorer;
}
/**
* updates the capabilities filter of the GOE
*
* @param filter the new filter to use
*/
protected void updateCapabilitiesFilter(Capabilities filter) {
Instances tempInst;
Capabilities filterClass;
if (filter == null) {
m_FilterEditor.setCapabilitiesFilter(new Capabilities(null));
return;
}
if (!ExplorerDefaults.getInitGenericObjectEditorFilter())
tempInst = new Instances(m_Instances, 0);
else
tempInst = new Instances(m_Instances);
tempInst
.setClassIndex(m_AttVisualizePanel.getColorBox().getSelectedIndex() - 1);
try {
filterClass = Capabilities.forInstances(tempInst);
} catch (Exception e) {
filterClass = new Capabilities(null);
}
// set new filter
m_FilterEditor.setCapabilitiesFilter(filterClass);
// check capabilities
m_ApplyFilterBut.setEnabled(true);
Capabilities currentCapabilitiesFilter =
m_FilterEditor.getCapabilitiesFilter();
Filter currentFilter = (Filter) m_FilterEditor.getValue();
Capabilities currentFilterCapabilities = null;
if (currentFilter != null && currentCapabilitiesFilter != null
&& (currentFilter instanceof CapabilitiesHandler)) {
currentFilterCapabilities =
((CapabilitiesHandler) currentFilter).getCapabilities();
if (!currentFilterCapabilities.supportsMaybe(currentCapabilitiesFilter)
&& !currentFilterCapabilities.supports(currentCapabilitiesFilter)) {
try {
currentFilter.setInputFormat(getInstances());
} catch (Exception ex) {
m_ApplyFilterBut.setEnabled(false);
}
}
}
}
/**
* method gets called in case of a change event
*
* @param e the associated change event
*/
public void capabilitiesFilterChanged(CapabilitiesFilterChangeEvent e) {
if (e.getFilter() == null)
updateCapabilitiesFilter(null);
else
updateCapabilitiesFilter((Capabilities) e.getFilter().clone());
}
/**
* Returns the title for the tab in the Explorer
*
* @return the title of this tab
*/
public String getTabTitle() {
return "Preprocess";
}
/**
* Returns the tooltip for the tab in the Explorer
*
* @return the tooltip of this tab
*/
public String getTabTitleToolTip() {
return "Open/Edit/Save instances";
}
@Override
public Defaults getDefaultSettings() {
return new PreprocessDefaults();
}
@Override
public void setActive(boolean active) {
super.setActive(active);
if (m_isActive) {
updateSettings();
}
}
@Override
public void settingsChanged() {
updateSettings();
}
protected void updateSettings() {
File initialDir =
getMainApplication().getApplicationSettings().getSetting(
getPerspectiveID(), PreprocessDefaults.INITIAL_DIR_KEY,
PreprocessDefaults.INITIAL_DIR, Environment.getSystemWide());
if (Environment.getSystemWide().containsEnvVariables(initialDir.toString())) {
String initDir = initialDir.toString();
try {
initDir = Environment.getSystemWide().substitute(initDir);
initialDir = new File(initDir);
} catch (Exception ex) {
}
}
m_FileChooser.setCurrentDirectory(initialDir);
if (!m_initialSettingsSet) {
// only want to set the preferred starting filter once!
Filter toUse =
getMainApplication().getApplicationSettings().getSetting(
getPerspectiveID(), PreprocessDefaults.FILTER_KEY,
PreprocessDefaults.FILTER, Environment.getSystemWide());
m_FilterEditor.setValue(toUse);
m_UndoBut.setEnabled(false);
m_initialSettingsSet = true;
}
/*
* m_UndoBut.setEnabled(getMainApplication().getApplicationSettings()
* .getSetting(PreprocessDefaults.ID, PreprocessDefaults.ENABLE_UNDO_KEY,
* PreprocessDefaults.ENABLE_UNDO, Environment.getSystemWide()));
*/
boolean sendToAll =
getMainApplication().getApplicationSettings().getSetting(
getPerspectiveID(),
PreprocessDefaults.ALWAYS_SEND_INSTANCES_TO_ALL_KEY,
PreprocessDefaults.ALWAYS_SEND_INSTANCES_TO_ALL,
Environment.getSystemWide());
if (sendToAll && getInstances() != null) {
// check to see if any perspectives that might now be visible need
// instances to be set (assume that if they are not okToBeActive() then
// they need the current set of instances
List visiblePerspectives =
getMainApplication().getPerspectiveManager().getVisiblePerspectives();
for (Perspective p : visiblePerspectives) {
if (!p.okToBeActive() && p.acceptsInstances()) {
p.setInstances(getInstances());
}
if (p.okToBeActive()) {
getMainApplication().getPerspectiveManager().setEnablePerspectiveTab(
p.getPerspectiveID(), true);
}
}
}
if (m_sendToPerspective != null) {
m_sendToPerspective.setEnabled(!sendToAll && getInstances() != null);
}
}
@Override
public List getMenus() {
return m_menus;
}
public static class PreprocessDefaults extends Defaults {
public static final String ID = "weka.gui.explorer.preprocesspanel";
public static final Settings.SettingKey INITIAL_DIR_KEY =
new Settings.SettingKey(ID + ".initialDir",
"Initial directory for opening datasets", "");
public static final File INITIAL_DIR = new File("${user.dir}");
public static final Settings.SettingKey UNDO_DIR_KEY =
new Settings.SettingKey(ID + ".undoDir",
"Directory for storing undo files", "");
public static final File UNDO_DIR = new File("${java.io.tmpdir}");
public static final Settings.SettingKey FILTER_KEY =
new Settings.SettingKey(ID + ".initialFilter", "Initial filter", "");
public static final Filter FILTER = new AllFilter();
public static final Settings.SettingKey ENABLE_UNDO_KEY =
new Settings.SettingKey(ID + ".enableUndo", "Enable undo", "");
public static final Boolean ENABLE_UNDO = true;
public static final Settings.SettingKey ALWAYS_SEND_INSTANCES_TO_ALL_KEY =
new Settings.SettingKey(ID + ".alwaysSendInstancesToAllPerspectives",
"Always send instances to all perspectives", "");
public static boolean ALWAYS_SEND_INSTANCES_TO_ALL = true;
public PreprocessDefaults() {
super(ID);
INITIAL_DIR_KEY.setMetadataElement("java.io.File.fileSelectionMode", ""
+ JFileChooser.DIRECTORIES_ONLY);
INITIAL_DIR_KEY.setMetadataElement("java.io.File.dialogType", ""
+ JFileChooser.OPEN_DIALOG);
UNDO_DIR_KEY.setMetadataElement("java.io.File.fileSelectionMode", ""
+ JFileChooser.DIRECTORIES_ONLY);
UNDO_DIR_KEY.setMetadataElement("java.io.File.dialogType", ""
+ JFileChooser.DIRECTORIES_ONLY);
m_defaults.put(INITIAL_DIR_KEY, INITIAL_DIR);
m_defaults.put(UNDO_DIR_KEY, UNDO_DIR);
m_defaults.put(FILTER_KEY, FILTER);
m_defaults.put(ENABLE_UNDO_KEY, ENABLE_UNDO);
m_defaults.put(ALWAYS_SEND_INSTANCES_TO_ALL_KEY,
ALWAYS_SEND_INSTANCES_TO_ALL);
}
}
/**
* Tests out the instance-preprocessing panel from the command line.
*
* @param args ignored
*/
public static void main(String[] args) {
try {
final JFrame jf = new JFrame("Weka Explorer: Preprocess");
jf.getContentPane().setLayout(new BorderLayout());
final PreprocessPanel sp = new PreprocessPanel();
jf.getContentPane().add(sp, BorderLayout.CENTER);
weka.gui.LogPanel lp = new weka.gui.LogPanel();
sp.setLog(lp);
jf.getContentPane().add(lp, BorderLayout.SOUTH);
jf.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
jf.dispose();
System.exit(0);
}
});
jf.pack();
jf.setSize(800, 600);
jf.setVisible(true);
} catch (Exception ex) {
ex.printStackTrace();
System.err.println(ex.getMessage());
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy