sirius.clustering.main.TrainClustererPane.java Source code

Java tutorial

Introduction

Here is the source code for sirius.clustering.main.TrainClustererPane.java

Source

/*==========================================================================
 SiriusPSB - A Generic System for Analysis of Biological Sequences
       http://compbio.ddns.comp.nus.edu.sg/~sirius/index.php
============================================================================
 Copyright (C) 2007 by Chuan Hock Koh
       
 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/>.
==========================================================================*/package sirius.clustering.main;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.ObjectOutputStream;

import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.filechooser.FileNameExtensionFilter;

import sirius.trainer.main.SiriusSettings;

import weka.clusterers.ClusterEvaluation;
import weka.clusterers.Clusterer;
import weka.core.Attribute;
import weka.core.Instances;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.Remove;
import weka.gui.GenericObjectEditor;
import weka.gui.PropertyPanel;

public class TrainClustererPane extends JComponent implements ActionListener {
    static final long serialVersionUID = sirius.Sirius.version;

    private JTextField numberOfClusterTextField;

    /** Lets the user configure the clusterer*/
    private GenericObjectEditor m_ClustererEditor = new GenericObjectEditor();
    /** The panel showing the current classifier one selection */
    private PropertyPanel m_CEPanel = new PropertyPanel(m_ClustererEditor);

    private JButton fileButton;
    private JTextField fileTextField;
    private JFrame parent;
    private JButton startButton = new JButton("Start");
    private JButton stopButton;
    private JLabel statusLabel;
    private Thread clusterThread;
    private Clusterer clusterer;

    private JButton saveClustererButton;

    private JTextArea outputTextArea;
    private JScrollPane outputScrollPane;

    private JComboBox m_ClassCombo = new JComboBox();

    public TrainClustererPane(JFrame mainFrame) {
        this.parent = mainFrame;

        m_ClustererEditor.setClassType(Clusterer.class);

        JPanel filePanel = new JPanel(new BorderLayout());
        filePanel.setBorder(
                BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Choose Training File"),
                        BorderFactory.createEmptyBorder(0, 5, 5, 5)));
        this.fileButton = new JButton("Choose");
        this.fileButton.addActionListener(this);
        this.fileTextField = new JTextField();
        this.fileTextField.setFocusable(false);
        filePanel.add(this.fileButton, BorderLayout.WEST);
        filePanel.add(this.fileTextField, BorderLayout.CENTER);

