/* * Copyright (c) 2010 The Jackson Laboratory * * This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. */ package org.jax.maanova.test.gui; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import org.jax.maanova.fit.FitMaanovaResult; import org.jax.maanova.fit.MixedModelSolutionMethod; import org.jax.maanova.madata.MicroarrayExperiment; import org.jax.maanova.project.MaanovaProject; import org.jax.maanova.test.TestModelCommandBuilder; import org.jax.maanova.test.TestType; import org.jax.r.RCommand; import org.jax.r.gui.RCommandEditorPanel; import org.jax.util.gui.CheckableListTableModel; import org.jax.util.gui.MessageDialogUtilities; import org.jax.util.gui.Validatable; /** * panel for selecting the fit and terms that should be tested */ public class MaanovaTestInitialPanel extends RCommandEditorPanel implements Validatable { /** * every {@link java.io.Serializable} is supposed to have one of these */ private static final long serialVersionUID = 6610799970830720392L; private static final String NO_FITS_AVAILABLE = "No Fits Available"; private final Map<FitMaanovaResult, MicroarrayExperiment> fitToExperimentMap; private final CheckableListTableModel termsToTestTableModel; private final TestModelCommandBuilder commandBuilder; /** * Constructor * @param project * the project that we're using * @param commandBuilder * the test command builder that this panel will modify */ public MaanovaTestInitialPanel( MaanovaProject project, TestModelCommandBuilder commandBuilder) { this.commandBuilder = commandBuilder; this.fitToExperimentMap = new HashMap<FitMaanovaResult, MicroarrayExperiment>(); this.termsToTestTableModel = new CheckableListTableModel( new String[] {"Test Term", "Term Name"}, 1); this.initComponents(); this.postGuiInit(project); } /** * take care of the initialization that wasn't handled by * @param project the project that we're doing a test for */ private void postGuiInit(MaanovaProject project) { // initialize the table this.termsToTestTable.setModel(this.termsToTestTableModel); this.termsToTestTableModel.addTableModelListener(new TableModelListener() { /** * {@inheritDoc} */ public void tableChanged(TableModelEvent e) { MaanovaTestInitialPanel.this.termsToTestTableModelChanged(); } }); // initialize the drop down along with any eventing MicroarrayExperiment[] allExperiments = project.getDataModel().getMicroarrays(); for(MicroarrayExperiment experiment: allExperiments) { for(FitMaanovaResult fit: experiment.getFitMaanovaResults()) { this.fitToExperimentMap.put(fit, experiment); this.experimentAndFitComboBox.addItem(fit); } } // TODO shouldn't fitmaanova and matest share the same methods? it // does not appear that that is the case for(MixedModelSolutionMethod method: MixedModelSolutionMethod.values()) { this.methodComboBox.addItem(method); } this.methodComboBox.addItemListener(new ItemListener() { /** * {@inheritDoc} */ public void itemStateChanged(ItemEvent e) { MaanovaTestInitialPanel.this.selectedMethodChanged(); } }); this.selectedMethodChanged(); if(this.fitToExperimentMap.isEmpty()) { this.experimentAndFitComboBox.addItem(NO_FITS_AVAILABLE); } else { this.experimentAndFitComboBox.addItemListener(new ItemListener() { /** * {@inheritDoc} */ public void itemStateChanged(ItemEvent e) { if(e.getStateChange() == ItemEvent.SELECTED) { MaanovaTestInitialPanel.this.selectedFitChanged(); } } }); } this.selectedFitChanged(); this.testTypeComboBox.addItem(TestType.F_TEST); this.testTypeComboBox.addItem(TestType.T_TEST); this.testTypeComboBox.addItemListener(new ItemListener() { /** * {@inheritDoc} */ public void itemStateChanged(ItemEvent e) { // don't worry about the deselected events. we don't need them if(e.getStateChange() == ItemEvent.SELECTED) { MaanovaTestInitialPanel.this.selectedTestTypeChanged(); } } }); this.selectedTestTypeChanged(); } /** * Respond to a change in the test method */ private void selectedMethodChanged() { this.commandBuilder.setMixedModelSolutionMethod( (MixedModelSolutionMethod)this.methodComboBox.getSelectedItem()); this.fireCommandModified(); } /** * respond to a change in the selected test type */ private void selectedTestTypeChanged() { this.commandBuilder.setTestType( (TestType)this.testTypeComboBox.getSelectedItem()); this.fireCommandModified(); } /** * respond to a change in the terms to test table model */ private void termsToTestTableModelChanged() { List<String> termsToTest = new ArrayList<String>(); int rowCount = this.termsToTestTableModel.getRowCount(); for(int i = 0; i < rowCount; i++) { Boolean selected = (Boolean)this.termsToTestTableModel.getValueAt(i, 0); if(selected) { termsToTest.add((String)this.termsToTestTableModel.getValueAt(i, 1)); } } this.commandBuilder.setTermsToTest(termsToTest.toArray( new String[termsToTest.size()])); FitMaanovaResult selectedFit = this.getSelectedFit(); List<String> levelsToTest = new ArrayList<String>(); if(selectedFit != null) { for(String term: termsToTest) { levelsToTest.addAll(Arrays.asList( selectedFit.getFitTermLevels(term))); } } this.commandBuilder.setLevelsToTest(levelsToTest.toArray( new String[levelsToTest.size()])); this.fireCommandModified(); } /** * respond to the user selecting a new fit */ private void selectedFitChanged() { final FitMaanovaResult selectedFit = this.getSelectedFit(); final MicroarrayExperiment selectedExperiment; if(selectedFit == null) { selectedExperiment = null; } else { selectedExperiment = this.fitToExperimentMap.get(selectedFit); } this.commandBuilder.setFitResultParameter( selectedFit == null ? null : selectedFit.getAccessorExpressionString()); this.commandBuilder.setMadataParameter( selectedExperiment == null ? null : selectedExperiment.getAccessorExpressionString()); this.updateTermsToTestTable(selectedFit); this.fireCommandModified(); } /** * Get the selected fit result * @return the selected fit or null */ private FitMaanovaResult getSelectedFit() { Object selectedItem = this.experimentAndFitComboBox.getSelectedItem(); if(selectedItem instanceof FitMaanovaResult) { return (FitMaanovaResult)selectedItem; } else { return null; } } /** * Update the terms table with a newly selected fit result * @param selectedFit * the newly selected fit */ private void updateTermsToTestTable(FitMaanovaResult selectedFit) { this.termsToTestTableModel.setRowCount(0); if(selectedFit != null) { for(String termName: selectedFit.getFitTermNames()) { this.termsToTestTableModel.addRow(new Object[] { Boolean.FALSE, termName}); } } } /** * {@inheritDoc} */ public RCommand[] getCommands() { return new RCommand[] {this.commandBuilder.getCommand()}; } /** * {@inheritDoc} */ public boolean validateData() { String errorMessage = null; if(this.commandBuilder.getFitResultParameter() == null) { errorMessage = "Cannot proceed without any fit result selected"; } else if(this.commandBuilder.getTermsToTest() == null || this.commandBuilder.getTermsToTest().length == 0) { errorMessage = "You must have at least one term selected before proceeding"; } if(errorMessage == null) { return true; } else { MessageDialogUtilities.warn( this, errorMessage, "Invalid Data"); return false; } } /** * This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ @SuppressWarnings("all") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { javax.swing.JLabel experimentAndFitLabel = new javax.swing.JLabel(); experimentAndFitComboBox = new javax.swing.JComboBox(); testTypeLabel = new javax.swing.JLabel(); testTypeComboBox = new javax.swing.JComboBox(); methodLabel = new javax.swing.JLabel(); methodComboBox = new javax.swing.JComboBox(); javax.swing.JLabel termsToTestLabel = new javax.swing.JLabel(); javax.swing.JScrollPane termsToTestScrollPane = new javax.swing.JScrollPane(); termsToTestTable = new javax.swing.JTable(); experimentAndFitLabel.setText("Experiment and Fit:"); testTypeLabel.setText("Test Type:"); methodLabel.setText("Method:"); termsToTestLabel.setText("Term(s) to Test:"); termsToTestScrollPane.setMinimumSize(new java.awt.Dimension(100, 100)); termsToTestScrollPane.setViewportView(termsToTestTable); org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .addContainerGap() .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(termsToTestScrollPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 506, Short.MAX_VALUE) .add(termsToTestLabel) .add(layout.createSequentialGroup() .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(experimentAndFitLabel) .add(testTypeLabel) .add(methodLabel)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(methodComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(testTypeComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(experimentAndFitComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .add(288, 288, 288))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .addContainerGap() .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(experimentAndFitLabel) .add(experimentAndFitComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(testTypeLabel) .add(testTypeComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(methodLabel) .add(methodComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(termsToTestLabel) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(termsToTestScrollPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 230, Short.MAX_VALUE) .addContainerGap()) ); }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JComboBox experimentAndFitComboBox; private javax.swing.JComboBox methodComboBox; private javax.swing.JLabel methodLabel; private javax.swing.JTable termsToTestTable; private javax.swing.JComboBox testTypeComboBox; private javax.swing.JLabel testTypeLabel; // End of variables declaration//GEN-END:variables }