/* * 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. */ /* * DefaultModelsPanel.java * Copyright (C) 2006 Robert Jung * */ package weka.gui.ensembleLibraryEditor; import weka.classifiers.Classifier; import weka.classifiers.EnsembleLibraryModel; import weka.classifiers.meta.ensembleSelection.EnsembleSelectionLibrary; import weka.core.Utils; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.InputStream; import java.util.Iterator; import java.util.Properties; import java.util.Vector; import java.util.regex.Pattern; /** * This class is intended to build a panel that contains as interface * that will let users choose default lists of models to add to the * library. There will be default a list of models provided by the * EnsembleLibrary class. In addition, the user will be able to prune * the list of defaults to remove models that have either high training * times, high testing times, or high file sizes on disk. Finally, users * will be able to also prune the size of the current working default set * to a specific number of models with a slider bar. * * @author Robert Jung (mrbobjung@gmail.com) * @version $Revision: 5928 $ */ public class DefaultModelsPanel extends JPanel implements ActionListener, ChangeListener { /** for serialization */ private static final long serialVersionUID = -6123488873592563339L; /** the name of the property file */ public static final String PROPERTY_FILE = "DefaultModels.props"; /** Contains the editor properties */ protected static Properties DEFAULT_PROPERTIES; /** options to exclude */ public String EXCLUDE_OPTIONS[] = { "Train Time", "Test Time", "File Size" }; /** an array of libray files to be used in populating * the default list comboBox*/ private String[] m_DefaultFileNames; /** an array of model Strings that should be excluded * if the file size option is selected*/ private String[] m_LargeFileSizeModels; /** an array of model Strings that should be excluded * if the train time option is selected*/ private String[] m_LargeTrainTimeModels; /** an array of model Strings that should be excluded * if the test time option is selected*/ private String[] m_LargeTestTimeModels; /** this is a combo box that will allow the user to select * which set of models to remove from the list */ private JComboBox m_ExcludeModelsComboBox; /** this is a button that will allow the user to select * which set of models to remove from the list */ private JButton m_ExcludeModelsButton; /** this is a combo box that will allow the user to select * the default model file */ private JComboBox m_DefaultFilesComboBox; /** allows the user to reload the default set */ private JButton m_RefreshButton; /** * This object will store all of the models that can be selected * from the default list. The ModelList class is * a custom class in weka.gui that knows how to display library * model objects in a JList */ private ModelList m_ModelList; /** This button allows the user to remove all the models currently * selected in the model List from those that will be added*/ private JButton m_RemoveSelectedButton; /** This button allows the user to add all the in the current * working default set to the library */ private JButton m_AddAllButton; /** This button allows the user to add all the models currently * selected to the current set of models in this library, after * this is selected it should also send the user back to the * main interface*/ private JButton m_AddSelectedButton; /** * This is a reference to the main gui object that is responsible * for displaying the model library. This panel will add models * to the main panel through methods in this object. */ private ListModelsPanel m_ListModelsPanel; /** whether an update is pending */ private boolean m_ListUpdatePending = false; /** * Loads the configuration property file */ static { try { System.out.println("package name: " + getPackageName()); DEFAULT_PROPERTIES = Utils.readProperties(getPackageName() + PROPERTY_FILE); java.util.Enumeration keys = (java.util.Enumeration) DEFAULT_PROPERTIES .propertyNames(); if (!keys.hasMoreElements()) { throw new Exception("Failed to read a property file for the " + "generic object editor"); } } catch (Exception ex) { JOptionPane.showMessageDialog(null, "Could not read a configuration file for the default models\n" + "panel.\n", "DefaultProperties", JOptionPane.ERROR_MESSAGE); } } /** * Constructor to initialize the GUI * * @param listModelsPanel the panel to use */ public DefaultModelsPanel(ListModelsPanel listModelsPanel) { m_ListModelsPanel = listModelsPanel; readProperties(); createDefaultModelsPanel(); } /** * This grabs the relevant properties from the Default model * properties file. * */ private void readProperties() { m_DefaultFileNames = DEFAULT_PROPERTIES.getProperty("files").split(", "); m_LargeTrainTimeModels = DEFAULT_PROPERTIES.getProperty("train_time").split(", "); m_LargeTestTimeModels = DEFAULT_PROPERTIES.getProperty("test_time").split(", "); m_LargeFileSizeModels = DEFAULT_PROPERTIES.getProperty("file_size").split(", "); } /** * Initializes the GUI * */ private void createDefaultModelsPanel() { setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); JLabel defaultFileLabel = new JLabel("Select default set: "); gbc.weightx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 1; gbc.anchor = GridBagConstraints.WEST; add(defaultFileLabel, gbc); m_DefaultFilesComboBox = new JComboBox(m_DefaultFileNames); m_DefaultFilesComboBox.setSelectedItem(m_DefaultFileNames[0]); m_DefaultFilesComboBox.addActionListener(this); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 1; gbc.gridy = 0; gbc.gridwidth = 1; gbc.anchor = GridBagConstraints.WEST; add(m_DefaultFilesComboBox, gbc); m_RefreshButton = new JButton("Reload set"); m_RefreshButton.addActionListener(this); gbc.weightx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 2; gbc.gridy = 0; gbc.gridwidth = 1; gbc.anchor = GridBagConstraints.WEST; add(m_RefreshButton, gbc); JLabel excludeModelsLabel = new JLabel("Exclude models w/ large"); gbc.weightx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 1; gbc.anchor = GridBagConstraints.WEST; add(excludeModelsLabel, gbc); m_ExcludeModelsComboBox = new JComboBox(EXCLUDE_OPTIONS); m_ExcludeModelsComboBox.setSelectedItem(EXCLUDE_OPTIONS[0]); //m_ExcludeModelsComboBox.addActionListener(this); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 1; gbc.gridy = 1; gbc.gridwidth = 1; gbc.anchor = GridBagConstraints.WEST; add(m_ExcludeModelsComboBox, gbc); m_ExcludeModelsButton = new JButton("Exclude"); m_ExcludeModelsButton.setToolTipText( "Exclude this type of models from the current working list"); m_ExcludeModelsButton.addActionListener(this); gbc.weightx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 2; gbc.gridy = 1; gbc.gridwidth = 1; gbc.anchor = GridBagConstraints.WEST; add(m_ExcludeModelsButton, gbc); JPanel modelListPanel = new JPanel(); modelListPanel.setBorder(BorderFactory .createTitledBorder("Working set of Default Library Models")); m_ModelList = new ModelList(); m_ModelList.getInputMap().put( KeyStroke.getKeyStroke("released DELETE"), "deleteSelected"); m_ModelList.getActionMap().put("deleteSelected", new AbstractAction("deleteSelected") { private static final long serialVersionUID = 4601977182190493654L; public void actionPerformed(ActionEvent evt) { Object[] currentModels = m_ModelList.getSelectedValues(); ModelList.SortedListModel dataModel = ((ModelList.SortedListModel) m_ModelList.getModel()); for (int i = 0; i < currentModels.length; i++) { dataModel.removeElement((EnsembleLibraryModel) currentModels[i]); } //Shrink the selected range to the first index that was selected int selected[] = new int[1]; selected[0] = m_ModelList.getSelectedIndices()[0]; m_ModelList.setSelectedIndices(selected); } }); m_ModelList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); m_ModelList.setLayoutOrientation(JList.VERTICAL); //m_ModelList.setVisibleRowCount(12); ToolTipManager.sharedInstance().registerComponent(m_ModelList); JScrollPane listView = new JScrollPane(m_ModelList); listView .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); listView.setPreferredSize(new Dimension(150, 50)); modelListPanel.setLayout(new BorderLayout()); modelListPanel.add(listView, BorderLayout.CENTER); gbc.weightx = 1; gbc.weighty = 1; gbc.fill = GridBagConstraints.BOTH; gbc.gridx = 0; gbc.gridy = 2; gbc.gridwidth = 3; gbc.anchor = GridBagConstraints.WEST; add(modelListPanel, gbc); m_RemoveSelectedButton = new JButton("Remove Selected"); m_RemoveSelectedButton.addActionListener(this); m_RemoveSelectedButton.setToolTipText( "Remove the selected models from the current default set"); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weighty = 0; gbc.gridx = 0; gbc.gridy = 3; gbc.anchor = GridBagConstraints.WEST; gbc.weightx = 1; gbc.gridwidth = 1; add(m_RemoveSelectedButton, gbc); m_AddSelectedButton = new JButton("Add Selected"); m_AddSelectedButton.addActionListener(this); m_AddSelectedButton.setToolTipText("Add selected models in " + "above list to the library"); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 1; gbc.gridy = 3; gbc.anchor = GridBagConstraints.WEST; gbc.gridwidth = 1; gbc.weightx = 1; add(m_AddSelectedButton, gbc); m_AddAllButton = new JButton("Add All"); m_AddAllButton.addActionListener(this); m_AddAllButton.setToolTipText("Add all models in the above" + "list to the Libray"); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 2; gbc.gridy = 3; gbc.anchor = GridBagConstraints.WEST; gbc.gridwidth = 1; gbc.weightx = 1; add(m_AddAllButton, gbc); m_ListUpdatePending = true; } /** * This method is called in response to user actions prompting * us to reload the model list: when they select a new list, * or hit reload. * */ public void updateDefaultList() { ((ModelList.SortedListModel) m_ModelList.getModel()).clear(); String ensemblePackageString = getPackageName(); int index = m_DefaultFilesComboBox.getSelectedIndex(); Vector classifiers = null; LibrarySerialization serialization; try { serialization = new LibrarySerialization(); String defaultFileString = ensemblePackageString + m_DefaultFileNames[index].trim() + ".model.xml"; //System.out.println(defaultFileString); InputStream is = ClassLoader.getSystemResourceAsStream(defaultFileString); if (is == null) { File f = new File(defaultFileString); if (f.exists()) { System.out.println("file existed: " + f.getPath()); } else { System.out.println("file didn't exist: " + f.getPath()); } } classifiers = (Vector) serialization.read(ClassLoader.getSystemResourceAsStream(defaultFileString)); for (Iterator it = classifiers.iterator(); it.hasNext();) { EnsembleLibraryModel model = m_ListModelsPanel.getLibrary().createModel((Classifier) it.next()); model.testOptions(); ((ModelList.SortedListModel) m_ModelList.getModel()).add(model); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Deals with user input to the various buttons in this GUI * * @param e the event */ public void actionPerformed(ActionEvent e) { ModelList.SortedListModel dataModel = ((ModelList.SortedListModel) m_ModelList .getModel()); if (e.getSource() == m_RefreshButton) { updateDefaultList(); } else if (e.getSource() == m_DefaultFilesComboBox) { updateDefaultList(); } else if (e.getSource() == m_RemoveSelectedButton) { //here we simply get the list of models that are //currently selected and ten remove them from the list Object[] currentModels = m_ModelList.getSelectedValues(); for (int i = 0; i < currentModels.length; i++) { dataModel.removeElement(currentModels[i]); } //Shrink the selected range to the first index that was selected if (m_ModelList.getSelectedIndices().length > 0) { int selected[] = new int[1]; selected[0] = m_ModelList.getSelectedIndices()[0]; m_ModelList.setSelectedIndices(selected); } } else if (e.getSource() == m_AddAllButton) { //here we just need to add all of the models to the //ListModelsPanel object Iterator it = dataModel.iterator(); while (it.hasNext()) { EnsembleLibraryModel currentModel = (EnsembleLibraryModel) it.next(); m_ListModelsPanel.addModel(currentModel); } dataModel.clear(); } else if (e.getSource() == m_AddSelectedButton) { //here we simply get the list of models that are //currently selected and ten remove them from the list Object[] currentModels = m_ModelList.getSelectedValues(); for (int i = 0; i < currentModels.length; i++) { m_ListModelsPanel.addModel((EnsembleLibraryModel) currentModels[i]); dataModel.removeElement(currentModels[i]); } } else if (e.getSource() == m_ExcludeModelsButton) { if (m_ExcludeModelsComboBox.getSelectedIndex() == 0) { applyTrainTimeFilters(); } else if (m_ExcludeModelsComboBox.getSelectedIndex() == 1) { applyTestTimeFilters(); } else if (m_ExcludeModelsComboBox.getSelectedIndex() == 2) { applyFileSizeFilters(); } } } /** * this listener event fires when the use switches back to this panel * it checks to se if the working directory has changed since they were * here last. If so then it updates the model list. * * @param e the event */ public void stateChanged(ChangeEvent e) { JTabbedPane pane = (JTabbedPane) e.getSource(); if (pane.getSelectedComponent().equals(this) && m_ListUpdatePending) { updateDefaultList(); m_ListUpdatePending = false; } } /** * Removes models from the list that fit the regular expressions * defining models that have large train times */ public void applyTrainTimeFilters() { //create an array of patterns and then pass them to the apply //filters method Pattern patterns[] = new Pattern[m_LargeTrainTimeModels.length]; for (int i = 0; i < m_LargeTrainTimeModels.length; i++) { patterns[i] = Pattern.compile(m_LargeTrainTimeModels[i]); } applyFilters(patterns); } /** * Removes models from the list that fit the regular expressions * defining models that have large test times */ public void applyTestTimeFilters() { //create an array of patterns and then pass them to the apply //filters method Pattern patterns[] = new Pattern[m_LargeTestTimeModels.length]; for (int i = 0; i < m_LargeTestTimeModels.length; i++) { patterns[i] = Pattern.compile(m_LargeTestTimeModels[i]); } applyFilters(patterns); } /** * Removes models from the list that fit the regular expressions * defining models that have large file sizes */ public void applyFileSizeFilters() { //create an array of patterns and then pass them to the apply //filters method Pattern patterns[] = new Pattern[m_LargeFileSizeModels.length]; for (int i = 0; i < m_LargeFileSizeModels.length; i++) { patterns[i] = Pattern.compile(m_LargeFileSizeModels[i]); } applyFilters(patterns); } /** * This is the code common to the previous three methods. It basically * takes a Java regexp pattern and applies it to the currently selected * list of models, removing those that match as it goes. * * @param patterns the regexp patterns */ public void applyFilters(Pattern[] patterns) { ModelList.SortedListModel dataModel = ((ModelList.SortedListModel) m_ModelList .getModel()); //this will track all of the models that we need to remove //from our list Vector toRemove = new Vector(); //here we simply get the list of models that are //currently selected and ten remove them from the list //if they match one of the patterns Iterator it = dataModel.iterator(); while (it.hasNext()) { EnsembleLibraryModel currentModel = (EnsembleLibraryModel) it.next(); for (int i = 0; i < patterns.length; i++) { if (patterns[i].matcher(currentModel.getStringRepresentation()).matches()) { toRemove.add(currentModel); break; } } } it = toRemove.iterator(); while (it.hasNext()) { dataModel.removeElement(it.next()); } } /** * this bit of code grabs all of the .model.xml files located in * the ensemble selection package directory. I decided to detect this * * directory in case we change the package name which I think we planned * on doing. * * @return the package name */ public static String getPackageName() { return EnsembleSelectionLibrary.class.toString() .replaceAll("class ", "") .replaceAll("EnsembleSelectionLibrary", "") .replaceAll("\\.", "/"); } }