/*********************************************************************** This file is part of KEEL-software, the Data Mining tool for regression, classification, clustering, pattern mining and so on. Copyright (C) 2004-2010 F. Herrera (herrera@decsai.ugr.es) L. S�nchez (luciano@uniovi.es) J. Alcal�-Fdez (jalcala@decsai.ugr.es) S. Garc�a (sglopez@ujaen.es) A. Fern�ndez (alberto.fernandez@ujaen.es) J. Luengo (julianlm@decsai.ugr.es) 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 http://www.gnu.org/licenses/ **********************************************************************/ /** * <p> * @author Written by Pedro Antonio Gutiérrez and Juan Carlos Fernández (University of Córdoba) 23/10/2008 * @version 1.0 * @since JDK1.5 * </p> */ package keel.GraphInterKeel.datacf.partitionData; import java.io.IOException; import keel.GraphInterKeel.datacf.util.FileBrowserPanel; import keel.GraphInterKeel.datacf.util.KeelFileFilter; import keel.GraphInterKeel.util.Path; import java.awt.Cursor; import java.io.File; import java.io.FileOutputStream; import java.util.Iterator; import java.util.List; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; public class PartitionPanel extends javax.swing.JPanel { /** * <p> * Panel for performing partitions of datasets * </p> */ /** * <p> * Constructor that initializes the panel * </p> */ public PartitionPanel() { initComponents(); } /** * <p> * This method is called from within the constructor to * initialize the form. * </p> * <p> * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. * </p> */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { fileBrowserPanel = new keel.GraphInterKeel.datacf.util.FileBrowserPanel(); KeelFileFilter fileFilter = new KeelFileFilter(); fileFilter.addExtension("dat"); fileFilter.setFilterName("KEEL Files (.dat)"); fileBrowserPanel.getFileChooser().setFileFilter(fileFilter); //chooser.showOpenDialog(this); typeofPartitionjPanel = new javax.swing.JPanel(); typejLabel = new javax.swing.JLabel(); typejComboBox = new javax.swing.JComboBox(); seedjLabel = new javax.swing.JLabel(); seedjTextField = new javax.swing.JTextField(); optionsjButton = new javax.swing.JButton(); dividejButton = new javax.swing.JButton(); waitingLabel = new javax.swing.JLabel(); setName("Form"); // NOI18N fileBrowserPanel.setName("fileBrowserPanel"); // NOI18N typeofPartitionjPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Type of Partition")); typeofPartitionjPanel.setName("typeofPartitionjPanel"); // NOI18N typejLabel.setText("Type of Partition"); typejLabel.setName("typejLabel"); // NOI18N typejComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "K-Fold Cross Validation", "5x2 Cross Validation", "K-Fold Distribution Optimally Balanced Stratified Cross Validation" })); typejComboBox.setToolTipText("Type of Partitioning Approach to Apply"); typejComboBox.setName("typejComboBox"); // NOI18N typejComboBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { typejComboBoxActionPerformed(evt); } }); seedjLabel.setText("Seed"); seedjLabel.setName("seedjLabel"); // NOI18N seedjTextField.setText("12345678"); seedjTextField.setToolTipText("Random Generator Seed for Performing the Partitions"); seedjTextField.setName("seedjTextField"); // NOI18N optionsjButton.setText("Options"); optionsjButton.setToolTipText("Options of the partitioning algorithm"); optionsjButton.setName("optionsjButton"); // NOI18N optionsjButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { optionsjButtonActionPerformed(evt); } }); dividejButton.setText("Divide"); dividejButton.setToolTipText("Make partitions of your selected dataset"); dividejButton.setName("dividejButton"); // NOI18N dividejButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { dividejButtonActionPerformed(evt); } }); waitingLabel.setBackground(new java.awt.Color(255, 153, 0)); waitingLabel.setFont(new java.awt.Font("Lucida Grande", 0, 24)); // NOI18N waitingLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); waitingLabel.setText("Creating dataset... Please, wait."); waitingLabel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); waitingLabel.setName("waitingLabel"); // NOI18N waitingLabel.setOpaque(true); waitingLabel.setVisible(false); javax.swing.GroupLayout typeofPartitionjPanelLayout = new javax.swing.GroupLayout(typeofPartitionjPanel); typeofPartitionjPanel.setLayout(typeofPartitionjPanelLayout); typeofPartitionjPanelLayout.setHorizontalGroup( typeofPartitionjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(typeofPartitionjPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(typeofPartitionjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(typeofPartitionjPanelLayout.createSequentialGroup() .addComponent(waitingLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addContainerGap()) .addGroup(typeofPartitionjPanelLayout.createSequentialGroup() .addGroup(typeofPartitionjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(seedjLabel) .addComponent(typejLabel)) .addGap(34, 34, 34) .addGroup(typeofPartitionjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(typejComboBox, 0, 1, Short.MAX_VALUE) .addComponent(seedjTextField)) .addGap(90, 90, 90) .addGroup(typeofPartitionjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(dividejButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(optionsjButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGap(28, 28, 28)))) ); typeofPartitionjPanelLayout.setVerticalGroup( typeofPartitionjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(typeofPartitionjPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(typeofPartitionjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(typejLabel) .addComponent(optionsjButton) .addComponent(typejComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(typeofPartitionjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(seedjLabel) .addComponent(seedjTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(dividejButton)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(waitingLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 57, Short.MAX_VALUE) .addContainerGap()) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(fileBrowserPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(typeofPartitionjPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(fileBrowserPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 342, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(typeofPartitionjPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) ); }// </editor-fold>//GEN-END:initComponents private void optionsjButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_optionsjButtonActionPerformed //If K-Fold Cross Validation is selected if (this.typejComboBox.getSelectedItem() == this.typejComboBox.getItemAt(0)) { kfoldOptions.setVisible(true); } //DOB-SCV else if (this.typejComboBox.getSelectedItem() == this.typejComboBox.getItemAt(2)) { kfoldOptions.setVisible(true); } //Hold-out //else if (this.typejComboBox.getSelectedItem() == this.typejComboBox.getItemAt(2)) { // holdOutOptions.setVisible(true); //} }//GEN-LAST:event_optionsjButtonActionPerformed private void typejComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_typejComboBoxActionPerformed if (this.typejComboBox.getSelectedItem() == this.typejComboBox.getItemAt(1)) { this.optionsjButton.setEnabled(false); } else { this.optionsjButton.setEnabled(true); //If K-Fold Cross Validation is selected } if (this.typejComboBox.getSelectedItem() == this.typejComboBox.getItemAt(0)) { kfoldOptions = new KFoldOptionsJDialog(parent, true); if (holdOutOptions != null) { holdOutOptions = null; } } // DOB-SCV else if (this.typejComboBox.getSelectedItem() == this.typejComboBox.getItemAt(2)) { kfoldOptions = new KFoldOptionsJDialog(parent, true); if (holdOutOptions != null) { holdOutOptions = null; } } //Hold-out //else if (this.typejComboBox.getSelectedItem() == this.typejComboBox.getItemAt(2)) { // holdOutOptions = new HoldOutOptionsJDialog(parent, true); // if (kfoldOptions != null) { // kfoldOptions = null; // } //} }//GEN-LAST:event_typejComboBoxActionPerformed private void dividejButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dividejButtonActionPerformed File originalFile = null; originalFile = fileBrowserPanel.getFileChooser().getSelectedFile(); if (originalFile == null) { JOptionPane.showMessageDialog(this, "You have to select a file", "Error", JOptionPane.ERROR_MESSAGE); return; } Path.setFilePath(fileBrowserPanel.getFileChooser().getCurrentDirectory()); int type = -1, nOfPartitions = 0, totalFractions = 0; if (((String) typejComboBox.getSelectedItem()).equals("K-Fold Cross Validation")) { type = 1; nOfPartitions = kfoldOptions.getK(); } else if (((String) typejComboBox.getSelectedItem()).equals("5x2 Cross Validation")) { type = 3; } else if (((String) typejComboBox.getSelectedItem()).equals("Hold-Out")) { type = 2; nOfPartitions = holdOutOptions.getNOfPartitions(); totalFractions = holdOutOptions.getTotalFractions(); } //DOB-SCV else if (((String) typejComboBox.getSelectedItem()).equals("K-Fold Distribution Optimally Balanced Stratified Cross Validation")) { type = 4; nOfPartitions = kfoldOptions.getK(); } else { return; } long seed; try { seed = Long.parseLong((String) seedjTextField.getText()); } catch (Exception ex) { JOptionPane.showMessageDialog(this, "Insert a correct seed, please", "Error", 2); return; } File posibleExperimentFile = new File("." + File.separator + "data" + File.separator + originalFile.getName().replaceAll(".dat", "") + File.separator + originalFile.getName()); boolean experimentDataset = false; try { if (posibleExperimentFile != null && posibleExperimentFile.exists() && originalFile.getCanonicalPath().equals(posibleExperimentFile.getCanonicalPath())) { experimentDataset = true; } } catch (IOException ex) { } String outputPath = null; if (!experimentDataset) { JFileChooser chooser = new JFileChooser(); chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); chooser.setDialogTitle("Select a folder to save the files"); chooser.setCurrentDirectory(Path.getFilePath()); String name = originalFile.getName(); int index = name.indexOf("-"); if (index == -1) { index = name.lastIndexOf("."); } if (index == -1) { index = name.length(); } name = name.substring(0, index); String finalName = name.concat("-" + ((type == 1 || type == 4) ? (nOfPartitions + "Fold") : ((type == 2) ? "HoldOut" : "5x2"))); chooser.setSelectedFile(new File(Path.getFilePath() + File.separator + finalName)); int returnVal = chooser.showSaveDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { Path.setFilePath(chooser.getCurrentDirectory()); File directory = new File(chooser.getSelectedFile().getPath()); if (!directory.exists()) { if (!directory.mkdirs()) { JOptionPane.showMessageDialog(this, "Problem Creating Directory", "Error", JOptionPane.ERROR_MESSAGE); return; } } outputPath = directory.getPath(); } } else { JOptionPane.showMessageDialog(this, "This dataset is included in the experiment section\n The partitions will be generated in the corresponding folder", "Error", JOptionPane.INFORMATION_MESSAGE); outputPath = originalFile.getPath().substring(0, originalFile.getPath().lastIndexOf(File.separator)); } if (outputPath != null) { // --------------------- // K-fold partition type if (type == 1) { for (int i = 0; i < nOfPartitions; i++) { String nombre_base = originalFile.getName().replaceAll(".dat", ""); File trainingFile = new File(outputPath + File.separator + nombre_base + "-" + String.valueOf(nOfPartitions) + "-" + String.valueOf(i + 1) + "tra.dat"); System.out.println(trainingFile.getAbsolutePath()); File testFile = new File(outputPath + File.separator + nombre_base + "-" + String.valueOf(nOfPartitions) + "-" + String.valueOf(i + 1) + "tst.dat"); if (!wantToBeOverwritten(trainingFile) || !wantToBeOverwritten(testFile)) { return; } } } // --------------------- // DOB-SCV partition type else if (type == 4) { for (int i = 0; i < nOfPartitions; i++) { String nombre_base = originalFile.getName().replaceAll(".dat", ""); File trainingFile = new File(outputPath + File.separator + nombre_base + "-" + String.valueOf(nOfPartitions) + "dobscv-" + String.valueOf(i + 1) + "tra.dat"); System.out.println(trainingFile.getAbsolutePath()); File testFile = new File(outputPath + File.separator + nombre_base + "-" + String.valueOf(nOfPartitions) + "dobscv-" + String.valueOf(i + 1) + "tst.dat"); if (!wantToBeOverwritten(trainingFile) || !wantToBeOverwritten(testFile)) { return; } } } // ---------------------- // Holdout partition type else if (type == 2) { for (int i = 0; i < nOfPartitions; i++) { String nombre_base = originalFile.getName().replaceAll(".dat", ""); File trainingFile = new File(outputPath + File.separator + nombre_base + "-" + String.valueOf(totalFractions) + "-" + String.valueOf(i + 1) + "tra.dat"); File testFile = new File(outputPath + File.separator + nombre_base + "-" + String.valueOf(totalFractions) + "-" + String.valueOf(i + 1) + "tst.dat"); if (!wantToBeOverwritten(trainingFile) || !wantToBeOverwritten(testFile)) { return; } } } // ----------------------------- // 5x2 Dietterich partition type else { for (int i = 0; i < 5; i++) { String nombre_base = originalFile.getName().replaceAll(".dat", ""); File trainingFile = new File(outputPath + File.separator + nombre_base + "-5x2-" + String.valueOf(i + 1) + "tra.dat"); File testFile = new File(outputPath + File.separator + nombre_base + "-5x2-" + String.valueOf(i + 1) + "tst.dat"); if (!wantToBeOverwritten(trainingFile) || !wantToBeOverwritten(testFile)) { return; } } } // waiting... this.waitingLabel.setVisible(true); this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); JOptionPane.showMessageDialog(this, "Your partitions are going to be generated. This process may take a while. Press OK to continue creating your partitions.", "Generating partitions", JOptionPane.INFORMATION_MESSAGE); try { PartitionGenerator partitionGenerator = new PartitionGenerator(); partitionGenerator.partition(type, originalFile.getPath(), outputPath, seed, nOfPartitions, totalFractions); this.setCursor(Cursor.getDefaultCursor()); JOptionPane.showMessageDialog(this, "Your partitions have been correctly generated!!", "Partitions Generated!!", JOptionPane.INFORMATION_MESSAGE); } catch (Exception ex) { JOptionPane.showMessageDialog(this, "Problem Creating Partitions", "Error", JOptionPane.ERROR_MESSAGE); this.setCursor(Cursor.getDefaultCursor()); return; } // end waiting... this.waitingLabel.setVisible(false); // If the dataset is the main file of a dataset of the Experiment section if (experimentDataset) { /*Load the previuos datasets.xml*/ Document data = new Document(); try { SAXBuilder builder = new SAXBuilder(); data = builder.build("./data/Datasets.xml"); } catch (JDOMException ex) { JOptionPane.showMessageDialog(this, "Problem Reading ./data/Datasets.xml:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); return; } catch (Exception ex) { JOptionPane.showMessageDialog(this, "Problem Reading ./data/Datasets.xml:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); return; } String rootName = originalFile.getName().replaceAll(".dat", ""); Iterator it = data.getRootElement().getChildren().iterator(); while (it.hasNext()) { Element element = (Element) it.next(); if (element.getChild("nameAbr").getValue().equals(rootName)) { // Holdout if (type == 1) { List<Element> list = element.getChild("partitions").getChildren("partition"); boolean founded = false; for (Element e : list) { if (e.getText().equals(nOfPartitions + "cfv")) { founded = true; } } if (!founded) { Element partition = new Element("partition"); partition.setText(nOfPartitions + "cfv"); element.getChild("partitions").addContent(partition); } } else if (type == 2) { List<Element> list = element.getChild("partitions").getChildren("partition"); boolean founded = false; for (Element e : list) { if (e.getText().equals(totalFractions + "ho")) { founded = true; } } if (!founded) { Element partition = new Element("partition"); partition.setText(totalFractions + "ho"); element.getChild("partitions").addContent(partition); } } //DOBSCV else if (type == 4) { List<Element> list = element.getChild("partitions").getChildren("partition"); boolean founded = false; for (Element e : list) { if (e.getText().equals(nOfPartitions + "dobscv")) { founded = true; } } if (!founded) { Element partition = new Element("partition"); partition.setText(nOfPartitions + "dobscv"); element.getChild("partitions").addContent(partition); } } else { List<Element> list = element.getChild("partitions").getChildren("partition"); boolean founded = false; for (Element e : list) { if (e.getText().equals(nOfPartitions + "ho")) { founded = true; } } if (!founded) { Element partition = new Element("partition"); partition.setText("5x2cv"); element.getChild("partitions").addContent(partition); } } } } try { File f = new File("./data/Datasets.xml"); FileOutputStream file2 = new FileOutputStream(f); XMLOutputter fmt = new XMLOutputter(); fmt.setFormat(Format.getPrettyFormat()); fmt.output(data, file2); } catch (Exception ex) { ex.printStackTrace(); } } } }//GEN-LAST:event_dividejButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton dividejButton; private keel.GraphInterKeel.datacf.util.FileBrowserPanel fileBrowserPanel; private javax.swing.JButton optionsjButton; private javax.swing.JLabel seedjLabel; private javax.swing.JTextField seedjTextField; private javax.swing.JComboBox typejComboBox; private javax.swing.JLabel typejLabel; private javax.swing.JPanel typeofPartitionjPanel; private javax.swing.JLabel waitingLabel; // End of variables declaration//GEN-END:variables /** Parent frame */ protected JFrame parent = null; /** An option dialog for obtaining the options of the holdout partition proccess */ protected HoldOutOptionsJDialog holdOutOptions = null; /** An option dialog for obtaining the options of the k-fold partition proccess */ protected KFoldOptionsJDialog kfoldOptions = new KFoldOptionsJDialog(parent, true); /** * <p> * Gets the file browser from this partition panel * </p> * @return FileBrowserPanel of this partition panel */ public FileBrowserPanel getFileBrowserPanel() { return fileBrowserPanel; } /** * <p> * Sets the filebrowser of this partition panel * </p> * @param fileBrowserPanel New FileBrowserPanel for this partition panel */ public void setFileBrowserPanel(FileBrowserPanel fileBrowserPanel) { this.fileBrowserPanel = fileBrowserPanel; } /** * <p> * Sets the JFrame parent * </p> * @param parent JFrame parent */ public void setParent(JFrame parent) { this.parent = parent; } /** * <p> * Shows an Option Dialog for confirming if a file should be overwritten * (if the file exists) * </p> * @param file File object to check if it should be overwritten * @return boolean This value indicates if the file should be overwritten */ private boolean wantToBeOverwritten(File file) { // Check if the file exists if (file.exists()) { // Do you want to overwrite the file? Object[] options = {"Yes", "No" }; int n = JOptionPane.showOptionDialog(parent, "File \"" + file.getName() + "\" exists.\nDo you want to overwrite it?", "File exists", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[1]); if (n == 1) { return false; } } return true; } }