Java tutorial
/*========================================================================== 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.misc.featurevisualizer; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import sirius.predictor.main.*; import sirius.trainer.main.SiriusSettings; import weka.attributeSelection.CfsSubsetEval; import weka.attributeSelection.ChiSquaredAttributeEval; import weka.core.Instances; import java.awt.event.*; import java.awt.*; import java.io.*; import java.text.DecimalFormat; import java.util.BitSet; public class FeatureVisualizerPane extends JComponent implements ActionListener, ComponentListener, ItemListener { static final long serialVersionUID = sirius.Sirius.version; private JTextField filenameTextField; private JButton browseButton; private JComboBox xAxisComboBox; private JComboBox yAxisComboBox; private JComboBox classComboBox; private JButton topChiSquareButton; private JButton topCFSButton; private JTextField yAxisIntervalTextField; private JTextField xAxisIntervalTextField; private Instances instances; private ChiSquaredAttributeEval myChiSquare; private int top1ChiSqIndex; private int top2ChiSqIndex; private int top1CFSIndex; private int top2CFSIndex; private JTextField statusTextField; private JTextField sequencesNumTextField; private JTextField featuresNumTextField; private JInternalFrame parent; private JTable sequenceNameTable; private SequenceNameTableModel sequenceNameTableModel; private JTextField sequenceNameTextField; private JButton sequenceNameButton; private FeatureGraphPane featureGraphPane; private FeatureViewPort featureViewPort; private JScrollPane featureGraphScrollPane; private double lastYAxisIntervalValue; private double lastXAxisIntervalValue; public FeatureVisualizerPane(final JInternalFrame parent, JTabbedPane tabbedPane) { this.parent = parent; JPanel arffFilePanel = new JPanel(); arffFilePanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Arff File"), BorderFactory.createEmptyBorder(0, 2, 2, 2))); filenameTextField = new JTextField(10); filenameTextField.setEnabled(false); browseButton = new JButton("Browse"); browseButton.addActionListener(this); arffFilePanel.add(filenameTextField); arffFilePanel.add(browseButton); JPanel yAxisPanel = new JPanel(); yAxisPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("y-Axis"), BorderFactory.createEmptyBorder(0, 2, 2, 2))); yAxisComboBox = new JComboBox(); yAxisComboBox.addItem(" "); yAxisComboBox.addItemListener(this); JLabel yAxisIntervalLabel = new JLabel("Interval: "); yAxisIntervalTextField = new JTextField(4); yAxisIntervalTextField.addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { } public void focusLost(FocusEvent e) { try { lastYAxisIntervalValue = Double.parseDouble(yAxisIntervalTextField.getText()); featureGraphPane.recalibrateYAxisLength(); featureViewPort.revalidate(); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(parent, "Invalid Input(Numbers Only)", "Error", JOptionPane.ERROR_MESSAGE); yAxisIntervalTextField.setText("" + lastYAxisIntervalValue); } } }); yAxisPanel.add(yAxisComboBox); yAxisPanel.add(yAxisIntervalLabel); yAxisPanel.add(yAxisIntervalTextField); JPanel xAxisPanel = new JPanel(); xAxisPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("x-Axis"), BorderFactory.createEmptyBorder(0, 2, 2, 2))); xAxisComboBox = new JComboBox(); xAxisComboBox.addItem(" "); xAxisComboBox.addItemListener(this); JLabel xAxisIntervalLabel = new JLabel("Interval: "); xAxisIntervalTextField = new JTextField(4); xAxisPanel.add(xAxisComboBox); xAxisPanel.add(xAxisIntervalLabel); xAxisPanel.add(xAxisIntervalTextField); xAxisIntervalTextField.addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { } public void focusLost(FocusEvent e) { try { lastXAxisIntervalValue = Double.parseDouble(xAxisIntervalTextField.getText()); featureGraphPane.recalibrateXAxisLength(); featureViewPort.revalidate(); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(parent, "Invalid Input(Numbers Only)", "Error", JOptionPane.ERROR_MESSAGE); xAxisIntervalTextField.setText("" + lastXAxisIntervalValue); } } }); JPanel classPanel = new JPanel(); classPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Class"), BorderFactory.createEmptyBorder(0, 5, 5, 5))); classComboBox = new JComboBox(); classComboBox.addItem(" "); classComboBox.setEnabled(false); classPanel.add(classComboBox); JPanel autoSelectPanel = new JPanel(); autoSelectPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Auto-Select"), BorderFactory.createEmptyBorder(0, 5, 5, 5))); topChiSquareButton = new JButton("Top 2 based on Chi-Square"); topChiSquareButton.addActionListener(this); topChiSquareButton.setEnabled(false); topCFSButton = new JButton("Top pair based on CFS"); topCFSButton.addActionListener(this); topCFSButton.setEnabled(false); autoSelectPanel.add(topChiSquareButton); autoSelectPanel.add(topCFSButton); JPanel statusPanel = new JPanel(new GridLayout(1, 1)); statusPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Status"), BorderFactory.createEmptyBorder(5, 5, 10, 5))); statusTextField = new JTextField(5); statusTextField.setEnabled(false); JPanel statsPanel = new JPanel(); statsPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Stats"), BorderFactory.createEmptyBorder(0, 5, 5, 5))); JLabel sequencesNumLabel = new JLabel("Sequences #: "); sequencesNumTextField = new JTextField(4); sequencesNumTextField.setEnabled(false); JLabel featuresNumLabel = new JLabel("Features #: "); featuresNumTextField = new JTextField(4); featuresNumTextField.setEnabled(false); statusPanel.add(statusTextField); statsPanel.add(sequencesNumLabel); statsPanel.add(sequencesNumTextField); statsPanel.add(featuresNumLabel); statsPanel.add(featuresNumTextField); JPanel northPanel = new JPanel(new BorderLayout()); JPanel northCenterPanel = new JPanel(new GridLayout(1, 2)); northPanel.add(arffFilePanel, BorderLayout.WEST); northCenterPanel.add(xAxisPanel); northCenterPanel.add(yAxisPanel); northPanel.add(northCenterPanel, BorderLayout.CENTER); JPanel southPanel = new JPanel(new GridLayout(1, 3)); southPanel.add(statusPanel); southPanel.add(statsPanel); southPanel.add(autoSelectPanel); JPanel centerPanel = new JPanel(new BorderLayout()); JPanel centerWestPanel = new JPanel(new BorderLayout()); centerWestPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Sequences Name"), BorderFactory.createEmptyBorder(0, 5, 5, 5))); sequenceNameTableModel = new SequenceNameTableModel(false); sequenceNameTable = new JTable(sequenceNameTableModel); sequenceNameTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); sequenceNameTable.getColumnModel().getColumn(0).setMinWidth(20); sequenceNameTable.getColumnModel().getColumn(1).setMinWidth(70); sequenceNameTable.getColumnModel().getColumn(0).setPreferredWidth(40); sequenceNameTable.getColumnModel().getColumn(1).setPreferredWidth(200); JScrollPane sequenceNameTableScrollPane = new JScrollPane(sequenceNameTable); centerWestPanel.add(sequenceNameTableScrollPane, BorderLayout.CENTER); JPanel sequenceNamePanel = new JPanel(); sequenceNamePanel.setBorder( BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Sequences Name File"), BorderFactory.createEmptyBorder(0, 5, 5, 5))); sequenceNameTextField = new JTextField(10); sequenceNameTextField.setEnabled(false); sequenceNameButton = new JButton("Browse"); sequenceNameButton.addActionListener(this); sequenceNamePanel.add(sequenceNameTextField); sequenceNamePanel.add(sequenceNameButton); centerPanel.add(centerWestPanel, BorderLayout.WEST); featureGraphPane = new FeatureGraphPane(instances, yAxisIntervalTextField, xAxisIntervalTextField); featureViewPort = new FeatureViewPort(featureGraphPane); JPanel featureGraphPanel = new JPanel(new BorderLayout()); featureGraphPanel.add(featureGraphPane, BorderLayout.CENTER); featureGraphScrollPane = new JScrollPane(); featureGraphScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); featureGraphScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); featureViewPort.setView(featureGraphPane); featureGraphScrollPane.setViewport(featureViewPort); featureGraphScrollPane.addComponentListener(this); featureGraphScrollPane.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Feature Graph"), BorderFactory.createEmptyBorder(0, 5, 5, 5))); centerPanel.add(featureGraphScrollPane, BorderLayout.CENTER); featureGraphPane.setParentDimension(featureGraphScrollPane.getSize()); setLayout(new BorderLayout()); add(northPanel, BorderLayout.NORTH); add(centerPanel, BorderLayout.CENTER); add(southPanel, BorderLayout.SOUTH); } public void itemStateChanged(ItemEvent e) { if (e.getSource().equals(xAxisComboBox)) { if (e.getStateChange() == ItemEvent.SELECTED) { featureGraphPane.setXIndex(xAxisComboBox.getSelectedIndex() - 1); featureViewPort.revalidate(); } } else if (e.getSource().equals(yAxisComboBox)) { if (e.getStateChange() == ItemEvent.SELECTED) { featureGraphPane.setYIndex(yAxisComboBox.getSelectedIndex() - 1); featureViewPort.revalidate(); } } } public void actionPerformed(ActionEvent ae) { if (ae.getSource().equals(browseButton)) { //applicationData.hasLocationIndexBeenSet = false; JFileChooser fc; //if working directory not set then look at the Sirius Settings file String lastLocation = SiriusSettings.getInformation("LastArffFileLocation: "); if (lastLocation == null) fc = new JFileChooser(); else fc = new JFileChooser(lastLocation); FileNameExtensionFilter filter = new FileNameExtensionFilter("Arff Files", "arff"); fc.setFileFilter(filter); int returnVal = fc.showOpenDialog(parent); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); SiriusSettings.updateInformation("LastArffFileLocation: ", file.getAbsolutePath()); filenameTextField.setText(file.getAbsolutePath()); try { loadArffFile(file); } catch (Exception e) { JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } } } else if (ae.getSource().equals(topChiSquareButton)) { if (instances != null) { setTop2ChiSqIndex(); setTop2ChiSq(); } } else if (ae.getSource().equals(topCFSButton)) { if (instances != null) { setTop2CFSIndex(); setTop2CFS(); } } } private void loadArffFile(final File file) throws Exception { Thread runThread = new Thread() { public void run() { try { instances = new Instances(new BufferedReader(new FileReader(file.getAbsolutePath()))); String sequenceNameFile = file.getAbsolutePath().substring(0, file.getAbsolutePath().indexOf(".arff")) + ".sequencesName"; featureGraphPane.setInstances(instances); sequenceNameTableModel.loadSequencesNameFile(sequenceNameFile); statusTextField.setText("Loading.."); instances.setClassIndex(instances.numAttributes() - 1); myChiSquare = new ChiSquaredAttributeEval(); myChiSquare.buildEvaluator(instances); yAxisComboBox.removeAllItems(); xAxisComboBox.removeAllItems(); yAxisComboBox.addItem(" "); xAxisComboBox.addItem(" "); updateComboBox(yAxisComboBox); updateComboBox(xAxisComboBox); updateComboBox(classComboBox); classComboBox.setSelectedIndex(classComboBox.getItemCount() - 1); classComboBox.repaint(); sequencesNumTextField.setText("" + instances.numInstances()); featuresNumTextField.setText("" + instances.numAttributes()); topChiSquareButton.setEnabled(true); topCFSButton.setEnabled(true); top1CFSIndex = -1; top2CFSIndex = -1; statusTextField.setText("Done"); } catch (Exception e) { JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } } }; runThread.setPriority(Thread.MIN_PRIORITY); runThread.start(); } private void updateComboBox(JComboBox comboBox) throws Exception { DecimalFormat df = new DecimalFormat("0.##"); for (int x = 0; x < this.instances.numAttributes(); x++) { comboBox.addItem( this.instances.attribute(x).name() + " (" + df.format(myChiSquare.evaluateAttribute(x)) + ")"); } } private void setTop2ChiSqIndex() { try { double top1ChiSq = -9999999; double top2ChiSq = -9999999; int divisor = instances.numAttributes() / 100; //-1 because assume that last attribute is class attribute for (int x = 0; x < this.instances.numAttributes() - 1; x++) { if (divisor != 0 && x % divisor == 0) statusTextField .setText("Calculating Top Chi-Sq.. " + ((x * 100) / instances.numAttributes()) + "%"); if (myChiSquare.evaluateAttribute(x) > top1ChiSq) { top2ChiSqIndex = top1ChiSqIndex; top2ChiSq = top1ChiSq; top1ChiSqIndex = x; top1ChiSq = myChiSquare.evaluateAttribute(x); } else if (myChiSquare.evaluateAttribute(x) > top2ChiSq) { top2ChiSqIndex = x; top2ChiSq = myChiSquare.evaluateAttribute(x); } } statusTextField.setText("Done"); } catch (Exception e) { JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } } private void setTop2ChiSq() { yAxisComboBox.setSelectedIndex(top1ChiSqIndex + 1); xAxisComboBox.setSelectedIndex(top2ChiSqIndex + 1); yAxisComboBox.repaint(); xAxisComboBox.repaint(); } private void setTop2CFSIndex() { if (top1CFSIndex != -1) return; Thread runThread = new Thread() { public void run() { try { CfsSubsetEval myCfs = new CfsSubsetEval(); myCfs.buildEvaluator(instances); double maxCFSScore = -9999999; int divisor = instances.numAttributes() / 100; BitSet bs = new BitSet(); //-1 because assume that last attribute is class attribute for (int x = 0; x < instances.numAttributes() - 1; x++) { if (divisor != 0 && x % divisor == 0) statusTextField.setText( "Calculating Top CFS.. " + ((x * 100) / instances.numAttributes()) + "%"); bs.set(x, true); //-1 because assume that last attribute is class attribute for (int y = (x + 1); y < instances.numAttributes() - 1; y++) { bs.set(y, true); if (myCfs.evaluateSubset(bs) > maxCFSScore) { maxCFSScore = myCfs.evaluateSubset(bs); top1CFSIndex = x; top2CFSIndex = y; } bs.set(y, false); } bs.set(x, false); } statusTextField.setText("Done"); setTop2CFS(); } catch (Exception e) { JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } } }; runThread.setPriority(Thread.MIN_PRIORITY); runThread.start(); } private void setTop2CFS() { yAxisComboBox.setSelectedIndex(top1CFSIndex + 1); xAxisComboBox.setSelectedIndex(top2CFSIndex + 1); yAxisComboBox.repaint(); xAxisComboBox.repaint(); } public void componentHidden(ComponentEvent e) { //Invoked when the component has been made invisible. } public void componentMoved(ComponentEvent e) { //Invoked when the component's position changes. } public void componentResized(ComponentEvent e) { //Invoked when the component's size changes. featureGraphPane.setParentDimension(featureGraphScrollPane.getSize()); } public void componentShown(ComponentEvent e) { //Invoked when the component has been made visible. } }