        JPanel clusteringMethodPanel = new JPanel(new GridLayout(1, 1, 5, 5));
        clusteringMethodPanel.setBorder(
                BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Choose a Clustering Method"),
                        BorderFactory.createEmptyBorder(0, 5, 5, 5)));
        clusteringMethodPanel.add(m_CEPanel);

        JPanel northPanel = new JPanel(new BorderLayout());
        northPanel.add(filePanel, BorderLayout.NORTH);
        northPanel.add(clusteringMethodPanel, BorderLayout.CENTER);

        JPanel outputPanel = new JPanel(new GridLayout(1, 1));
        outputPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Output"),
                BorderFactory.createEmptyBorder(0, 5, 5, 5)));
        this.outputTextArea = new JTextArea();
        this.outputTextArea.setFocusable(false);
        outputScrollPane = new JScrollPane(this.outputTextArea);
        outputPanel.add(outputScrollPane);

        JPanel startStopButtonsPanel = new JPanel(new GridLayout(1, 2, 5, 5));
        this.startButton.addActionListener(this);
        this.stopButton = new JButton("Stop");
        this.stopButton.addActionListener(this);
        this.stopButton.setEnabled(false);
        startStopButtonsPanel.add(this.startButton);
        startStopButtonsPanel.add(this.stopButton);

        JPanel buttonsPanel = new JPanel(new GridLayout(2, 1, 5, 5));
        buttonsPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Controls"),
                BorderFactory.createEmptyBorder(0, 5, 5, 5)));
        buttonsPanel.add(startStopButtonsPanel);
        this.saveClustererButton = new JButton("Save Clusterer");
        this.saveClustererButton.addActionListener(this);
        buttonsPanel.add(this.saveClustererButton);

        JPanel numberOfClusterPanel = new JPanel(new GridLayout(1, 2, 5, 5));
        numberOfClusterTextField = new JTextField();
        this.numberOfClusterTextField.setEnabled(false);
        JLabel numberOfClusterLabel = new JLabel("Number of Clusters: ");
        numberOfClusterPanel.add(numberOfClusterLabel);
        numberOfClusterPanel.add(this.numberOfClusterTextField);

        JPanel southPanel = new JPanel(new GridLayout(1, 1));
        southPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Status"),
                BorderFactory.createEmptyBorder(0, 5, 5, 5)));
        this.statusLabel = new JLabel(" ");
        southPanel.add(this.statusLabel);

        JPanel classIndexPanel = new JPanel(new BorderLayout());
        classIndexPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Settings"),
                BorderFactory.createEmptyBorder(0, 5, 5, 5)));
        JLabel classIndexLabel = new JLabel("Class: ");
        JPanel extraPanel = new JPanel(new BorderLayout());
        extraPanel.add(classIndexLabel, BorderLayout.WEST);
        extraPanel.add(this.m_ClassCombo, BorderLayout.CENTER);
        classIndexPanel.add(extraPanel, BorderLayout.NORTH);

        JPanel emptyPanel1 = new JPanel();
        JPanel emptyPanel2 = new JPanel();

        JPanel centerNorthPanel = new JPanel(new GridLayout(1, 4, 5, 5));
        centerNorthPanel.add(classIndexPanel);
        centerNorthPanel.add(buttonsPanel);
        centerNorthPanel.add(emptyPanel1);
        centerNorthPanel.add(emptyPanel2);

        JPanel centerPanel = new JPanel(new BorderLayout());
        centerPanel.add(outputPanel, BorderLayout.CENTER);
        centerPanel.add(centerNorthPanel, BorderLayout.NORTH);

        setLayout(new BorderLayout());
        add(northPanel, BorderLayout.NORTH);
        add(southPanel, BorderLayout.SOUTH);
        add(centerPanel, BorderLayout.CENTER);
    }

    public void actionPerformed(ActionEvent ae) {
        if (ae.getSource().equals(this.fileButton)) {
            loadFile();
        } else if (ae.getSource().equals(this.startButton)) {
            start();
        } else if (ae.getSource().equals(this.stopButton)) {
            stop();
        } else if (ae.getSource().equals(this.saveClustererButton)) {
            saveClusterer();
        }
    }

    private void saveClusterer() {
        if (this.clusterer == null) {
            JOptionPane.showMessageDialog(parent, "Please train clusterer first!", "Error",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
        JFileChooser fc;
        String lastLocation = SiriusSettings.getInformation("LastClusteringOutputLocation: ");
        if (lastLocation == null)
            fc = new JFileChooser();
        else
            fc = new JFileChooser(lastLocation);
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Clusterer Files", "clusterer");
        fc.setFileFilter(filter);
        int returnVal = fc.showSaveDialog(parent);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            String savingFilename = file.getAbsolutePath();
            if (savingFilename.indexOf(".clusterer") == -1)
                savingFilename += ".clusterer";
            try {
                this.statusLabel.setText(" Saving..");
                FileOutputStream fos1 = new FileOutputStream(savingFilename);
                ObjectOutputStream oos1 = new ObjectOutputStream(fos1);
                oos1.writeObject(this.clusterer);
                oos1.close();
                SiriusSettings.updateInformation("LastCLusteringOutputLocation: ", savingFilename);
                this.statusLabel.setText(" Saving..Done!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void start() {
        if (this.fileTextField.getText().length() == 0) {
            JOptionPane.showMessageDialog(parent, "Please choose training file!", "Error",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
        if (m_ClustererEditor.getValue() == null) {
            JOptionPane.showMessageDialog(parent, "Please choose clustering method!", "Error",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
        if (clusterThread != null) {
            JOptionPane.showMessageDialog(parent, "Cannot start training of Clusterer as another is running!",
                    "Error", JOptionPane.ERROR_MESSAGE);
            return;
        }
        this.startButton.setEnabled(false);
        this.stopButton.setEnabled(true);
        this.numberOfClusterTextField.setText("");
        clusterThread = (new Thread() {
            public void run() {
                try {
                    Instances inst = new Instances(new BufferedReader(new FileReader(fileTextField.getText())));
                    inst.setClassIndex(m_ClassCombo.getSelectedIndex());
                    if (inst.classAttribute().isNumeric()) {
                        JOptionPane.showMessageDialog(parent, "Class must be nominal!", "Error",
                                JOptionPane.ERROR_MESSAGE);
                    } else {
                        outputTextArea.setText("");
                        clusterer = (Clusterer) m_ClustererEditor.getValue();
                        statusLabel.setText(" Training Clusterer..");
                        clusterer.buildClusterer(removeClass(inst));
                        ClusterEvaluation eval = new ClusterEvaluation();
                        eval.setClusterer(clusterer);
                        eval.evaluateClusterer(inst);
                        outputTextArea.append(eval.clusterResultsToString());
                        outputTextArea.append("\n");
                        if (clusterer != null) {
                            numberOfClusterTextField.setText("" + clusterer.numberOfClusters());
                            statusLabel.setText(" Clusterer Trained..");
                        }
                    }
                    startButton.setEnabled(true);
                    stopButton.setEnabled(false);
                    clusterThread = null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        clusterThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
        clusterThread.start();
    }

    private Instances removeClass(Instances inst) {//Copied directly from Weka's ClustererPanel.java
        Remove af = new Remove();
        Instances retI = null;
        try {
            if (inst.classIndex() < 0) {
                //do nothing since classindex is not set
                retI = inst;
            } else {
                //remove class attribute
                af.setAttributeIndices("" + (inst.classIndex() + 1));
                af.setInvertSelection(false);
                af.setInputFormat(inst);
                retI = Filter.useFilter(inst, af);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retI;
    }

    private void stop() {
        this.clusterThread = null;
        this.clusterer = null;
        this.startButton.setEnabled(true);
        this.stopButton.setEnabled(false);
        this.statusLabel.setText(" Training Clusterer - Interrupted..");
    }

    private void loadFile() {
        try {
            JFileChooser fc;
            String lastLocation = SiriusSettings.getInformation("LastClusteringOutputLocation: ");
            if (lastLocation == null)
                fc = new JFileChooser();
            else
                fc = new JFileChooser(lastLocation);
            FileNameExtensionFilter filter = new FileNameExtensionFilter("Arff File", "arff");
            fc.setFileFilter(filter);
            int returnVal = fc.showOpenDialog(parent);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fc.getSelectedFile();
                SiriusSettings.updateInformation("LastClusteringOutputLocation: ", file.getAbsolutePath());
                this.fileTextField.setText(file.getAbsolutePath());
                Instances inst = new Instances(new BufferedReader(new FileReader(fileTextField.getText())));
                setInstances(inst);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setInstances(Instances inst) {//Directly copied with slight modification from weka's ClustererPanel.java
        String[] attribNames = new String[inst.numAttributes()];
        for (int i = 0; i < inst.numAttributes(); i++) {
            String type = "";
            switch (inst.attribute(i).type()) {
            case Attribute.NOMINAL:
                type = "(Nom) ";
                break;
            case Attribute.NUMERIC:
                type = "(Num) ";
                break;
            case Attribute.STRING:
                type = "(Str) ";
                break;
            case Attribute.DATE:
                type = "(Dat) ";
                break;
            case Attribute.RELATIONAL:
                type = "(Rel) ";
                break;
            default:
                type = "(???) ";
            }
            String attnm = inst.attribute(i).name();
            attribNames[i] = type + attnm;
        }
        m_ClassCombo.setModel(new DefaultComboBoxModel(attribNames));
        if (inst.classIndex() == -1)
            m_ClassCombo.setSelectedIndex(attribNames.length - 1);
        else
            m_ClassCombo.setSelectedIndex(inst.classIndex());
    }
}