/* * 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. */ /* * RunPanel.java * Copyright (C) 1999 University of Waikato, Hamilton, New Zealand * */ package weka.gui.experiment; import weka.core.SerializedObject; import weka.core.Utils; import weka.experiment.Experiment; import weka.experiment.RemoteExperiment; import weka.experiment.RemoteExperimentEvent; import weka.experiment.RemoteExperimentListener; import weka.gui.LogPanel; import java.awt.BorderLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.ObjectInputStream; import java.io.Serializable; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; /** * This panel controls the running of an experiment. * * @author Len Trigg (trigg@cs.waikato.ac.nz) * @version $Revision: 1.21 $ */ public class RunPanel extends JPanel implements ActionListener { /** for serialization */ private static final long serialVersionUID = 1691868018596872051L; /** The message displayed when no experiment is running */ protected static final String NOT_RUNNING = "Not running"; /** Click to start running the experiment */ protected JButton m_StartBut = new JButton("Start"); /** Click to signal the running experiment to halt */ protected JButton m_StopBut = new JButton("Stop"); protected LogPanel m_Log = new LogPanel(); /** The experiment to run */ protected Experiment m_Exp; /** The thread running the experiment */ protected Thread m_RunThread = null; /** A pointer to the results panel */ protected ResultsPanel m_ResultsPanel = null; /* * A class that handles running a copy of the experiment * in a separate thread */ class ExperimentRunner extends Thread implements Serializable { /** for serialization */ private static final long serialVersionUID = -5591889874714150118L; Experiment m_ExpCopy; public ExperimentRunner(final Experiment exp) throws Exception { // Create a full copy using serialization if (exp == null) { System.err.println("Null experiment!!!"); } else { System.err.println("Running experiment: " + exp.toString()); } System.err.println("Writing experiment copy"); SerializedObject so = new SerializedObject(exp); System.err.println("Reading experiment copy"); m_ExpCopy = (Experiment) so.getObject(); System.err.println("Made experiment copy"); } public void abortExperiment() { if (m_ExpCopy instanceof RemoteExperiment) { ((RemoteExperiment)m_ExpCopy).abortExperiment(); // m_StartBut.setEnabled(true); m_StopBut.setEnabled(false); // statusMessage(NOT_RUNNING); } } /** * Starts running the experiment. */ public void run() { m_StartBut.setEnabled(false); m_StopBut.setEnabled(true); if (m_ResultsPanel != null) { m_ResultsPanel.setExperiment(null); } try { if (m_ExpCopy instanceof RemoteExperiment) { // add a listener System.err.println("Adding a listener"); ((RemoteExperiment)m_ExpCopy). addRemoteExperimentListener(new RemoteExperimentListener() { public void remoteExperimentStatus(RemoteExperimentEvent e) { if (e.m_statusMessage) { statusMessage(e.m_messageString); } if (e.m_logMessage) { logMessage(e.m_messageString); } if (e.m_experimentFinished) { m_RunThread = null; m_StartBut.setEnabled(true); m_StopBut.setEnabled(false); statusMessage(NOT_RUNNING); } } }); } logMessage("Started"); statusMessage("Initializing..."); m_ExpCopy.initialize(); int errors = 0; if (!(m_ExpCopy instanceof RemoteExperiment)) { statusMessage("Iterating..."); while (m_RunThread != null && m_ExpCopy.hasMoreIterations()) { try { String current = "Iteration:"; if (m_ExpCopy.getUsePropertyIterator()) { int cnum = m_ExpCopy.getCurrentPropertyNumber(); String ctype = m_ExpCopy.getPropertyArray().getClass().getComponentType().getName(); int lastDot = ctype.lastIndexOf('.'); if (lastDot != -1) { ctype = ctype.substring(lastDot + 1); } String cname = " " + ctype + "=" + (cnum + 1) + ":" + m_ExpCopy.getPropertyArrayValue(cnum).getClass().getName(); current += cname; } String dname = ((File) m_ExpCopy.getDatasets() .elementAt(m_ExpCopy.getCurrentDatasetNumber())) .getName(); current += " Dataset=" + dname + " Run=" + (m_ExpCopy.getCurrentRunNumber()); statusMessage(current); m_ExpCopy.nextIteration(); } catch (Exception ex) { errors ++; logMessage(ex.getMessage()); ex.printStackTrace(); boolean continueAfterError = false; if (continueAfterError) { m_ExpCopy.advanceCounters(); // Try to keep plowing through } else { m_RunThread = null; } } } statusMessage("Postprocessing..."); m_ExpCopy.postProcess(); if (m_RunThread == null) { logMessage("Interrupted"); } else { logMessage("Finished"); } if (errors == 1) { logMessage("There was " + errors + " error"); } else { logMessage("There were " + errors + " errors"); } statusMessage(NOT_RUNNING); } else { statusMessage("Remote experiment running..."); ((RemoteExperiment)m_ExpCopy).runExperiment(); } } catch (Exception ex) { ex.printStackTrace(); System.err.println(ex.getMessage()); statusMessage(ex.getMessage()); } finally { if (m_ResultsPanel != null) { m_ResultsPanel.setExperiment(m_ExpCopy); } if (!(m_ExpCopy instanceof RemoteExperiment)) { m_RunThread = null; m_StartBut.setEnabled(true); m_StopBut.setEnabled(false); System.err.println("Done..."); } } } } /** * Sets the pointer to the results panel. */ public void setResultsPanel(ResultsPanel rp) { m_ResultsPanel = rp; } /** * Creates the run panel with no initial experiment. */ public RunPanel() { m_StartBut.addActionListener(this); m_StopBut.addActionListener(this); m_StartBut.setEnabled(false); m_StopBut.setEnabled(false); m_StartBut.setMnemonic('S'); m_StopBut.setMnemonic('t'); m_Log.statusMessage(NOT_RUNNING); // Set the GUI layout JPanel controls = new JPanel(); GridBagLayout gb = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); controls.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5)); // controls.setLayout(new GridLayout(1,2)); controls.setLayout(gb); constraints.gridx=0;constraints.gridy=0;constraints.weightx=5; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridwidth=1;constraints.gridheight=1; constraints.insets = new Insets(0,2,0,2); controls.add(m_StartBut,constraints); constraints.gridx=1;constraints.gridy=0;constraints.weightx=5; constraints.gridwidth=1;constraints.gridheight=1; controls.add(m_StopBut,constraints); setLayout(new BorderLayout()); add(controls, BorderLayout.NORTH); add(m_Log, BorderLayout.CENTER); } /** * Creates the panel with the supplied initial experiment. * * @param exp a value of type 'Experiment' */ public RunPanel(Experiment exp) { this(); setExperiment(exp); } /** * Sets the experiment the panel operates on. * * @param exp a value of type 'Experiment' */ public void setExperiment(Experiment exp) { m_Exp = exp; m_StartBut.setEnabled(m_RunThread == null); m_StopBut.setEnabled(m_RunThread != null); } /** * Controls starting and stopping the experiment. * * @param e a value of type 'ActionEvent' */ public void actionPerformed(ActionEvent e) { if (e.getSource() == m_StartBut) { if (m_RunThread == null) { try { m_RunThread = new ExperimentRunner(m_Exp); m_RunThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority m_RunThread.start(); } catch (Exception ex) { ex.printStackTrace(); logMessage("Problem creating experiment copy to run: " + ex.getMessage()); } } } else if (e.getSource() == m_StopBut) { m_StopBut.setEnabled(false); logMessage("User aborting experiment. "); if (m_Exp instanceof RemoteExperiment) { logMessage("Waiting for remote tasks to " +"complete..."); } ((ExperimentRunner)m_RunThread).abortExperiment(); // m_RunThread.stop() ?? m_RunThread = null; } } /** * Sends the supplied message to the log panel log area. * * @param message the message to log */ protected void logMessage(String message) { m_Log.logMessage(message); } /** * Sends the supplied message to the log panel status line. * * @param message the status message */ protected void statusMessage(String message) { m_Log.statusMessage(message); } /** * Tests out the run panel from the command line. * * @param args may contain options specifying an experiment to run. */ public static void main(String [] args) { try { boolean readExp = Utils.getFlag('l', args); final String expFile = Utils.getOption('f', args); if (readExp && (expFile.length() == 0)) { throw new Exception("A filename must be given with the -f option"); } Experiment exp = null; if (readExp) { FileInputStream fi = new FileInputStream(expFile); ObjectInputStream oi = new ObjectInputStream( new BufferedInputStream(fi)); Object to = oi.readObject(); if (to instanceof RemoteExperiment) { exp = (RemoteExperiment)to; } else { exp = (Experiment)to; } oi.close(); } else { exp = new Experiment(); } System.err.println("Initial Experiment:\n" + exp.toString()); final JFrame jf = new JFrame("Run Weka Experiment"); jf.getContentPane().setLayout(new BorderLayout()); final RunPanel sp = new RunPanel(exp); //sp.setBorder(BorderFactory.createTitledBorder("Setup")); jf.getContentPane().add(sp, BorderLayout.CENTER); jf.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.err.println("\nExperiment Configuration\n" + sp.m_Exp.toString()); jf.dispose(); System.exit(0); } }); jf.pack(); jf.setVisible(true); } catch (Exception ex) { ex.printStackTrace(); System.err.println(ex.getMessage()); } } }