// $Id: PhyloInferenceDialog.java,v 1.7 2010/10/13 21:12:18 cmzmasek Exp $
// forester -- software libraries and applications
// for genomics and evolutionary biology research.
//
// Copyright (C) 2010 Christian M Zmasek
// Copyright (C) 2010 Sanford-Burnham Medical Research Institute
// All rights reserved
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
//
// Contact: cmzmasek@yahoo.com
// WWW: www.phylosoft.org/forester
package org.forester.archaeopteryx;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import org.forester.evoinference.distance.PairwiseDistanceCalculator.PWD_DISTANCE_METHOD;
import org.forester.sequence.Sequence;
import org.forester.util.BasicDescriptiveStatistics;
import org.forester.util.DescriptiveStatistics;
import org.forester.util.ForesterUtil;
public class PhyloInferenceDialog extends JDialog implements ActionListener {
private static final long serialVersionUID = 8337543508238133614L;
private final JPanel _pnl;
private final JButton _launch_btn;
private final JFormattedTextField _bootstrap_tf;
private final JCheckBox _bootstrap_cb;
private final PhylogeneticInferenceOptions _opts;
private JTextField _input_msa_file_tf;
private JButton _select_input_msa_btn;
private final MainFrameApplication _parent_frame;
private JTextField _msa_length_tf;
private JTextField _msa_size_tf;
private JTextField _msa_type_tf;
private final JRadioButton _distance_calc_kimura_rb;
private final JRadioButton _distance_calc_poisson_rb;
private final JRadioButton _distance_calc_fract_dissimilarity_rb;
private int _value = JOptionPane.CANCEL_OPTION;
private JTextField _input_seqs_tf;
private JButton _select_input_seqs_btn;
private JTextField _input_seqs_number_tf;
private JTextField _input_seqs_median_length_tf;
private JTextField _input_seqs_min_length_tf;
private JTextField _input_seqs_max_length_tf;
private JTextField _input_seqs_type_tf;
public PhyloInferenceDialog( final MainFrameApplication frame,
final PhylogeneticInferenceOptions options,
final boolean from_unaligned_seqs ) {
super( frame, true );
setVisible( false );
_parent_frame = frame;
_opts = options;
_pnl = new JPanel();
getContentPane().add( _pnl );
final BoxLayout box_layout = new BoxLayout( _pnl, BoxLayout.PAGE_AXIS );
_pnl.setLayout( box_layout );
if ( from_unaligned_seqs ) {
setTitle( "Phylogenetic Inference (including multiple sequence alignment)" );
final JPanel inputfile_pnl_1 = new JPanel();
final JPanel inputfile_pnl_2 = new JPanel();
inputfile_pnl_1.setLayout( new FlowLayout() );
inputfile_pnl_2.setLayout( new FlowLayout() );
inputfile_pnl_1.add( new JLabel( "Input Sequence File:" ) );
inputfile_pnl_1.add( _input_seqs_tf = new JTextField() );
inputfile_pnl_1.add( _select_input_seqs_btn = new JButton( "Select Input File" ) );
inputfile_pnl_2.add( new JLabel( "Sequences: " ) );
inputfile_pnl_2.add( new JLabel( "Number of Sequences:" ) );
inputfile_pnl_2.add( _input_seqs_number_tf = new JTextField() );
inputfile_pnl_2.add( new JLabel( "Length: median:" ) );
inputfile_pnl_2.add( _input_seqs_median_length_tf = new JTextField() );
inputfile_pnl_2.add( new JLabel( "min:" ) );
inputfile_pnl_2.add( _input_seqs_min_length_tf = new JTextField() );
inputfile_pnl_2.add( new JLabel( "max:" ) );
inputfile_pnl_2.add( _input_seqs_max_length_tf = new JTextField() );
inputfile_pnl_2.add( new JLabel( "Type:" ) );
inputfile_pnl_2.add( _input_seqs_type_tf = new JTextField() );
_input_seqs_median_length_tf.setColumns( 4 );
_input_seqs_min_length_tf.setColumns( 4 );
_input_seqs_max_length_tf.setColumns( 4 );
_input_seqs_number_tf.setColumns( 4 );
_input_seqs_type_tf.setColumns( 2 );
_input_seqs_tf.setColumns( 20 );
_input_seqs_tf.setEditable( false );
_input_seqs_median_length_tf.setEditable( false );
_input_seqs_min_length_tf.setEditable( false );
_input_seqs_max_length_tf.setEditable( false );
_input_seqs_number_tf.setEditable( false );
_input_seqs_type_tf.setEditable( false );
_select_input_seqs_btn.addActionListener( this );
_pnl.add( inputfile_pnl_1 );
_pnl.add( inputfile_pnl_2 );
}
else {
setTitle( "Phylogenetic Inference (from already aligned sequences) " );
// Inputfile (MSA):
final JPanel inputfile_pnl_1 = new JPanel();
final JPanel inputfile_pnl_2 = new JPanel();
inputfile_pnl_1.setLayout( new FlowLayout() );
inputfile_pnl_2.setLayout( new FlowLayout() );
inputfile_pnl_1.add( new JLabel( "Input MSA File:" ) );
inputfile_pnl_1.add( _input_msa_file_tf = new JTextField() );
inputfile_pnl_1.add( _select_input_msa_btn = new JButton( "Select Input File" ) );
inputfile_pnl_2.add( new JLabel( "MSA: " ) );
inputfile_pnl_2.add( new JLabel( "Number of Sequences:" ) );
inputfile_pnl_2.add( _msa_size_tf = new JTextField() );
inputfile_pnl_2.add( new JLabel( "Length:" ) );
inputfile_pnl_2.add( _msa_length_tf = new JTextField() );
inputfile_pnl_2.add( new JLabel( "Type:" ) );
inputfile_pnl_2.add( _msa_type_tf = new JTextField() );
_msa_length_tf.setColumns( 4 );
_msa_size_tf.setColumns( 4 );
_msa_type_tf.setColumns( 2 );
_input_msa_file_tf.setColumns( 20 );
_input_msa_file_tf.setEditable( false );
_msa_length_tf.setEditable( false );
_msa_size_tf.setEditable( false );
_msa_type_tf.setEditable( false );
_select_input_msa_btn.addActionListener( this );
_pnl.add( inputfile_pnl_1 );
_pnl.add( inputfile_pnl_2 );
}
// Distance calculation:
//TODO if type==AA...
final JPanel distance_calc_pnl_1 = new JPanel();
distance_calc_pnl_1.setLayout( new FlowLayout() );
distance_calc_pnl_1.add( new JLabel( "Distance calculation:" ) );
distance_calc_pnl_1.add( _distance_calc_kimura_rb = new JRadioButton( "Kimura correction" ) );
distance_calc_pnl_1.add( _distance_calc_poisson_rb = new JRadioButton( "Poisson" ) );
distance_calc_pnl_1
.add( _distance_calc_fract_dissimilarity_rb = new JRadioButton( "Fractional dissimilarity" ) );
final ButtonGroup distance_calc_group_1 = new ButtonGroup();
distance_calc_group_1.add( _distance_calc_kimura_rb );
distance_calc_group_1.add( _distance_calc_poisson_rb );
distance_calc_group_1.add( _distance_calc_fract_dissimilarity_rb );
_pnl.add( distance_calc_pnl_1 );
// Bootstrap resampling:
final JPanel bootstrap_pnl = new JPanel();
bootstrap_pnl.setLayout( new FlowLayout() );
bootstrap_pnl.add( _bootstrap_cb = new JCheckBox( "Perform Bootstrap Resampling" ) );
bootstrap_pnl.add( new JLabel( "Number of Bootstrap Samples:" ) );
bootstrap_pnl.add( _bootstrap_tf = new JFormattedTextField( Util.createMaskFormatter( "###" ) ) );
// TODO see http://download.oracle.com/javase/tutorial/uiswing/components/formattedtextfield.html
//_bootstrap_tf.setColumns( 4 );
_pnl.add( bootstrap_pnl );
_launch_btn = new JButton( "Go!" );
_launch_btn.addActionListener( this );
_pnl.add( _launch_btn );
initializeValues( from_unaligned_seqs );
pack();
setLocationRelativeTo( getParentFrame() );
setResizable( false );
}
public void actionPerformed( final ActionEvent e ) {
if ( e.getSource() == _select_input_msa_btn ) {
readInputFile();
}
else if ( e.getSource() == _select_input_seqs_btn ) {
readInputSeqsFile();
}
else if ( e.getSource() == _launch_btn ) {
launch();
}
}
public void activate() {
setVisible( true );
}
private MainFrameApplication getParentFrame() {
return _parent_frame;
}
public PhylogeneticInferenceOptions getPhylogeneticInferenceOptions() {
return _opts;
}
public int getValue() {
return _value;
}
private void initializeValues(boolean from_unaligned_seqs) {
_value = JOptionPane.CANCEL_OPTION;
if ( from_unaligned_seqs) {
updateSeqsItems();
}
else {
updateMsaItems();
}
updateDistanceCalcMethod();
_bootstrap_tf.setText( getPhylogeneticInferenceOptions().getBootstrapSamples() + "" );
}
private void launch() {
processPerformBootstrapResampling();
if ( _bootstrap_cb.isSelected() ) {
processBootstrapSamplesNumber();
}
processDistanceCalcMethod();
setVisible( false );
_value = JOptionPane.OK_OPTION;
}
private void processBootstrapSamplesNumber() {
int bootstrap_samples = 0;
try {
bootstrap_samples = Integer.parseInt( _bootstrap_tf.getText() );
}
catch ( final NumberFormatException e ) {
bootstrap_samples = 0;
}
if ( bootstrap_samples >= 0 ) {
getPhylogeneticInferenceOptions().setBootstrapSamples( bootstrap_samples );
}
}
private void processDistanceCalcMethod() {
if ( ( _distance_calc_kimura_rb != null ) && _distance_calc_kimura_rb.isSelected() ) {
getPhylogeneticInferenceOptions().setPwdDistanceMethod( PWD_DISTANCE_METHOD.KIMURA_DISTANCE );
}
else if ( ( _distance_calc_poisson_rb != null ) && _distance_calc_poisson_rb.isSelected() ) {
getPhylogeneticInferenceOptions().setPwdDistanceMethod( PWD_DISTANCE_METHOD.POISSON_DISTANCE );
}
else if ( ( _distance_calc_fract_dissimilarity_rb != null )
&& _distance_calc_fract_dissimilarity_rb.isSelected() ) {
getPhylogeneticInferenceOptions().setPwdDistanceMethod( PWD_DISTANCE_METHOD.FRACTIONAL_DISSIMILARITY );
}
}
private void processPerformBootstrapResampling() {
getPhylogeneticInferenceOptions().setPerformBootstrapResampling( _bootstrap_cb.isSelected() );
}
private void readInputFile() {
getParentFrame().readMsaFromFile();
updateMsaItems();
}
private void readInputSeqsFile() {
getParentFrame().readSeqsFromFile();
updateSeqsItems();
}
private void updateDistanceCalcMethod() {
switch ( getPhylogeneticInferenceOptions().getPwdDistanceMethod() ) {
case KIMURA_DISTANCE:
_distance_calc_kimura_rb.setSelected( true );
break;
case POISSON_DISTANCE:
_distance_calc_poisson_rb.setSelected( true );
break;
case FRACTIONAL_DISSIMILARITY:
_distance_calc_fract_dissimilarity_rb.setSelected( true );
break;
default:
throw new IllegalStateException( "invalid distance calc method" );
}
}
private void updateMsaItems() {
if ( getParentFrame().getMsa() != null ) {
_input_msa_file_tf.setText( getParentFrame().getMsaFile().toString() );
_msa_length_tf.setText( getParentFrame().getMsa().getLength() + "" );
_msa_size_tf.setText( getParentFrame().getMsa().getNumberOfSequences() + "" );
_msa_type_tf.setText( getParentFrame().getMsa().getType() + "" );
_input_msa_file_tf.setEnabled( true );
_msa_length_tf.setEnabled( true );
_msa_size_tf.setEnabled( true );
_msa_type_tf.setEnabled( true );
_launch_btn.setEnabled( true );
}
else {
_input_msa_file_tf.setText( "" );
_msa_length_tf.setText( "" );
_msa_size_tf.setText( "" );
_msa_type_tf.setText( "" );
_input_msa_file_tf.setEnabled( false );
_msa_length_tf.setEnabled( false );
_msa_size_tf.setEnabled( false );
_msa_type_tf.setEnabled( false );
_launch_btn.setEnabled( false );
}
}
private void updateSeqsItems() {
if ( getParentFrame().getSeqs() != null ) {
final DescriptiveStatistics stats = calcSequenceStats( getParentFrame().getSeqs() );
_input_seqs_tf.setText( getParentFrame().getSeqsFile().toString() );
_input_seqs_median_length_tf.setText( (int) stats.median() + "" );
_input_seqs_min_length_tf.setText( (int) stats.getMin() + "" );
_input_seqs_max_length_tf.setText( (int) stats.getMax() + "" );
_input_seqs_number_tf.setText( getParentFrame().getSeqs().size() + "" );
_input_seqs_type_tf.setText( getParentFrame().getSeqs().get( 0 ).getType() + "" );
_input_seqs_tf.setEnabled( true );
_input_seqs_median_length_tf.setEnabled( true );
_input_seqs_min_length_tf.setEnabled( true );
_input_seqs_max_length_tf.setEnabled( true );
_input_seqs_number_tf.setEnabled( true );
_input_seqs_type_tf.setEnabled( true );
_launch_btn.setEnabled( true );
}
else {
_input_seqs_tf.setText( "" );
_input_seqs_median_length_tf.setText( "" );
_input_seqs_min_length_tf.setText( "" );
_input_seqs_max_length_tf.setText( "" );
_input_seqs_number_tf.setText( "" );
_input_seqs_type_tf.setText( "" );
_input_seqs_tf.setEnabled( false );
_input_seqs_median_length_tf.setEnabled( false );
_input_seqs_min_length_tf.setEnabled( false );
_input_seqs_max_length_tf.setEnabled( false );
_input_seqs_number_tf.setEnabled( false );
_input_seqs_type_tf.setEnabled( false );
_launch_btn.setEnabled( false );
}
}
DescriptiveStatistics calcSequenceStats( List<Sequence> seqs ) {
DescriptiveStatistics stats = new BasicDescriptiveStatistics();
for( Sequence s : seqs ) {
stats.addValue( s.getLength() );
}
return stats;
}
}