/*
* 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.Dialog;
import java.awt.Frame;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import org.jax.maanova.Maanova;
import org.jax.maanova.configuration.MaanovaApplicationConfigurationManager;
import org.jax.maanova.madata.MicroarrayExperiment;
import org.jax.maanova.madata.ProbesetRow;
import org.jax.maanova.madata.gui.AddGeneListDialog;
import org.jax.maanova.test.MaanovaTestResult;
import org.jax.maanova.test.MaanovaTestStatisticSubtype;
import org.jax.maanova.test.MaanovaTestStatisticType;
import org.jax.maanova.test.MaanovaTestStatistics;
import org.jax.util.Condition;
import org.jax.util.ObjectUtil;
import org.jax.util.datastructure.SequenceUtilities;
import org.jax.util.gui.MessageDialogUtilities;
import org.jax.util.io.CommonFlatFileFormat;
import org.jax.util.io.FileChooserExtensionFilter;
import org.jax.util.io.FlatFileWriter;
/**
* The panel for displaying test results
* @author <A HREF="mailto:keith.sheppard@jax.org">Keith Sheppard</A>
*/
public class TestResultsPanel extends JPanel
{
/**
* every {@link java.io.Serializable} is supposed to have one of these
*/
private static final long serialVersionUID = 9130392632381226634L;
private static final Logger LOG = Logger.getLogger(
TestResultsPanel.class.getName());
private static final String PROBESET_ID_HEADER_STRING = "Probeset ID";
private volatile int[] validIndices = null;
private final MaanovaTestResult testResult;
private DefaultTableModel resultsTableModel;
private FilterSortRowsDialog filterSortDialog;
private SubsetColumnsDialog subsetColumnsDialog;
/**
* Constructor
* @param testResult
* the test results to display
*/
public TestResultsPanel(MaanovaTestResult testResult)
{
this(testResult, 0);
}
/**
* Constructor
* @param testResult
* the test results to display
* @param initialTestIndex
* the initial test index that we should display
*/
public TestResultsPanel(
MaanovaTestResult testResult,
int initialTestIndex)
{
this.testResult = testResult;
this.initComponents();
this.postGuiInit(initialTestIndex);
}
/**
* take care of the GUI initialization that isn't handled by the GUI
* builder
* @param initialTestIndex the initial test index to use
*/
private void postGuiInit(int initialTestIndex)
{
this.resultsTableModel = new DefaultTableModel()
{
/**
* every Serializable is supposed to have one of these
*/
private static final long serialVersionUID = 2005622745249975240L;
/**
* {@inheritDoc}
*/
@Override
public boolean isCellEditable(int row, int column)
{
return false;
}
};
this.resultsTable.setModel(this.resultsTableModel);
this.resultsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener()
{
/**
* {@inheritDoc}
*/
public void valueChanged(ListSelectionEvent e)
{
TestResultsPanel.this.rowSelectionChanged();
}
});
MaanovaTestStatistics fStat = this.testResult.getStatistics(
MaanovaTestStatisticType.F_STAT);
int testCount = fStat.getContrastCount();
for(int i = 0; i < testCount; i++)
{
this.testNumberComboBox.addItem(i + 1);
}
this.testNumberComboBox.setSelectedIndex(initialTestIndex);
if(testCount == 1)
{
// don't bother the user with a choice for test number if there
// is only one option that can be chosen
this.testNumberLabel.setVisible(false);
this.testNumberComboBox.setVisible(false);
}
else
{
this.testNumberComboBox.addItemListener(new ItemListener()
{
/**
* {@inheritDoc}
*/
public void itemStateChanged(ItemEvent e)
{
if(e.getStateChange() == ItemEvent.SELECTED)
{
TestResultsPanel.this.refreshTable();
}
}
});
}
this.filterSortRowsButton.addActionListener(new ActionListener()
{
/**
* {@inheritDoc}
*/
public void actionPerformed(ActionEvent e)
{
TestResultsPanel.this.showFilterSortDialog();
}
});
this.subsetColumnsButton.addActionListener(new ActionListener()
{
/**
* {@inheritDoc}
*/
public void actionPerformed(ActionEvent e)
{
TestResultsPanel.this.showSubsetColumnsDialog();
}
});
this.exportToFlatFileButton.addActionListener(new ActionListener()
{
/**
* {@inheritDoc}
*/
public void actionPerformed(ActionEvent e)
{
TestResultsPanel.this.exportResultsToFlatFile();
}
});
this.showVolcanoPlotButton.addActionListener(new ActionListener()
{
/**
* {@inheritDoc}
*/
public void actionPerformed(ActionEvent e)
{
TestResultsPanel.this.showVolcanoPlot();
}
});
this.saveGeneListButton.addActionListener(new ActionListener()
{
/**
* {@inheritDoc}
*/
public void actionPerformed(ActionEvent e)
{
TestResultsPanel.this.saveGeneList();
}
});
Icon helpIcon = new ImageIcon(TestResultsPanel.class.getResource(
"/images/action/help-16x16.png"));
this.helpButton.setIcon(helpIcon);
this.helpButton.addActionListener(new ActionListener()
{
/**
* {@inheritDoc}
*/
public void actionPerformed(ActionEvent e)
{
TestResultsPanel.this.help();
}
});
this.refreshTable();
}
private void help()
{
Maanova.getInstance().showHelp("test-results-table", this);
}
private void rowSelectionChanged()
{
this.selectedRowCountTextField.setText(Integer.toString(
this.resultsTable.getSelectedRowCount()));
}
private void saveGeneList()
{
List<StatisticItem> headerItems = this.getSelectedStatistics();
ProbesetRow[] matrix = this.getSortedFilteredMatrix(headerItems);
List<String> genes = new ArrayList<String>();
final int[] selectedRowIndices = this.getSelectedRowIndices();
if(selectedRowIndices.length == 0)
{
MessageDialogUtilities.warn(
this,
"Please select the gene rows that you would " +
"like to add to a gene list. To select all rows you " +
"can use <control+A> on Windows or <command+A> on " +
"Mac OS X.",
"No Rows Selected");
return;
}
int ii = 0;
for(int i = 0; i < matrix.length && ii < selectedRowIndices.length; i++)
{
if(selectedRowIndices[ii] == i)
{
genes.add(matrix[i].getId());
ii++;
}
}
AddGeneListDialog dialog = new AddGeneListDialog(
(JFrame)org.jax.util.gui.SwingUtilities.getContainingWindow(this),
this.testResult.getParentExperiment(),
genes);
dialog.pack();
dialog.setVisible(true);
}
/**
* Getter for the selected indices
* @return the selected indices
*/
private int[] getSelectedRowIndices()
{
int[] indices = this.resultsTable.getSelectedRows();
Arrays.sort(indices);
return indices;
}
/**
* export the current results to CSV file
*/
private void exportResultsToFlatFile()
{
MaanovaApplicationConfigurationManager manager =
MaanovaApplicationConfigurationManager.getInstance();
JFileChooser fileChooser = new JFileChooser(
manager.getStartingDataDirectory());
fileChooser.setDialogTitle("Export Table to CSV");
fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setMultiSelectionEnabled(false);
fileChooser.setFileFilter(new FileChooserExtensionFilter(
"csv",
"Comma-Separated Values"));
int response = fileChooser.showSaveDialog(this);
if(response == JFileChooser.APPROVE_OPTION)
{
File selectedFile = fileChooser.getSelectedFile();
if(selectedFile != null &&
(!selectedFile.exists() || MessageDialogUtilities.confirmOverwrite(this, selectedFile)))
{
manager.setStartingDataDirectory(selectedFile.getParentFile());
try
{
FlatFileWriter writer = new FlatFileWriter(
new BufferedWriter(new FileWriter(selectedFile)),
CommonFlatFileFormat.CSV_UNIX);
List<StatisticItem> headerItems =
this.getSelectedStatistics();
String[] headerStrings = new String[headerItems.size() + 1];
headerStrings[0] = PROBESET_ID_HEADER_STRING;
for(int colIndex = 1; colIndex < headerStrings.length; colIndex++)
{
headerStrings[colIndex] = headerItems.get(colIndex - 1).toString();
}
writer.writeRow(headerStrings);
ProbesetRow[] matrix = this.getSortedFilteredMatrix(headerItems);
for(ProbesetRow row: matrix)
{
this.writeProbesetRow(writer, row);
}
writer.flush();
writer.close();
}
catch(IOException ex)
{
String titleString = "Error Writing Table";
LOG.log(Level.SEVERE,
titleString,
ex);
MessageDialogUtilities.errorLater(
this,
ex.getMessage(),
titleString);
}
}
}
}
/**
* Write a probeset row
* @param writer the flat file writer to write to
* @param row the probeset row to write
* @throws IOException the IO exception
*/
private void writeProbesetRow(FlatFileWriter writer, ProbesetRow row) throws IOException
{
Double[] rowValues = row.getValues();
String[] tblRow = new String[rowValues.length + 1];
tblRow[0] = row.getId();
for(int colIndex = 1; colIndex < tblRow.length; colIndex++)
{
tblRow[colIndex] = rowValues[colIndex - 1].toString();
}
writer.writeRow(tblRow);
}
/**
* Show the subset columns dialog
*/
private void showSubsetColumnsDialog()
{
this.maybeInitSubsetColumnsDialog();
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
/**
* {@inheritDoc}
*/
public void run()
{
TestResultsPanel.this.subsetColumnsDialog.setVisible(true);
}
});
}
private void maybeInitSubsetColumnsDialog()
{
if(this.subsetColumnsDialog == null)
{
Window parent = org.jax.util.gui.SwingUtilities.getContainingWindow(this);
if(parent instanceof Frame)
{
this.subsetColumnsDialog = new SubsetColumnsDialog((Frame)parent);
}
else
{
this.subsetColumnsDialog = new SubsetColumnsDialog((Dialog)parent);
}
this.subsetColumnsDialog.pack();
this.subsetColumnsDialog.setStatistics(this.getAllStatistics());
// when the window is made invisible that means it
// has been closed and we should update the table to take into
// account any modified settings
this.subsetColumnsDialog.addComponentListener(new ComponentAdapter()
{
/**
* {@inheritDoc}
*/
@Override
public void componentHidden(ComponentEvent e)
{
TestResultsPanel.this.refreshTable();
}
});
}
}
/**
* Show the filter/sort dialog
*/
private void showFilterSortDialog()
{
this.maybeInitFilterSortDialog();
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
/**
* {@inheritDoc}
*/
public void run()
{
TestResultsPanel.this.filterSortDialog.setVisible(true);
}
});
}
private void maybeInitFilterSortDialog()
{
if(this.filterSortDialog == null)
{
Window parent = org.jax.util.gui.SwingUtilities.getContainingWindow(this);
if(parent instanceof Frame)
{
this.filterSortDialog = new FilterSortRowsDialog(
(Frame)parent,
this.testResult);
}
else
{
this.filterSortDialog = new FilterSortRowsDialog(
(Dialog)parent,
this.testResult);
}
this.filterSortDialog.pack();
this.filterSortDialog.setStatistics(this.getAllStatistics());
// when the window is made invisible that means it
// has been closed and we should update the table to take into
// account any modified settings
this.filterSortDialog.addComponentListener(new ComponentAdapter()
{
/**
* {@inheritDoc}
*/
@Override
public void componentHidden(ComponentEvent e)
{
TestResultsPanel.this.filterSortDialogClosed();
}
});
}
}
/**
* for when the filter/sort dialog has been closed
*/
private void filterSortDialogClosed()
{
String geneList = this.filterSortDialog.getGeneListToFilterBy();
if(geneList == null)
{
this.validIndices = null;
}
else
{
MicroarrayExperiment experiment = this.testResult.getParentExperiment();
this.validIndices = experiment.getIndicesForGeneListNamed(geneList);
}
this.refreshTable();
}
private void refreshTable()
{
this.resultsTableModel.setRowCount(0);
List<StatisticItem> selectedStats = this.getSelectedStatistics();
{
Vector<Object> headerStrings = new Vector<Object>(selectedStats.size() + 1);
headerStrings.add(PROBESET_ID_HEADER_STRING);
headerStrings.addAll(selectedStats);
this.resultsTableModel.setColumnIdentifiers(headerStrings);
}
ProbesetRow[] statsMatrix = this.getSortedFilteredMatrix(selectedStats);
for(ProbesetRow statsRow: statsMatrix)
{
Double[] currRowValues = statsRow.getValues();
String[] tableRow = new String[currRowValues.length + 1];
tableRow[0] = statsRow.getId();
for(int tblCol = 1; tblCol < tableRow.length; tblCol++)
{
tableRow[tblCol] = currRowValues[tblCol - 1].toString();
}
this.resultsTableModel.addRow(tableRow);
}
this.totalRowCountTextField.setText(Integer.toString(statsMatrix.length));
this.selectedRowCountTextField.setText("0");
}
private ProbesetRow[] getSortedFilteredMatrix(List<StatisticItem> selectedStats)
{
ProbesetRow[] statsMatrix = this.getStatisticsMatrix(selectedStats);
if(this.filterSortDialog != null)
{
if(this.filterSortDialog.isFilteringOn())
{
StatisticItem filterStat =
this.filterSortDialog.getSelectedFilterStatistic();
double filterThreshold =
this.filterSortDialog.getSelectedFilterThreshold();
statsMatrix = this.filterMatrixByThreshold(
selectedStats,
statsMatrix,
filterStat,
filterThreshold);
}
if(this.filterSortDialog.isSortingOn())
{
StatisticItem sortStat =
this.filterSortDialog.getSelectedSortStatistic();
statsMatrix = this.sortMatrix(
selectedStats,
statsMatrix,
sortStat);
}
}
return statsMatrix;
}
private void showVolcanoPlot()
{
List<StatisticItem> testStats = this.getSelectedStatistics();
final int[] selectedRowIndices = this.getSelectedRowIndices();
final int[] selectedGeneIndices = new int[selectedRowIndices.length];
if(selectedGeneIndices.length > 0)
{
final ProbesetRow[] statsMatrix = this.getSortedFilteredMatrix(testStats);
int ii = 0;
for(int i = 0; i < statsMatrix.length && ii < selectedRowIndices.length; i++)
{
if(selectedRowIndices[ii] == i)
{
selectedGeneIndices[ii] = statsMatrix[i].getIndex();
ii++;
}
}
}
Arrays.sort(selectedGeneIndices);
final VolcanoPlotAction volcanoPlotAction = new VolcanoPlotAction(
this.testResult,
this.testNumberComboBox.getSelectedIndex(),
selectedGeneIndices);
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
/**
* {@inheritDoc}
*/
public void run()
{
volcanoPlotAction.act();
}
});
}
private ProbesetRow[] sortMatrix(
List<StatisticItem> matrixHeader,
final ProbesetRow[] statsMatrix,
final StatisticItem sortStat)
{
final int sortColIndex = matrixHeader.indexOf(sortStat);
if(sortColIndex == -1)
{
String warningMessage =
"Cannot sort on " + sortStat + " because that column has " +
"been hidden.";
LOG.warning(warningMessage);
MessageDialogUtilities.warn(
this,
warningMessage,
"Cannot Sort");
return new ProbesetRow[0];
}
else
{
final boolean reverseSort = requiresReverseOrdering(sortStat);
final boolean takeAbsValue = sortStat instanceof FoldChangeStatisticItem;
Comparator<ProbesetRow> sortComparator = new Comparator<ProbesetRow>()
{
/**
* {@inheritDoc}
*/
public int compare(ProbesetRow row1, ProbesetRow row2)
{
Double val1 = row1.getValues()[sortColIndex];
if(takeAbsValue && val1 != null && val1.doubleValue() < 0.0)
{
val1 = new Double(-val1.doubleValue());
}
Double val2 = row2.getValues()[sortColIndex];
if(takeAbsValue && val2 != null && val2.doubleValue() < 0.0)
{
val2 = new Double(-val2.doubleValue());
}
int comp = ObjectUtil.compare(val1, val2);
return reverseSort ? -comp : comp;
}
};
Arrays.sort(statsMatrix, sortComparator);
return statsMatrix;
}
}
private boolean requiresReverseOrdering(StatisticItem statisticItem)
{
if(statisticItem instanceof FoldChangeStatisticItem)
{
return true;
}
else
{
TestStatisticItem statisticTestItem = (TestStatisticItem)statisticItem;
switch(statisticTestItem.getTestStatisticSubtype())
{
case F_OBSERVED:
{
return true;
}
default:
{
return false;
}
}
}
}
/**
* Filter values from the given matrix using the given threshold value
* @param matrixHeader
* the header values for the stats matrix
* @param statsMatrix
* the stats matrix to filter
* @param filterStat
* the statistic to filter on
* @param filterThreshold
* the threshold to use
* @return
* the filtered array
*/
private ProbesetRow[] filterMatrixByThreshold(
List<StatisticItem> matrixHeader,
final ProbesetRow[] statsMatrix,
final StatisticItem filterStat,
final double filterThreshold)
{
int filterColIndex = matrixHeader.indexOf(filterStat);
if(filterColIndex == -1)
{
String warningMessage =
"Cannot filter on " + filterStat + " because that column has " +
"been hidden.";
LOG.warning(warningMessage);
MessageDialogUtilities.warn(
this,
warningMessage,
"Cannot Filter");
return new ProbesetRow[0];
}
else
{
List<ProbesetRow> filteredList = new ArrayList<ProbesetRow>();
final boolean takeAbsValue = filterStat instanceof FoldChangeStatisticItem;
final boolean reverseOrder = this.requiresReverseOrdering(filterStat);
final Condition<Double> filterCond = new Condition<Double>()
{
public boolean test(Double value)
{
if(value == null)
{
return false;
}
else
{
double dblVal = value.doubleValue();
if(takeAbsValue)
{
dblVal = Math.abs(dblVal);
}
if(reverseOrder)
{
return dblVal >= filterThreshold;
}
else
{
return dblVal <= filterThreshold;
}
}
}
};
// loop through everything only keeping the values that pass
// through the filter
for(int i = 0; i < statsMatrix.length; i++)
{
if(filterCond.test(statsMatrix[i].getValues()[filterColIndex]))
{
filteredList.add(statsMatrix[i]);
}
}
return filteredList.toArray(new ProbesetRow[filteredList.size()]);
}
}
/**
* Get the 2D stats matrix. This returns a 2D row x column matrix where
* the rows can be given directly to a JTable
* @param testStatisticsItems
* the items to extract
* @return
* the matrix
*/
private ProbesetRow[] getStatisticsMatrix(List<StatisticItem> testStatisticsItems)
{
Double[][] matrix = new Double[testStatisticsItems.size()][];
for(int i = 0; i < matrix.length; i++)
{
StatisticItem currStatItem = testStatisticsItems.get(i);
if(currStatItem instanceof FoldChangeStatisticItem)
{
matrix[i] = this.testResult.getFoldChangeValues(
this.testNumberComboBox.getSelectedIndex());
}
else
{
TestStatisticItem currTestStatItem = (TestStatisticItem)currStatItem;
MaanovaTestStatistics stats = this.testResult.getStatistics(
currTestStatItem.getTestStatisticType());
matrix[i] = stats.getValues(
currTestStatItem.getTestStatisticSubtype(),
this.testNumberComboBox.getSelectedIndex());
}
}
// transpose the transpose so that data rows are together
matrix = SequenceUtilities.transposeMatrix(matrix);
String[] probesetIds = this.testResult.getProbesetIds();
assert probesetIds.length == matrix.length;
ProbesetRow[] probesetRows = new ProbesetRow[matrix.length];
for(int row = 0; row < probesetRows.length; row++)
{
probesetRows[row] = new ProbesetRow(probesetIds[row], matrix[row], row);
}
return SequenceUtilities.retainIndices(
this.validIndices,
probesetRows);
}
/**
* Get selected test statistics
* @return the selected test statistics
*/
private List<StatisticItem> getSelectedStatistics()
{
if(this.subsetColumnsDialog == null)
{
return this.getAllStatistics();
}
else
{
return this.subsetColumnsDialog.getSelectedStatistics();
}
}
private List<StatisticItem> getAllStatistics()
{
List<StatisticItem> stats = new ArrayList<StatisticItem>();
stats.add(new FoldChangeStatisticItem());
for(MaanovaTestStatisticType currType: MaanovaTestStatisticType.values())
{
for(MaanovaTestStatisticSubtype currSubtype: MaanovaTestStatisticSubtype.values())
{
MaanovaTestStatistics currStats = this.testResult.getStatistics(currType);
if(currStats.hasTestStatistic(currSubtype))
{
stats.add(new TestStatisticItem(
currType,
currSubtype));
}
}
}
return stats;
}
/**
* 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() {
testNumberLabel = new javax.swing.JLabel();
testNumberComboBox = new javax.swing.JComboBox();
filterSortRowsButton = new javax.swing.JButton();
subsetColumnsButton = new javax.swing.JButton();
javax.swing.JScrollPane resultsTableScrollPane = new javax.swing.JScrollPane();
resultsTable = new javax.swing.JTable();
javax.swing.JLabel totalRowCountLabel = new javax.swing.JLabel();
totalRowCountTextField = new javax.swing.JTextField();
javax.swing.JLabel selectedRowCountLabel = new javax.swing.JLabel();
selectedRowCountTextField = new javax.swing.JTextField();
exportToFlatFileButton = new javax.swing.JButton();
showVolcanoPlotButton = new javax.swing.JButton();
saveGeneListButton = new javax.swing.JButton();
helpButton = new javax.swing.JButton();
testNumberLabel.setText("Test Number:");
filterSortRowsButton.setText("Filter/Sort Rows...");
subsetColumnsButton.setText("Add/Remove Columns...");
resultsTableScrollPane.setViewportView(resultsTable);
totalRowCountLabel.setText("Total Row Count:");
totalRowCountTextField.setEditable(false);
selectedRowCountLabel.setText("Selected Row Count:");
selectedRowCountTextField.setEditable(false);
exportToFlatFileButton.setText("Export To CSV...");
showVolcanoPlotButton.setText("Show Volcano Plot...");
saveGeneListButton.setText("Add Selected Rows to List...");
helpButton.setText("Help...");
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(resultsTableScrollPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 680, Short.MAX_VALUE)
.add(layout.createSequentialGroup()
.add(testNumberLabel)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(testNumberComboBox, 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(filterSortRowsButton)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(subsetColumnsButton))
.add(layout.createSequentialGroup()
.add(exportToFlatFileButton)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(showVolcanoPlotButton)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(saveGeneListButton)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(helpButton))
.add(layout.createSequentialGroup()
.add(totalRowCountLabel)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(totalRowCountTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(18, 18, 18)
.add(selectedRowCountLabel)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(selectedRowCountTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.add(20, 20, 20)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(testNumberLabel)
.add(testNumberComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(filterSortRowsButton)
.add(subsetColumnsButton))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(resultsTableScrollPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 213, Short.MAX_VALUE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(totalRowCountLabel)
.add(totalRowCountTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(selectedRowCountLabel)
.add(selectedRowCountTextField, 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(exportToFlatFileButton)
.add(showVolcanoPlotButton)
.add(saveGeneListButton)
.add(helpButton))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton exportToFlatFileButton;
private javax.swing.JButton filterSortRowsButton;
private javax.swing.JButton helpButton;
private javax.swing.JTable resultsTable;
private javax.swing.JButton saveGeneListButton;
private javax.swing.JTextField selectedRowCountTextField;
private javax.swing.JButton showVolcanoPlotButton;
private javax.swing.JButton subsetColumnsButton;
private javax.swing.JComboBox testNumberComboBox;
private javax.swing.JLabel testNumberLabel;
private javax.swing.JTextField totalRowCountTextField;
// End of variables declaration//GEN-END:variables
}