/***********************************************************************
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;
}
}