/*
* Copyright (c) 2009 The Jackson Laboratory
*
* This software was developed by Gary Churchill's Lab at The Jackson
* Laboratory (see http://research.jax.org/faculty/churchill).
*
* 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.qtl.ui;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.help.CSH;
import javax.help.HelpSet;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import org.jax.qtl.Constants;
import org.jax.qtl.QTL;
import org.jax.qtl.cross.Cross;
import org.jax.qtl.cross.CrossChromosome;
import org.jax.qtl.graph.OneDimensionPlotContainerPanel;
import org.jax.qtl.graph.RfPlot;
import org.jax.qtl.project.QtlProject;
import org.jax.qtl.project.QtlProjectManager;
import org.jax.qtl.util.Tools;
import org.jax.r.jriutilities.RInterface;
import org.jax.r.jriutilities.RInterfaceFactory;
import org.jax.r.jriutilities.SilentRCommand;
import org.rosuda.JRI.REXP;
/**
* <p>Title: QTL data analysis</p>
*
* <p>Description: </p>
*
* <p>Company: The Jackson Laboratory</p>
*
* @author Lei Wu
* @version 1.0
*/
public class RfPlotDialog extends JDialog implements Constants {
/**
*
*/
private static final long serialVersionUID = -824385139238584485L;
private int selectedCrossIndex, selectedMaxit = MAXIT_DEFAULT;
private JTextField tfMaxit, tfTol;
private String selectedTol = TOL_DEFAULT;
private int[] selectedChrIndexes = new int[] {0};
private Thread runRcommand;
private boolean newChrTable = true;
private ListSelectionTable tbChr;
private Cross[] crosses;
/**
* Constructor
*/
public RfPlotDialog() {
super(QTL.getInstance().getApplicationFrame(), "Recombination Fraction Plot", true);
QtlProject activeProject =
QtlProjectManager.getInstance().getActiveProject();
this.crosses = activeProject.getDataModel().getCrosses();
// TODO do the right thing with cross indexes
this.selectedCrossIndex = 0;
setCurrentPane(makeContentPane());
this.setLocation(this.getParent().getX() + 150, this.getParent().getY() + 150);
this.setModal(true);
this.pack();
setVisible(true);
}
// set the contentPane to the given content. This is used for updating the current window
private void setCurrentPane(JPanel content) {
getContentPane().removeAll();
this.setContentPane(content);
this.validate();
this.pack();
}
private JPanel makeContentPane() {
JPanel result = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
int line = 1;
result.add(makeCrossSelectionPane(), Tools.setGbc(c, 1,line++,1,1));
result.add(makeParameterSelectionPane(), Tools.setGbc(c, 1,line++,1,1));
result.add(makeChromosomeSelectionPane(), Tools.setGbc(c, 1,line++,1,1));
result.add(makeButtonPane(), Tools.setGbc(c, 1,line++,1,1));
return result;
}
private JPanel makeButtonPane() {
JButton okButton = new JButton("OK");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
dispose();
RfPlotDialog.this.runRcommand = new Thread(new Runnable() {
public void run() {
// set current cross in QTL
// run R command to get the estimated map
// maxit
String maxit = RfPlotDialog.this.tfMaxit.getText();
if (maxit.equals(MAXIT_DEFAULT + "")) maxit = "";
else maxit = ", " + maxit;
// tol
String tol = RfPlotDialog.this.tfTol.getText();
if (tol.equals(TOL_DEFAULT)) tol = "";
else tol = ", " + tol;
final Cross selectedCross =
RfPlotDialog.this.crosses[RfPlotDialog.this.selectedCrossIndex];
String rcmd =
selectedCross.getAccessorExpressionString() +
" <- est.rf(" +
selectedCross.getAccessorExpressionString() +
maxit +
tol + ")";
String comment =
"Estimate the sex-averaged recombination fraction for cross: " +
selectedCross.getAccessorExpressionString() + " ...";
RInterface rInterface = RInterfaceFactory.getRInterfaceInstance();
synchronized(rInterface)
{
rInterface.insertComment(comment);
rInterface.evaluateCommandNoReturn(rcmd);
}
// get the est.rf result from R for drawing RF plot
final double[][] rf;
synchronized(rInterface)
{
String rcmdForGetRf =
selectedCross.getAccessorExpressionString() +
"$rf";
REXP rfExpression = rInterface.evaluateCommand(
new SilentRCommand(rcmdForGetRf));
rf = rfExpression.asDoubleMatrix();
}
// update UI on EDT
SwingUtilities.invokeLater(new Runnable() {
public void run() {
String iframeid =
"Cross" +
selectedCross.getAccessorExpressionString() +
".rf";
RfPlot temp = new RfPlot(selectedCross, rf, RfPlotDialog.this.selectedChrIndexes);
QTL.getInstance().getDesktop().createInternalFrame(
new OneDimensionPlotContainerPanel(temp),
"RF Plot for cross: " + selectedCross.getAccessorExpressionString(),
null,
iframeid);
// parameters for making R command
String rcmd = "plot.rf(" + selectedCross.getAccessorExpressionString() + ")";
String comment =
"Plot recombination fraction plot for cross: " +
selectedCross.getAccessorExpressionString() + " ...";
RInterface rInterface = RInterfaceFactory.getRInterfaceInstance();
synchronized(rInterface)
{
rInterface.insertComment(comment);
// insert a comment in place of the command
// since we're taking care of the plot in
// java
rInterface.insertComment(rcmd);
}
}
});
}
});
RfPlotDialog.this.runRcommand.start();
}
});
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
dispose();
}
});
JButton helpButton = new JButton("Help");
HelpSet hs = QTL.getInstance().getMenubar().getHelpSet();
CSH.setHelpIDString(helpButton, "RF_Plot");
helpButton.addActionListener(new CSH.DisplayHelpFromSource(hs, "javax.help.SecondaryWindow", null));
JPanel buttonPane = new JPanel();
buttonPane.add(okButton);
buttonPane.add(cancelButton);
buttonPane.add(helpButton);
return buttonPane;
}
private JPanel makeCrossSelectionPane() {
final JComboBox crossListCombobox = new JComboBox(this.crosses);
int defaultHeight = (int) crossListCombobox.getPreferredSize().getHeight();
crossListCombobox.setPreferredSize(new Dimension(CROSS_COMBOBOX_WIDTH, defaultHeight));
crossListCombobox.setSelectedIndex(this.selectedCrossIndex);
crossListCombobox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
int oldCrossIndex = RfPlotDialog.this.selectedCrossIndex;
RfPlotDialog.this.selectedCrossIndex = crossListCombobox.getSelectedIndex();
if (oldCrossIndex != RfPlotDialog.this.selectedCrossIndex) {
RfPlotDialog.this.newChrTable = true;
setCurrentPane(makeContentPane());
}
}
});
JPanel result = new JPanel();
result.add(crossListCombobox);
result.setBorder(BorderFactory.createTitledBorder(" Choose cross "));
return result;
}
private JPanel makeParameterSelectionPane() {
JLabel maxitLable = new JLabel(MAXIT_LABEL);
JLabel tolLabel = new JLabel(TOL_LABEL);
this.tfMaxit = new JTextField(this.selectedMaxit + "");
this.tfMaxit.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
try {
RfPlotDialog.this.selectedMaxit = Integer.parseInt(RfPlotDialog.this.tfMaxit.getText());
}
catch (NumberFormatException ee) {
}
}
public void insertUpdate(DocumentEvent e) {
try {
RfPlotDialog.this.selectedMaxit = Integer.parseInt(RfPlotDialog.this.tfMaxit.getText());
}
catch (NumberFormatException ee) {
}
}
public void removeUpdate(DocumentEvent e) {
try {
RfPlotDialog.this.selectedMaxit = Integer.parseInt(RfPlotDialog.this.tfMaxit.getText());
}
catch (NumberFormatException ee) {
}
}
});
this.tfMaxit.setPreferredSize(new Dimension(TEXT_FIELD_WIDTH, (int) this.tfMaxit.getPreferredSize().getHeight()));
this.tfTol = new JTextField(this.selectedTol);
this.tfTol.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {}
public void insertUpdate(DocumentEvent e) {
try {
RfPlotDialog.this.selectedTol = RfPlotDialog.this.tfTol.getText();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
public void removeUpdate(DocumentEvent e) {}
});
this.tfTol.setPreferredSize(new Dimension(TEXT_FIELD_WIDTH, (int) this.tfTol.getPreferredSize().getHeight()));
JPanel result = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
int line = 1;
result.add(maxitLable, Tools.setGbc(c, 1, line, 1, 1));
result.add(this.tfMaxit, Tools.setGbc(c, 2, line++, 1, 1));
result.add(tolLabel, Tools.setGbc(c, 1, line, 1, 1));
result.add(this.tfTol, Tools.setGbc(c, 2, line++, 1, 1));
result.setBorder(BorderFactory.createTitledBorder(" Parameters for estimate recombination fraction "));
return result;
}
private JPanel makeChromosomeSelectionPane() {
final Cross selectedCross =
RfPlotDialog.this.crosses[this.selectedCrossIndex];
if (this.newChrTable) {
List<CrossChromosome> genoData = selectedCross.getGenotypeData();
String[] chromosomeNames = new String[genoData.size()];
for(int i = 0; i < chromosomeNames.length; i++)
{
chromosomeNames[i] = genoData.get(i).getChromosomeName();
}
this.tbChr = new ListSelectionTable(chromosomeNames, "Chromosomes", true, this);
this.selectedChrIndexes = this.tbChr.getSelections();
this.newChrTable = false;
}
this.tbChr.getModel().addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
RfPlotDialog.this.selectedChrIndexes = RfPlotDialog.this.tbChr.getSelections();
if (RfPlotDialog.this.selectedChrIndexes.length == 0) RfPlotDialog.this.selectedChrIndexes = new int[] {0};
RfPlotDialog.this.tbChr.setDefaultSelection(RfPlotDialog.this.selectedChrIndexes);
setCurrentPane(makeContentPane());
}
});
JScrollPane holder = new JScrollPane(this.tbChr);
holder.setPreferredSize(new Dimension( (int) holder.getPreferredSize().getWidth() / 2, (int) holder.getPreferredSize().getHeight() / 4));
JPanel result = new JPanel();
result.add(holder);
result.setBorder(BorderFactory.createTitledBorder(" Choose chromosome to plot recombination fraction "));
return result;
}
}