PreprocessPanel.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 28k
Category:

Windows Develop

Development Platform:

Java

  1. /*
  2.  *    This program is free software; you can redistribute it and/or modify
  3.  *    it under the terms of the GNU General Public License as published by
  4.  *    the Free Software Foundation; either version 2 of the License, or
  5.  *    (at your option) any later version.
  6.  *
  7.  *    This program is distributed in the hope that it will be useful,
  8.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.  *    GNU General Public License for more details.
  11.  *
  12.  *    You should have received a copy of the GNU General Public License
  13.  *    along with this program; if not, write to the Free Software
  14.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  */
  16. /*
  17.  *    PreprocessPanel.java
  18.  *    Copyright (C) 1999 Len Trigg
  19.  *
  20.  */
  21. package weka.gui.explorer;
  22. import java.awt.BorderLayout;
  23. import java.awt.GridLayout;
  24. import java.awt.event.ActionEvent;
  25. import java.awt.event.ActionListener;
  26. import java.awt.event.WindowAdapter;
  27. import java.awt.event.WindowEvent;
  28. import java.beans.PropertyChangeEvent;
  29. import java.beans.PropertyChangeListener;
  30. import java.beans.PropertyChangeSupport;
  31. import java.io.BufferedReader;
  32. import java.io.BufferedWriter;
  33. import java.io.File;
  34. import java.io.FileReader;
  35. import java.io.FileWriter;
  36. import java.io.InputStreamReader;
  37. import java.io.Reader;
  38. import java.io.Writer;
  39. import java.net.URL;
  40. import javax.swing.BorderFactory;
  41. import javax.swing.JButton;
  42. import javax.swing.JFileChooser;
  43. import javax.swing.JFrame;
  44. import javax.swing.JLabel;
  45. import javax.swing.JOptionPane;
  46. import javax.swing.JPanel;
  47. import javax.swing.ListSelectionModel;
  48. import javax.swing.SwingConstants;
  49. import javax.swing.SwingUtilities;
  50. import javax.swing.event.ListSelectionEvent;
  51. import javax.swing.event.ListSelectionListener;
  52. import javax.swing.filechooser.FileFilter;
  53. import weka.core.Instances;
  54. import weka.core.SerializedObject;
  55. import weka.core.converters.Loader;
  56. import weka.experiment.InstanceQuery;
  57. import weka.filters.Filter;
  58. import weka.filters.UnsupervisedFilter;
  59. import weka.gui.AttributeSelectionPanel;
  60. import weka.gui.AttributeSummaryPanel;
  61. import weka.gui.ExtensionFileFilter;
  62. import weka.gui.FileEditor;
  63. import weka.gui.GenericArrayEditor;
  64. import weka.gui.GenericObjectEditor;
  65. import weka.gui.InstancesSummaryPanel;
  66. import weka.gui.Logger;
  67. import weka.gui.PropertyDialog;
  68. import weka.gui.SysErrLog;
  69. import weka.gui.TaskLogger;
  70. import weka.core.UnassignedClassException;
  71. /** 
  72.  * This panel controls simple preprocessing of instances. Attributes may be
  73.  * selected for inclusion/exclusion, summary information on instances and
  74.  * attributes is shown. A sequence of filters may be configured to alter the
  75.  * set of instances. Altered instances may also be saved.
  76.  *
  77.  * @author Len Trigg (trigg@cs.waikato.ac.nz)
  78.  * @version $Revision: 1.29 $
  79.  */
  80. public class PreprocessPanel extends JPanel {
  81.   /** Displays simple stats on the base instances */
  82.   protected InstancesSummaryPanel m_BaseInstPanel =
  83.     new InstancesSummaryPanel();
  84.   
  85.   /** Displays simple stats on the working instances */
  86.   protected InstancesSummaryPanel m_WorkingInstPanel =
  87.     new InstancesSummaryPanel();
  88.   /** Click to load base instances from a file */
  89.   protected JButton m_OpenFileBut = new JButton("Open file...");
  90.   /** Click to load base instances from a URL */
  91.   protected JButton m_OpenURLBut = new JButton("Open URL...");
  92.   /** Click to load base instances from a Database */
  93.   protected JButton m_OpenDBBut = new JButton("Open DB...");
  94.   protected GenericObjectEditor m_DatabaseQueryEditor = 
  95.     new GenericObjectEditor();
  96.   /** Click to apply filters and replace the working dataset */
  97.   protected JButton m_ApplyBut = new JButton("Apply Filters");
  98.   /** Click to replace the base dataset with the working dataset */
  99.   protected JButton m_ReplaceBut = new JButton("Replace");
  100.   /** Click to apply filters and save the results */
  101.   protected JButton m_SaveBut = new JButton("Save...");
  102.   
  103.   /** Panel to let the user toggle attributes */
  104.   protected AttributeSelectionPanel m_AttPanel = new AttributeSelectionPanel();
  105.   /** Lets the user add a series of filters */
  106.   protected GenericArrayEditor m_Filters = new GenericArrayEditor();
  107.   /** Displays summary stats on the selected attribute */
  108.   protected AttributeSummaryPanel m_AttSummaryPanel =
  109.     new AttributeSummaryPanel();
  110.   
  111.   /** Filter to ensure only arff files are selected */  
  112.   protected FileFilter m_ArffFilter =
  113.     new ExtensionFileFilter(Instances.FILE_EXTENSION, "Arff data files");
  114.   /** The file chooser for selecting arff files */
  115.   protected JFileChooser m_FileChooser 
  116.     = new JFileChooser(new File(System.getProperty("user.dir")));
  117.   /** Stores the last URL that instances were loaded from */
  118.   protected String m_LastURL = "http://";
  119.   
  120.   /** Stores the last sql query executed */
  121.   protected String m_SQLQ = new String("SELECT * FROM ?");
  122.   
  123.   /** The unadulterated instances */
  124.   protected Instances m_BaseInstances;
  125.   /** The working (filtered) copy */
  126.   protected Instances m_WorkingInstances;
  127.   
  128.   /**
  129.    * Manages sending notifications to people when we change the set of
  130.    * working instances.
  131.    */
  132.   protected PropertyChangeSupport m_Support = new PropertyChangeSupport(this);
  133.   /** A thread to loading/saving instances from a file or URL */
  134.   protected Thread m_IOThread;
  135.   protected Logger m_Log = new SysErrLog();
  136.   /** A copy of the most recently applied filters */
  137.   protected SerializedObject m_FiltersCopy = null;
  138.   
  139.   static {
  140.     java.beans.PropertyEditorManager
  141.       .registerEditor(java.io.File.class,
  142.                       FileEditor.class);
  143.     java.beans.PropertyEditorManager
  144.       .registerEditor(weka.core.SelectedTag.class,
  145.       weka.gui.SelectedTagEditor.class);
  146.     java.beans.PropertyEditorManager
  147.       .registerEditor(weka.filters.UnsupervisedFilter.class,
  148.       weka.gui.GenericObjectEditor.class);
  149.      java.beans.PropertyEditorManager
  150.       .registerEditor(weka.attributeSelection.ASSearch.class,
  151.       weka.gui.GenericObjectEditor.class);
  152.      java.beans.PropertyEditorManager
  153.       .registerEditor(weka.attributeSelection.ASEvaluation.class,
  154.       weka.gui.GenericObjectEditor.class);
  155.      java.beans.PropertyEditorManager
  156.       .registerEditor(weka.experiment.InstanceQuery.class,
  157.       weka.gui.GenericObjectEditor.class);
  158.      java.beans.PropertyEditorManager
  159.        .registerEditor(weka.core.converters.Loader.class,
  160.       weka.gui.GenericObjectEditor.class);
  161.   }
  162.   
  163.   /**
  164.    * Creates the instances panel with no initial instances.
  165.    */
  166.   public PreprocessPanel() {
  167.     // Create/Configure/Connect components
  168.     try {
  169.     m_DatabaseQueryEditor.setClassType(weka.experiment.InstanceQuery.class);
  170.     m_DatabaseQueryEditor.setValue(new weka.experiment.InstanceQuery());
  171.     ((GenericObjectEditor.GOEPanel)m_DatabaseQueryEditor.getCustomEditor())
  172.       .addOkListener(new ActionListener() {
  173.   public void actionPerformed(ActionEvent e) {
  174.     setBaseInstancesFromDBQ();
  175.   }
  176. });
  177.     } catch (Exception ex) {
  178.     }
  179.     m_OpenFileBut.setToolTipText("Open a set of instances from a file");
  180.     m_OpenURLBut.setToolTipText("Open a set of instances from a URL");
  181.     m_OpenDBBut.setToolTipText("Open a set of instances from a database");
  182.     m_ReplaceBut
  183.       .setToolTipText("Replace the base relation with the working relation");
  184.     m_ApplyBut.setToolTipText("Update working relation with current filters");
  185.     m_SaveBut.setToolTipText("Save the working relation to a file");
  186.     m_Filters.setToolTipText("Edit a list of filters to transform instances");
  187.     m_FileChooser.setFileFilter(m_ArffFilter);
  188.     m_FileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
  189.     m_OpenURLBut.addActionListener(new ActionListener() {
  190.       public void actionPerformed(ActionEvent e) {
  191. setBaseInstancesFromURLQ();
  192.       }
  193.     });
  194.     m_OpenDBBut.addActionListener(new ActionListener() {
  195.       public void actionPerformed(ActionEvent e) {
  196. PropertyDialog pd = new PropertyDialog(m_DatabaseQueryEditor,100,100);
  197. //setBaseInstancesFromDBQ();
  198.       }
  199.     });
  200.     m_OpenFileBut.addActionListener(new ActionListener() {
  201.       public void actionPerformed(ActionEvent e) {
  202. setBaseInstancesFromFileQ();
  203.       }
  204.     });
  205.     m_ReplaceBut.addActionListener(new ActionListener() {
  206.       public void actionPerformed(ActionEvent e) {
  207. setBaseInstances(m_WorkingInstances);
  208.       }
  209.     });
  210.     m_ApplyBut.addActionListener(new ActionListener() {
  211.       public void actionPerformed(ActionEvent e) {
  212. setWorkingInstancesFromFilters();
  213.       }
  214.     });
  215.     m_SaveBut.addActionListener(new ActionListener() {
  216.       public void actionPerformed(ActionEvent e) {
  217. saveWorkingInstancesToFileQ();
  218.       }
  219.     });
  220.     m_AttPanel.getSelectionModel()
  221.       .addListSelectionListener(new ListSelectionListener() {
  222. public void valueChanged(ListSelectionEvent e) {
  223.   if (!e.getValueIsAdjusting()) {
  224.     ListSelectionModel lm = (ListSelectionModel) e.getSource();
  225.     for (int i = e.getFirstIndex(); i <= e.getLastIndex(); i++) {
  226.       if (lm.isSelectedIndex(i)) {
  227. m_AttSummaryPanel.setAttribute(i);
  228. break;
  229.       }
  230.     }
  231.   }
  232. }
  233.     });
  234.     m_BaseInstPanel.setBorder(BorderFactory
  235.       .createTitledBorder("Base relation"));
  236.     m_WorkingInstPanel.setBorder(BorderFactory
  237.  .createTitledBorder("Working relation"));
  238.     m_AttPanel.setBorder(BorderFactory
  239.     .createTitledBorder("Attributes in base relation"));
  240.     m_Filters.setBorder(BorderFactory.createTitledBorder("Filters"));
  241.     m_AttSummaryPanel.setBorder(BorderFactory
  242.     .createTitledBorder("Attribute information for base relation"));
  243.     m_Filters.setValue(new UnsupervisedFilter [0]);
  244.     m_ReplaceBut.setEnabled(false);
  245.     m_ApplyBut.setEnabled(false);
  246.     m_SaveBut.setEnabled(false);
  247.     
  248.     // Set up the GUI layout
  249.     JPanel instInfo = new JPanel();
  250.     instInfo.setLayout(new GridLayout(1, 2));
  251.     instInfo.add(m_BaseInstPanel);
  252.     instInfo.add(m_WorkingInstPanel);
  253.     JPanel buttons = new JPanel();
  254.     buttons.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
  255.     buttons.setLayout(new GridLayout(1, 6, 5, 5));
  256.     buttons.add(m_OpenFileBut);
  257.     buttons.add(m_OpenURLBut);
  258.     buttons.add(m_OpenDBBut);
  259.     buttons.add(m_ApplyBut);
  260.     buttons.add(m_ReplaceBut);
  261.     buttons.add(m_SaveBut);
  262.     JPanel filterNAttInfo = new JPanel();
  263.     filterNAttInfo.setLayout(new GridLayout(2, 1));
  264.     filterNAttInfo.add(m_Filters);
  265.     filterNAttInfo.add(m_AttSummaryPanel);
  266.     JPanel filters = new JPanel();
  267.     filters.setLayout(new GridLayout(1, 2));
  268.     filters.add(m_AttPanel);
  269.     filters.add(filterNAttInfo);
  270.     JPanel p3 = new JPanel();
  271.     p3.setLayout(new BorderLayout());
  272.     p3.add(instInfo, BorderLayout.NORTH);
  273.     p3.add(filters, BorderLayout.CENTER);
  274.     
  275.     setLayout(new BorderLayout());
  276.     add(buttons, BorderLayout.NORTH);
  277.     add(p3, BorderLayout.CENTER);
  278.   }
  279.   /**
  280.    * gets a copy of the most recently applied filters.
  281.    * @return a serialized array of the most recently applied filters
  282.    */
  283.   protected synchronized SerializedObject getMostRecentFilters() {
  284.     return m_FiltersCopy;
  285.   }
  286.   /**
  287.    * Sets the Logger to receive informational messages
  288.    *
  289.    * @param newLog the Logger that will now get info messages
  290.    */
  291.   public void setLog(Logger newLog) {
  292.     m_Log = newLog;
  293.   }
  294.   
  295.   /**
  296.    * Tells the panel to use a new base set of instances.
  297.    *
  298.    * @param inst a set of Instances
  299.    */
  300.   public void setBaseInstances(Instances inst) {
  301.     m_BaseInstances = inst;
  302.     try {
  303.       Runnable r = new Runnable() {
  304. public void run() {
  305.   m_BaseInstPanel.setInstances(m_BaseInstances);
  306.   m_AttPanel.setInstances(m_BaseInstances);
  307.   m_AttSummaryPanel.setInstances(m_BaseInstances);
  308.   m_Log.logMessage("Base relation is now "
  309.    + m_BaseInstances.relationName()
  310.    + " (" + m_BaseInstances.numInstances()
  311.    + " instances)");
  312.   m_Log.statusMessage("OK");
  313.   // clear most recently applied filters
  314.   m_FiltersCopy = null;
  315.   setWorkingInstances(m_BaseInstances);
  316.   m_ApplyBut.setEnabled(true);
  317.   m_ReplaceBut.setEnabled(false);
  318.   m_SaveBut.setEnabled(false);
  319. }
  320.       };
  321.       if (SwingUtilities.isEventDispatchThread()) {
  322. r.run();
  323.       } else {
  324. SwingUtilities.invokeAndWait(r);
  325.       }
  326.     } catch (Exception ex) {
  327.       JOptionPane.showMessageDialog(this,
  328.     "Problem setting base instances:n"
  329.     + ex.getMessage(),
  330.     "Instances",
  331.     JOptionPane.ERROR_MESSAGE);
  332.     }
  333.   }
  334.   /**
  335.    * Tells the panel to use a new working set of instances.
  336.    *
  337.    * @param inst a set of Instances
  338.    */
  339.   public void setWorkingInstances(Instances inst) {
  340.     if (m_WorkingInstances != inst) {
  341.       m_WorkingInstances = inst;
  342.       m_WorkingInstPanel.setInstances(m_WorkingInstances);
  343.       m_Log.logMessage("Working relation is now "
  344.        + m_WorkingInstances.relationName()
  345.        + " (" + m_WorkingInstances.numInstances()
  346.        + " instances)");
  347.       m_Log.statusMessage("OK");
  348.       m_ReplaceBut.setEnabled(true);
  349.       m_SaveBut.setEnabled(true);
  350.       
  351.       // Fire a propertychange event
  352.       m_Support.firePropertyChange("", null, null);
  353.     }
  354.   }
  355.   /**
  356.    * Gets the working set of instances.
  357.    *
  358.    * @return the working instances
  359.    */
  360.   public Instances getWorkingInstances() {
  361.     return m_WorkingInstances;
  362.   }
  363.   
  364.   /**
  365.    * Adds a PropertyChangeListener who will be notified of value changes.
  366.    *
  367.    * @param l a value of type 'PropertyChangeListener'
  368.    */
  369.   public void addPropertyChangeListener(PropertyChangeListener l) {
  370.     m_Support.addPropertyChangeListener(l);
  371.   }
  372.   /**
  373.    * Removes a PropertyChangeListener.
  374.    *
  375.    * @param l a value of type 'PropertyChangeListener'
  376.    */
  377.   public void removePropertyChangeListener(PropertyChangeListener l) {
  378.     m_Support.removePropertyChangeListener(l);
  379.   }
  380.   /**
  381.    * Gets an array of all the filters that have been configured for use.
  382.    *
  383.    * @return an array containing all the filters
  384.    */
  385.   protected UnsupervisedFilter [] getFilters() {
  386.     UnsupervisedFilter [] extras = (UnsupervisedFilter [])m_Filters.getValue();
  387.     if (extras == null) {
  388.       extras = new UnsupervisedFilter [0];
  389.     }
  390.     weka.filters.unsupervised.attribute.Remove af = null;
  391.     try {
  392.       // Configure the attributeFilter from the current attribute panel
  393.       int [] selectedAttributes = m_AttPanel.getSelectedAttributes();
  394.       if (selectedAttributes.length < m_BaseInstances.numAttributes()) {
  395. af = new weka.filters.unsupervised.attribute.Remove();
  396. af.setInvertSelection(true);
  397. af.setAttributeIndicesArray(selectedAttributes);
  398.       }
  399.     } catch (Exception ex) {
  400.       ex.printStackTrace();
  401.       m_Log.logMessage(ex.getMessage());
  402.     }
  403.     if (af == null) {
  404.       return extras;
  405.     }
  406.     UnsupervisedFilter [] result = new UnsupervisedFilter[extras.length + 1];
  407.     result[0] = af;
  408.     System.arraycopy(extras, 0, result, 1, extras.length);
  409.     return result;
  410.   }
  411.   
  412.   /**
  413.    * Passes the supplied instances through all the filters that have
  414.    * been configured for use.
  415.    *
  416.    * @param instances the input instances
  417.    * @return the filtered instances
  418.    */
  419.   protected Instances filterInstances(Instances instances) {
  420.     UnsupervisedFilter [] filters = getFilters();
  421.     Instances temp = instances;
  422.     try {
  423.       if (m_Log instanceof TaskLogger) {
  424. ((TaskLogger)m_Log).taskStarted();
  425.       }
  426.       for (int i = 0; i < filters.length; i++) {
  427. m_Log.statusMessage("Passing through filter " + (i + 1) + ": "
  428.     + filters[i].getClass().getName());
  429. ((Filter)filters[i]).setInputFormat(temp);
  430. temp = Filter.useFilter(temp, (Filter) filters[i]);
  431.       }
  432.       if (m_Log instanceof TaskLogger) {
  433. ((TaskLogger)m_Log).taskFinished();
  434.       }
  435.       // try to save a copy of the filters using serialization
  436.       try {
  437. m_FiltersCopy = new SerializedObject(filters);
  438.       } catch (Exception ex) {
  439. JOptionPane.showMessageDialog(this,
  440.       "Could not create copy of filters",
  441.       null,
  442.       JOptionPane.ERROR_MESSAGE);
  443.       }
  444.       return temp;
  445.     } catch (Exception ex) {
  446.       // the the weka sleep
  447.       if (m_Log instanceof TaskLogger) {
  448. ((TaskLogger)m_Log).taskFinished();
  449.       }
  450.       // Pop up an error optionpane
  451.       JOptionPane.showMessageDialog(this,
  452.     "Problem filtering instances:n"
  453.     + ex.getMessage(),
  454.     "Instance Filter",
  455.     JOptionPane.ERROR_MESSAGE);
  456.       ex.printStackTrace();
  457.       m_Log.logMessage(ex.getMessage());
  458.       return null;
  459.     }
  460.   }
  461.   /**
  462.    * Applies the current filters and attribute selection settings and
  463.    * sets the result as the working dataset. This is done in the IO
  464.    * thread, and an error message is popped up if the IO thread is busy.
  465.    */
  466.   public void setWorkingInstancesFromFilters() {
  467.     if (m_IOThread == null) {
  468.       int res = 0;
  469.       if (m_AttPanel.getSelectedAttributes().length == 0) {
  470. Object[] options = { "OK", "CANCEL" };
  471. res = JOptionPane.showOptionDialog(null, 
  472.      "Unselecting all attributes will result "
  473.      +"in an empty dataset.nDo you want to "
  474.      +"continue?", "Warning", 
  475.      JOptionPane.DEFAULT_OPTION, 
  476.      JOptionPane.WARNING_MESSAGE,
  477.      null, options, options[1]);
  478.       }
  479.       if (res == 0) {
  480. m_IOThread = new Thread() {
  481.     public void run() {
  482.       Instances f = filterInstances(m_BaseInstances);
  483.       if (f != null) {
  484. if ((f == m_BaseInstances) && (f == m_WorkingInstances)) {
  485.   m_Log.logMessage("No changes from base relation");
  486. } else {
  487.   setWorkingInstances(f);
  488. }
  489.       }
  490.       m_IOThread = null;
  491.     }
  492.   };
  493. m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
  494. m_IOThread.start();
  495.       }
  496.     } else {
  497.       JOptionPane.showMessageDialog(this,
  498.     "Can't apply filters at this time,n"
  499.     + "currently busy with other IO",
  500.     "Apply filters",
  501.     JOptionPane.WARNING_MESSAGE);
  502.     }
  503.   }
  504.   /**
  505.    * Queries the user for a file to save instances as, then saves the
  506.    * instances in a background process. This is done in the IO
  507.    * thread, and an error message is popped up if the IO thread is busy.
  508.    */
  509.   public void saveWorkingInstancesToFileQ() {
  510.     
  511.     if (m_IOThread == null) {
  512.       int returnVal = m_FileChooser.showSaveDialog(this);
  513.       if (returnVal == JFileChooser.APPROVE_OPTION) {
  514. File sFile = m_FileChooser.getSelectedFile();
  515. if (!sFile.getName().toLowerCase().endsWith(Instances.FILE_EXTENSION)) {
  516.   sFile = new File(sFile.getParent(), sFile.getName() 
  517.                            + Instances.FILE_EXTENSION);
  518. }
  519. File selected = sFile;
  520. saveInstancesToFile(selected, m_WorkingInstances);
  521.       }
  522.     } else {
  523.       JOptionPane.showMessageDialog(this,
  524.     "Can't save at this time,n"
  525.     + "currently busy with other IO",
  526.     "Save Instances",
  527.     JOptionPane.WARNING_MESSAGE);
  528.     }
  529.   }
  530.   
  531.   /**
  532.    * Queries the user for a file to load instances from, then loads the
  533.    * instances in a background process. This is done in the IO
  534.    * thread, and an error message is popped up if the IO thread is busy.
  535.    */
  536.   public void setBaseInstancesFromFileQ() {
  537.     
  538.     if (m_IOThread == null) {
  539.       int returnVal = m_FileChooser.showOpenDialog(this);
  540.       if (returnVal == JFileChooser.APPROVE_OPTION) {
  541. File selected = m_FileChooser.getSelectedFile();
  542. setBaseInstancesFromFile(selected);
  543.       }
  544.     } else {
  545.       JOptionPane.showMessageDialog(this,
  546.     "Can't load at this time,n"
  547.     + "currently busy with other IO",
  548.     "Load Instances",
  549.     JOptionPane.WARNING_MESSAGE);
  550.     }
  551.   }
  552.   /**
  553.    * Queries the user for a URL to a database to load instances from, 
  554.    * then loads the instances in a background process. This is done in the IO
  555.    * thread, and an error message is popped up if the IO thread is busy.
  556.    */
  557.   public void setBaseInstancesFromDBQ() {
  558.     if (m_IOThread == null) {
  559.       try {
  560. InstanceQuery InstQ = 
  561.   (InstanceQuery)m_DatabaseQueryEditor.getValue();
  562. InstQ.connectToDatabase();      
  563. setBaseInstancesFromDB(InstQ);
  564.       } catch (Exception ex) {
  565. JOptionPane.showMessageDialog(this,
  566.       "Problem connecting to database:n"
  567.       + ex.getMessage(),
  568.       "Load Instances",
  569.       JOptionPane.ERROR_MESSAGE);
  570.       }
  571.       
  572.     } else {
  573.       JOptionPane.showMessageDialog(this,
  574.      "Can't load at this time,n"
  575.     + "currently busy with other IO",
  576.     "Load Instances",
  577.     JOptionPane.WARNING_MESSAGE);
  578.     }
  579.   }
  580.     
  581.   /**
  582.    * Queries the user for a URL to load instances from, then loads the
  583.    * instances in a background process. This is done in the IO
  584.    * thread, and an error message is popped up if the IO thread is busy.
  585.    */
  586.   public void setBaseInstancesFromURLQ() {
  587.     
  588.     if (m_IOThread == null) {
  589.       try {
  590. String urlName = (String) JOptionPane.showInputDialog(this,
  591. "Enter the source URL",
  592. "Load Instances",
  593. JOptionPane.QUESTION_MESSAGE,
  594. null,
  595. null,
  596. m_LastURL);
  597. if (urlName != null) {
  598.   m_LastURL = urlName;
  599.   URL url = new URL(urlName);
  600.   setBaseInstancesFromURL(url);
  601. }
  602.       } catch (Exception ex) {
  603. JOptionPane.showMessageDialog(this,
  604.       "Problem with URL:n"
  605.       + ex.getMessage(),
  606.       "Load Instances",
  607.       JOptionPane.ERROR_MESSAGE);
  608.       }
  609.     } else {
  610.       JOptionPane.showMessageDialog(this,
  611.     "Can't load at this time,n"
  612.     + "currently busy with other IO",
  613.     "Load Instances",
  614.     JOptionPane.WARNING_MESSAGE);
  615.     }
  616.   }
  617.   
  618.   
  619.   /**
  620.    * Saves the filtered instances to the supplied file.
  621.    *
  622.    * @param f a value of type 'File'
  623.    * @param inst the instances to save
  624.    */
  625.   protected void saveInstancesToFile(final File f, final Instances inst) {
  626.       
  627.     if (m_IOThread == null) {
  628.       m_IOThread = new Thread() {
  629. public void run() {
  630.   try {
  631.     m_Log.statusMessage("Saving to file...");
  632.     Writer w = new BufferedWriter(new FileWriter(f));
  633.     Instances h = new Instances(inst, 0);
  634.     w.write(h.toString());
  635.     w.write("n");
  636.     for (int i = 0; i < inst.numInstances(); i++) {
  637.       w.write(inst.instance(i).toString());
  638.       w.write("n");
  639.     }
  640.     w.close();
  641.     m_Log.statusMessage("OK");
  642.   } catch (Exception ex) {
  643.     ex.printStackTrace();
  644.     m_Log.logMessage(ex.getMessage());
  645.   }
  646.   m_IOThread = null;
  647. }
  648.       };
  649.       m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
  650.       m_IOThread.start();
  651.     } else {
  652.       JOptionPane.showMessageDialog(this,
  653.     "Can't save at this time,n"
  654.     + "currently busy with other IO",
  655.     "Save Instances",
  656.     JOptionPane.WARNING_MESSAGE);
  657.     }
  658.   }
  659.   /**
  660.    * Pops up generic object editor with list of conversion filters
  661.    *
  662.    * @param f the File
  663.    */
  664.   private void converterQuery(final File f) {
  665.     final GenericObjectEditor convEd = new GenericObjectEditor();
  666.     try {
  667.       convEd.setClassType(weka.core.converters.Loader.class);
  668.       convEd.setValue(new weka.core.converters.CSVLoader());
  669.       ((GenericObjectEditor.GOEPanel)convEd.getCustomEditor())
  670. .addOkListener(new ActionListener() {
  671.     public void actionPerformed(ActionEvent e) {
  672.       tryConverter((Loader)convEd.getValue(), f);
  673.     }
  674.   });
  675.     } catch (Exception ex) {
  676.     }
  677.     PropertyDialog pd = new PropertyDialog(convEd, 100, 100);
  678.   }
  679.   /**
  680.    * Applies the selected converter
  681.    *
  682.    * @param cnv the converter to apply to the input file
  683.    * @param f the input file
  684.    */
  685.   private void tryConverter(final Loader cnv, final File f) {
  686.     if (m_IOThread == null) {
  687.       m_IOThread = new Thread() {
  688.   public void run() {
  689.     try {
  690.       cnv.setSource(f);
  691.       Instances inst = cnv.getDataSet();
  692.       setBaseInstances(inst);
  693.     } catch (Exception ex) {
  694.       m_Log.statusMessage(cnv.getClass().getName()+" failed to load "
  695.  +f.getName());
  696.       m_IOThread = null;
  697.       converterQuery(f);
  698.     }
  699.     m_IOThread = null;
  700.   }
  701. };
  702.       m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
  703.       m_IOThread.start();
  704.     }
  705.   }
  706.   /**
  707.    * Loads results from a set of instances contained in the supplied
  708.    * file. This is started in the IO thread, and a dialog is popped up
  709.    * if there's a problem.
  710.    *
  711.    * @param f a value of type 'File'
  712.    */
  713.   public void setBaseInstancesFromFile(final File f) {
  714.       
  715.     if (m_IOThread == null) {
  716.       m_IOThread = new Thread() {
  717. public void run() {
  718.   try {
  719.     m_Log.statusMessage("Reading from file...");
  720.     Reader r = new BufferedReader(new FileReader(f));
  721.     setBaseInstances(new Instances(r));
  722.     r.close();
  723.   } catch (Exception ex) {
  724.     m_Log.statusMessage("Problem reading " + f.getName() 
  725. + " as an arff file.");
  726.     JOptionPane.showMessageDialog(PreprocessPanel.this,
  727.   "Couldn't read '"
  728.   + f.getName() + "' as an arff file.n"
  729.   + "Reason:n" + ex.getMessage(),
  730.   "Load Instances",
  731.   JOptionPane.ERROR_MESSAGE); 
  732.     m_IOThread = null;
  733.     converterQuery(f);
  734.   }
  735.   m_IOThread = null;
  736. }
  737.       };
  738.       m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
  739.       m_IOThread.start();
  740.     } else {
  741.       JOptionPane.showMessageDialog(this,
  742.     "Can't load at this time,n"
  743.     + "currently busy with other IO",
  744.     "Load Instances",
  745.     JOptionPane.WARNING_MESSAGE);
  746.     }
  747.   }
  748.   
  749.   /**
  750.    * Loads instances from a database
  751.    *
  752.    * @param iq the InstanceQuery object to load from (this is assumed
  753.    * to have been already connected to a valid database).
  754.    */
  755.   public void setBaseInstancesFromDB(final InstanceQuery iq) {
  756.     if (m_IOThread == null) {
  757.       m_IOThread = new Thread() {
  758. public void run() {
  759.   
  760.   try {
  761.     m_Log.statusMessage("Reading from database...");
  762.     final Instances i = iq.retrieveInstances();
  763.     SwingUtilities.invokeAndWait(new Runnable() {
  764.       public void run() {
  765. setBaseInstances(new Instances(i));
  766.       }
  767.     });
  768.     iq.disconnectFromDatabase();
  769.   } catch (Exception ex) {
  770.     m_Log.statusMessage("Probelm executing DB query "+m_SQLQ);
  771.     JOptionPane.showMessageDialog(PreprocessPanel.this,
  772.   "Couldn't read from database:n"
  773.   + ex.getMessage(),
  774.   "Load Instances",
  775.   JOptionPane.ERROR_MESSAGE);
  776.   }
  777.    m_IOThread = null;
  778. }
  779.       };
  780.       m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
  781.       m_IOThread.start();
  782.     } else {
  783.        JOptionPane.showMessageDialog(this,
  784.     "Can't load at this time,n"
  785.     + "currently busy with other IO",
  786.     "Load Instances",
  787.     JOptionPane.WARNING_MESSAGE);
  788.     }
  789.   }
  790.   /**
  791.    * Loads instances from a URL.
  792.    *
  793.    * @param u the URL to load from.
  794.    */
  795.   public void setBaseInstancesFromURL(final URL u) {
  796.     if (m_IOThread == null) {
  797.       m_IOThread = new Thread() {
  798. public void run() {
  799.   try {
  800.     m_Log.statusMessage("Reading from URL...");
  801.     Reader r = new BufferedReader(
  802.        new InputStreamReader(u.openStream()));
  803.     setBaseInstances(new Instances(r));
  804.     r.close();
  805.   } catch (Exception ex) {
  806.     m_Log.statusMessage("Problem reading " + u);
  807.     JOptionPane.showMessageDialog(PreprocessPanel.this,
  808.   "Couldn't read from URL:n"
  809.   + u + "n"
  810.   + ex.getMessage(),
  811.   "Load Instances",
  812.   JOptionPane.ERROR_MESSAGE);
  813.   }
  814.   m_IOThread = null;
  815. }
  816.       };
  817.       m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
  818.       m_IOThread.start();
  819.     } else {
  820.       JOptionPane.showMessageDialog(this,
  821.     "Can't load at this time,n"
  822.     + "currently busy with other IO",
  823.     "Load Instances",
  824.     JOptionPane.WARNING_MESSAGE);
  825.     }
  826.   }
  827.   
  828.   /**
  829.    * Tests out the instance-preprocessing panel from the command line.
  830.    *
  831.    * @param args ignored
  832.    */
  833.   public static void main(String [] args) {
  834.     try {
  835.       final JFrame jf = new JFrame("Weka Knowledge Explorer: Preprocess");
  836.       jf.getContentPane().setLayout(new BorderLayout());
  837.       final PreprocessPanel sp = new PreprocessPanel();
  838.       jf.getContentPane().add(sp, BorderLayout.CENTER);
  839.       weka.gui.LogPanel lp = new weka.gui.LogPanel();
  840.       sp.setLog(lp);
  841.       jf.getContentPane().add(lp, BorderLayout.SOUTH);
  842.       jf.addWindowListener(new WindowAdapter() {
  843. public void windowClosing(WindowEvent e) {
  844.   jf.dispose();
  845.   System.exit(0);
  846. }
  847.       });
  848.       jf.pack();
  849.       jf.setSize(800, 600);
  850.       jf.setVisible(true);
  851.     } catch (Exception ex) {
  852.       ex.printStackTrace();
  853.       System.err.println(ex.getMessage());
  854.     }
  855.   }
  856. }