/* * 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 2 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Explorer.java * Copyright (C) 1999 University of Waikato, Hamilton, New Zealand * */ package weka.gui.explorer; import weka.core.Capabilities; import weka.core.Copyright; import weka.core.Instances; import weka.core.Memory; import weka.core.converters.AbstractFileLoader; import weka.core.converters.ConverterUtils; import weka.gui.LogPanel; import weka.gui.Logger; import weka.gui.LookAndFeel; import weka.gui.WekaTaskMonitor; import java.awt.BorderLayout; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; import java.util.EventListener; import java.util.HashSet; import java.util.Hashtable; import java.util.Vector; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.event.ChangeEvent; /** * The main class for the Weka explorer. Lets the user create, * open, save, configure, datasets, and perform ML analysis. * * @author Len Trigg (trigg@cs.waikato.ac.nz) * @version $Revision: 7190 $ */ public class Explorer extends JPanel { /** for serialization */ private static final long serialVersionUID = -7674003708867909578L; /** * Interface for classes that listen for filter changes. * * @author FracPete (fracpete at waikato dot ac dot nz) * @version $Revision: 7190 $ */ public static interface CapabilitiesFilterChangeListener extends EventListener { /** * method gets called in case of a change event * * @param e the associated change event */ public void capabilitiesFilterChanged(CapabilitiesFilterChangeEvent e); } /** * This event can be fired in case the capabilities filter got changed * * @author FracPete (fracpete at waikato dot ac dot nz) * @version $Revision: 7190 $ */ public static class CapabilitiesFilterChangeEvent extends ChangeEvent { /** for serialization */ private static final long serialVersionUID = 1194260517270385559L; /** the capabilities filter */ protected Capabilities m_Filter; /** * Constructs a GOECapabilitiesFilterChangeEvent object. * * @param source the Object that is the source of the event * @param filter the responsible capabilities filter */ public CapabilitiesFilterChangeEvent(Object source, Capabilities filter) { super(source); m_Filter = filter; } /** * returns the associated Capabilities filter * * @return the filter */ public Capabilities getFilter() { return m_Filter; } } /** * A common interface for panels to be displayed in the Explorer * * @author FracPete (fracpete at waikato dot ac dot nz) * @version $Revision: 7190 $ */ public static interface ExplorerPanel { /** * 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); /** * returns the parent Explorer frame * * @return the parent */ public Explorer getExplorer(); /** * Tells the panel to use a new set of instances. * * @param inst a set of Instances */ public void setInstances(Instances inst); /** * Returns the title for the tab in the Explorer * * @return the title of this tab */ public String getTabTitle(); /** * Returns the tooltip for the tab in the Explorer * * @return the tooltip of this tab */ public String getTabTitleToolTip(); } /** * A common interface for panels in the explorer that can handle logs * * @author FracPete (fracpete at waikato dot ac dot nz) * @version $Revision: 7190 $ */ public static interface LogHandler { /** * Sets the Logger to receive informational messages * * @param newLog the Logger that will now get info messages */ public void setLog(Logger newLog); } /** The panel for preprocessing instances */ protected PreprocessPanel m_PreprocessPanel = new PreprocessPanel(); /** Contains all the additional panels apart from the pre-processing panel */ protected Vector<ExplorerPanel> m_Panels = new Vector<ExplorerPanel>(); /** The tabbed pane that controls which sub-pane we are working with */ protected JTabbedPane m_TabbedPane = new JTabbedPane(); /** The panel for log and status messages */ protected LogPanel m_LogPanel = new LogPanel(new WekaTaskMonitor()); /** the listeners that listen to filter changes */ protected HashSet<CapabilitiesFilterChangeListener> m_CapabilitiesFilterChangeListeners = new HashSet<CapabilitiesFilterChangeListener>(); /** * Creates the experiment environment gui with no initial experiment */ public Explorer() { String date = (new SimpleDateFormat("EEEE, d MMMM yyyy")).format(new Date()); m_LogPanel.logMessage("Weka Explorer"); m_LogPanel.logMessage("(c) " + Copyright.getFromYear() + "-" + Copyright.getToYear() + " " + Copyright.getOwner() + ", " + Copyright.getAddress()); m_LogPanel.logMessage("web: " + Copyright.getURL()); m_LogPanel.logMessage("Started on " + date); m_LogPanel.statusMessage("Welcome to the Weka Explorer"); // intialize pre-processpanel m_PreprocessPanel.setLog(m_LogPanel); m_TabbedPane.addTab( m_PreprocessPanel.getTabTitle(), null, m_PreprocessPanel, m_PreprocessPanel.getTabTitleToolTip()); // initialize additional panels String[] tabs = ExplorerDefaults.getTabs(); Hashtable<String, HashSet> tabOptions = new Hashtable<String, HashSet>(); for (int i = 0; i < tabs.length; i++) { try { // determine classname and additional options String[] optionsStr = tabs[i].split(":"); String classname = optionsStr[0]; HashSet options = new HashSet(); tabOptions.put(classname, options); for (int n = 1; n < optionsStr.length; n++) options.add(optionsStr[n]); // setup panel ExplorerPanel panel = (ExplorerPanel) Class.forName(classname).newInstance(); panel.setExplorer(this); m_Panels.add(panel); if (panel instanceof LogHandler) ((LogHandler) panel).setLog(m_LogPanel); m_TabbedPane.addTab( panel.getTabTitle(), null, (JPanel) panel, panel.getTabTitleToolTip()); } catch (Exception e) { e.printStackTrace(); } } // setup tabbed pane m_TabbedPane.setSelectedIndex(0); for (int i = 0; i < m_Panels.size(); i++) { HashSet options = tabOptions.get(m_Panels.get(i).getClass().getName()); m_TabbedPane.setEnabledAt(i + 1, options.contains("standalone")); } // setup notification for dataset changes m_PreprocessPanel.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { for (int i = 0; i < m_Panels.size(); i++) { m_Panels.get(i).setInstances(m_PreprocessPanel.getInstances()); m_TabbedPane.setEnabledAt(i + 1, true); } } }); // add listeners for changes in the capabilities m_PreprocessPanel.setExplorer(this); addCapabilitiesFilterListener(m_PreprocessPanel); for (int i = 0; i < m_Panels.size(); i++) { if (m_Panels.get(i) instanceof CapabilitiesFilterChangeListener) addCapabilitiesFilterListener((CapabilitiesFilterChangeListener) m_Panels.get(i)); } // add components to layout setLayout(new BorderLayout()); add(m_TabbedPane, BorderLayout.CENTER); add(m_LogPanel, BorderLayout.SOUTH); } /** * returns all the panels, apart from the PreprocessPanel * * @return the currently displayed panels w/o PreprocessPanel */ public Vector<ExplorerPanel> getPanels() { return m_Panels; } /** * returns the instance of the PreprocessPanel being used in this instance * of the Explorer * * @return the panel */ public PreprocessPanel getPreprocessPanel() { return m_PreprocessPanel; } /** * returns the tabbed pane of the Explorer * * @return the tabbed pane */ public JTabbedPane getTabbedPane() { return m_TabbedPane; } /** * adds the listener to the list of objects that listen for changes of the * CapabilitiesFilter * * @param l the listener to add * @see #m_CapabilitiesFilterChangeListeners */ public void addCapabilitiesFilterListener(CapabilitiesFilterChangeListener l) { m_CapabilitiesFilterChangeListeners.add(l); } /** * Removes the specified listener from the set of listeners if it is present. * * @param l the listener to remove * @return true if the listener was registered */ public boolean removeCapabilitiesFilterListener(CapabilitiesFilterChangeListener l) { return m_CapabilitiesFilterChangeListeners.remove(l); } /** * notifies all the listeners of a change * * @param filter the affected filter */ public void notifyCapabilitiesFilterListener(Capabilities filter) { for (CapabilitiesFilterChangeListener l: m_CapabilitiesFilterChangeListeners) { if (l == this) continue; l.capabilitiesFilterChanged(new CapabilitiesFilterChangeEvent(this, filter)); } } /** variable for the Explorer class which would be set to null by the memory monitoring thread to free up some memory if we running out of memory */ private static Explorer m_explorer; /** for monitoring the Memory consumption */ private static Memory m_Memory = new Memory(true); /** * Tests out the explorer environment. * * @param args ignored. */ public static void main(String [] args) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.INFO, "Logging started"); LookAndFeel.setLookAndFeel(); // make sure that packages are loaded and the GenericPropertiesCreator // executes to populate the lists correctly weka.gui.GenericObjectEditor.determineClasses(); try { // uncomment to disable the memory management: //m_Memory.setEnabled(false); m_explorer = new Explorer(); final JFrame jf = new JFrame("Weka Explorer"); jf.getContentPane().setLayout(new BorderLayout()); jf.getContentPane().add(m_explorer, BorderLayout.CENTER); jf.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { jf.dispose(); System.exit(0); } }); jf.pack(); jf.setSize(800, 600); jf.setVisible(true); Image icon = Toolkit.getDefaultToolkit(). getImage(m_explorer.getClass().getClassLoader().getResource("weka/gui/weka_icon_new_48.png")); jf.setIconImage(icon); if (args.length == 1) { System.err.println("Loading instances from " + args[0]); AbstractFileLoader loader = ConverterUtils.getLoaderForFile(args[0]); loader.setFile(new File(args[0])); m_explorer.m_PreprocessPanel.setInstancesFromFile(loader); } Thread memMonitor = new Thread() { public void run() { while(true) { try { //System.out.println("Before sleeping."); this.sleep(4000); System.gc(); if (m_Memory.isOutOfMemory()) { // clean up jf.dispose(); m_explorer = null; System.gc(); // stop threads m_Memory.stopThreads(); // display error System.err.println("\ndisplayed message:"); m_Memory.showOutOfMemory(); System.err.println("\nexiting"); System.exit(-1); } } catch(InterruptedException ex) { ex.printStackTrace(); } } } }; memMonitor.setPriority(Thread.MAX_PRIORITY); memMonitor.start(); } catch (Exception ex) { ex.printStackTrace(); System.err.println(ex.getMessage()); } } }