2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
5 // Copyright (C) 2008-2009 Christian M. Zmasek
6 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
7 // Copyright (C) 2003-2007 Ethalinda K.S. Cannon
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 // Contact: phylosoft @ gmail . com
25 // WWW: https://sites.google.com/site/cmzmasek/home/software/forester
27 package org.forester.archaeopteryx;
29 import java.awt.BorderLayout;
31 import java.awt.event.ActionEvent;
32 import java.awt.event.ComponentAdapter;
33 import java.awt.event.ComponentEvent;
34 import java.awt.event.WindowAdapter;
35 import java.awt.event.WindowEvent;
37 import java.io.FileInputStream;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.net.MalformedURLException;
42 import java.util.ArrayList;
43 import java.util.HashSet;
44 import java.util.List;
47 import javax.swing.ButtonGroup;
48 import javax.swing.JCheckBoxMenuItem;
49 import javax.swing.JFileChooser;
50 import javax.swing.JMenu;
51 import javax.swing.JMenuBar;
52 import javax.swing.JMenuItem;
53 import javax.swing.JOptionPane;
54 import javax.swing.JRadioButtonMenuItem;
55 import javax.swing.UIManager;
56 import javax.swing.UnsupportedLookAndFeelException;
57 import javax.swing.WindowConstants;
58 import javax.swing.event.ChangeEvent;
59 import javax.swing.event.ChangeListener;
60 import javax.swing.event.InternalFrameAdapter;
61 import javax.swing.event.InternalFrameEvent;
63 import org.forester.analysis.TaxonomyDataManager;
64 import org.forester.archaeopteryx.Options.CLADOGRAM_TYPE;
65 import org.forester.archaeopteryx.Options.NODE_LABEL_DIRECTION;
66 import org.forester.archaeopteryx.Options.PHYLOGENY_GRAPHICS_TYPE;
67 import org.forester.archaeopteryx.tools.InferenceManager;
68 import org.forester.archaeopteryx.tools.PhyloInferenceDialog;
69 import org.forester.archaeopteryx.tools.PhylogeneticInferenceOptions;
70 import org.forester.archaeopteryx.tools.PhylogeneticInferrer;
71 import org.forester.archaeopteryx.tools.SequenceDataRetriver;
72 import org.forester.archaeopteryx.webservices.PhylogeniesWebserviceClient;
73 import org.forester.archaeopteryx.webservices.WebservicesManager;
74 import org.forester.io.parsers.FastaParser;
75 import org.forester.io.parsers.GeneralMsaParser;
76 import org.forester.io.parsers.PhylogenyParser;
77 import org.forester.io.parsers.nexus.NexusPhylogeniesParser;
78 import org.forester.io.parsers.nhx.NHXParser;
79 import org.forester.io.parsers.nhx.NHXParser.TAXONOMY_EXTRACTION;
80 import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
81 import org.forester.io.parsers.phyloxml.PhyloXmlParser;
82 import org.forester.io.parsers.tol.TolParser;
83 import org.forester.io.parsers.util.ParserUtils;
84 import org.forester.io.writers.SequenceWriter;
85 import org.forester.msa.Msa;
86 import org.forester.msa.MsaFormatException;
87 import org.forester.phylogeny.Phylogeny;
88 import org.forester.phylogeny.PhylogenyMethods;
89 import org.forester.phylogeny.PhylogenyNode;
90 import org.forester.phylogeny.PhylogenyNode.NH_CONVERSION_SUPPORT_VALUE_STYLE;
91 import org.forester.phylogeny.data.Confidence;
92 import org.forester.phylogeny.data.PhylogenyDataUtil;
93 import org.forester.phylogeny.data.Sequence;
94 import org.forester.phylogeny.data.Taxonomy;
95 import org.forester.phylogeny.factories.ParserBasedPhylogenyFactory;
96 import org.forester.phylogeny.factories.PhylogenyFactory;
97 import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
98 import org.forester.sequence.MolecularSequence;
99 import org.forester.util.BasicDescriptiveStatistics;
100 import org.forester.util.BasicTable;
101 import org.forester.util.BasicTableParser;
102 import org.forester.util.DescriptiveStatistics;
103 import org.forester.util.ForesterUtil;
105 public final class MainFrameApplication extends MainFrame {
107 private final static int FRAME_X_SIZE = 900;
108 private final static int FRAME_Y_SIZE = 900;
109 // Filters for the file-open dialog (classes defined in this file)
110 private static final long serialVersionUID = -799735726778865234L;
111 private static final boolean PREPROCESS_TREES = false;
112 private final JFileChooser _values_filechooser;
113 private final JFileChooser _sequences_filechooser;
114 private final JFileChooser _open_filechooser;
115 private final JFileChooser _msa_filechooser;
116 private final JFileChooser _seqs_pi_filechooser;
117 private final JFileChooser _open_filechooser_for_species_tree;
118 // Application-only print menu items
119 private JMenuItem _collapse_below_threshold;
120 private JMenuItem _collapse_below_branch_length;
121 private ButtonGroup _radio_group_1;
122 private ButtonGroup _radio_group_2;
124 double _min_not_collapse = AptxConstants.MIN_NOT_COLLAPSE_DEFAULT;
125 double _min_not_collapse_bl = 0.001;
126 // Phylogeny Inference menu
127 private JMenu _inference_menu;
128 private JMenuItem _inference_from_msa_item;
129 private JMenuItem _inference_from_seqs_item;
130 // Phylogeny Inference
131 private PhylogeneticInferenceOptions _phylogenetic_inference_options = null;
132 private Msa _msa = null;
133 private File _msa_file = null;
134 private List<MolecularSequence> _seqs = null;
135 private File _seqs_file = null;
136 JMenuItem _read_values_jmi;
137 JMenuItem _read_seqs_jmi;
139 private MainFrameApplication( final Phylogeny[] phys, final Configuration config ) {
140 _configuration = config;
141 if ( _configuration == null ) {
142 throw new IllegalArgumentException( "configuration is null" );
145 setOptions( Options.createInstance( _configuration ) );
146 _mainpanel = new MainPanel( _configuration, this );
147 _open_filechooser = null;
148 _open_filechooser_for_species_tree = null;
149 _save_filechooser = null;
150 _writetopdf_filechooser = null;
151 _writetographics_filechooser = null;
152 _msa_filechooser = null;
153 _seqs_pi_filechooser = null;
154 _values_filechooser = null;
155 _sequences_filechooser = null;
156 _jmenubar = new JMenuBar();
159 _contentpane = getContentPane();
160 _contentpane.setLayout( new BorderLayout() );
161 _contentpane.add( _mainpanel, BorderLayout.CENTER );
163 setSize( MainFrameApplication.FRAME_X_SIZE, MainFrameApplication.FRAME_Y_SIZE );
164 // The window listener
165 setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE );
166 addFrameListener( new FrameAdapter() {
169 public void FrameClosing () {
174 // setVisible( true );
175 if ( ( phys != null ) && ( phys.length > 0 ) ) {
176 AptxUtil.addPhylogeniesToTabs( phys, "", null, _configuration, _mainpanel );
178 getMainPanel().getControlPanel().showWholeAll();
179 getMainPanel().getControlPanel().showWhole();
181 //activateSaveAllIfNeeded();
182 // ...and its children
183 _contentpane.repaint();
188 private MainFrameApplication( final Phylogeny[] phys, final Configuration config, final String title ) {
189 this( phys, config, title, null );
192 private MainFrameApplication( final Phylogeny[] phys,
193 final Configuration config,
195 final File current_dir ) {
197 _configuration = config;
198 if ( _configuration == null ) {
199 throw new IllegalArgumentException( "configuration is null" );
202 if ( _configuration.isUseNativeUI() ) {
203 UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
206 UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName() );
209 catch ( final UnsupportedLookAndFeelException e ) {
210 AptxUtil.dieWithSystemError( "unsupported look and feel: " + e.toString() );
212 catch ( final ClassNotFoundException e ) {
213 AptxUtil.dieWithSystemError( "class not found exception: " + e.toString() );
215 catch ( final InstantiationException e ) {
216 AptxUtil.dieWithSystemError( "instantiation exception: " + e.toString() );
218 catch ( final IllegalAccessException e ) {
219 AptxUtil.dieWithSystemError( "illegal access exception: " + e.toString() );
221 if ( ( current_dir != null ) && current_dir.canRead() && current_dir.isDirectory() ) {
222 setCurrentDir( current_dir );
224 // hide until everything is ready
226 setOptions( Options.createInstance( _configuration ) );
227 setInferenceManager( InferenceManager.createInstance( _configuration ) );
228 setPhylogeneticInferenceOptions( PhylogeneticInferenceOptions.createInstance( _configuration ) );
230 setTitle( AptxConstants.PRG_NAME + " " + AptxConstants.VERSION + " (" + AptxConstants.PRG_DATE + ")" );
231 _mainpanel = new MainPanel( _configuration, this );
233 _open_filechooser = new JFileChooser();
234 _open_filechooser.setMultiSelectionEnabled( true );
235 _open_filechooser.addChoosableFileFilter( MainFrame.xmlfilter );
236 _open_filechooser.addChoosableFileFilter( MainFrame.nhxfilter );
237 _open_filechooser.addChoosableFileFilter( MainFrame.nhfilter );
238 _open_filechooser.addChoosableFileFilter( MainFrame.nexusfilter );
239 _open_filechooser.addChoosableFileFilter( MainFrame.tolfilter );
240 _open_filechooser.addChoosableFileFilter( _open_filechooser.getAcceptAllFileFilter() );
241 _open_filechooser.setFileFilter( MainFrame.defaultfilter );
242 _open_filechooser_for_species_tree = new JFileChooser();
243 _open_filechooser_for_species_tree.setMultiSelectionEnabled( false );
244 _open_filechooser_for_species_tree.addChoosableFileFilter( MainFrame.xmlfilter );
245 _open_filechooser_for_species_tree.addChoosableFileFilter( MainFrame.tolfilter );
246 _open_filechooser_for_species_tree.setFileFilter( MainFrame.xmlfilter );
248 _msa_filechooser = new JFileChooser();
249 _msa_filechooser.setName( "Read Multiple Sequence Alignment File" );
250 _msa_filechooser.setMultiSelectionEnabled( false );
251 _msa_filechooser.addChoosableFileFilter( _msa_filechooser.getAcceptAllFileFilter() );
252 _msa_filechooser.addChoosableFileFilter( MainFrame.msafilter );
254 _seqs_pi_filechooser = new JFileChooser();
255 _seqs_pi_filechooser.setName( "Read Sequences File" );
256 _seqs_pi_filechooser.setMultiSelectionEnabled( false );
257 _seqs_pi_filechooser.addChoosableFileFilter( _seqs_pi_filechooser.getAcceptAllFileFilter() );
258 _seqs_pi_filechooser.addChoosableFileFilter( MainFrame.seqsfilter );
260 _values_filechooser = new JFileChooser();
261 _values_filechooser.setMultiSelectionEnabled( false );
263 _sequences_filechooser = new JFileChooser();
264 _sequences_filechooser.setMultiSelectionEnabled( false );
266 final String home_dir = System.getProperty( "user.home" );
267 _open_filechooser.setCurrentDirectory( new File( home_dir ) );
268 _open_filechooser_for_species_tree.setCurrentDirectory( new File( home_dir ) );
269 _msa_filechooser.setCurrentDirectory( new File( home_dir ) );
270 _seqs_pi_filechooser.setCurrentDirectory( new File( home_dir ) );
271 _values_filechooser.setCurrentDirectory( new File( home_dir ) );
272 _sequences_filechooser.setCurrentDirectory( new File( home_dir ) );
274 catch ( final Exception e ) {
276 // Do nothing. Not important.
278 // build the menu bar
279 _jmenubar = new JMenuBar();
280 if ( !_configuration.isUseNativeUI() ) {
281 _jmenubar.setBackground( getConfiguration().getGuiMenuBackgroundColor() );
284 if ( AptxConstants.__ALLOW_PHYLOGENETIC_INFERENCE ) {
285 buildPhylogeneticInferenceMenu();
294 setJMenuBar( _jmenubar );
295 _jmenubar.add( _help_jmenu );
296 _contentpane = getContentPane();
297 _contentpane.setLayout( new BorderLayout() );
298 _contentpane.add( _mainpanel, BorderLayout.CENTER );
300 setSize( MainFrameApplication.FRAME_X_SIZE, MainFrameApplication.FRAME_Y_SIZE );
301 // addWindowFocusListener( new WindowAdapter() {
304 // public void windowGainedFocus( WindowEvent e ) {
305 // requestFocusInWindow();
308 // The window listener
309 setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE );
311 addFrameListener( new FrameAdapter() {
314 public void FrameClosing( ) {
315 if (MainFrameApplication.this.getParent() == null) {
316 if ( isUnsavedDataPresent() ) {
317 final int r = JOptionPane.showConfirmDialog( _mainpanel,
318 "Close Archaeopteryx despite potentially unsaved changes?",
320 JOptionPane.YES_NO_OPTION );
321 if ( r != JOptionPane.YES_OPTION ) {
326 final int r = JOptionPane
327 .showConfirmDialog( null, "Exit Archaeopteryx?", "Exit?", JOptionPane.YES_NO_OPTION );
328 if ( r != JOptionPane.YES_OPTION ) {
335 // The component listener
336 addComponentListener( new ComponentAdapter() {
339 public void componentResized( final ComponentEvent e ) {
340 if ( _mainpanel.getCurrentTreePanel() != null ) {
341 _mainpanel.getCurrentTreePanel()
342 .calcParametersForPainting( _mainpanel.getCurrentTreePanel().getWidth(),
343 _mainpanel.getCurrentTreePanel().getHeight() );
347 requestFocusInWindow();
348 // addKeyListener( this );
350 if ( ( phys != null ) && ( phys.length > 0 ) ) {
351 AptxUtil.addPhylogeniesToTabs( phys, title, null, _configuration, _mainpanel );
353 getMainPanel().getControlPanel().showWholeAll();
354 getMainPanel().getControlPanel().showWhole();
356 activateSaveAllIfNeeded();
357 // ...and its children
358 _contentpane.repaint();
368 private MainFrameApplication( final Phylogeny[] phys, final String config_file, final String title ) {
369 // Reads the config file (false, false => not url, not applet):
370 this( phys, new Configuration( config_file, false, false, true ), title );
374 public void actionPerformed( final ActionEvent e ) {
376 super.actionPerformed( e );
377 final Object o = e.getSource();
378 // Handle app-specific actions here:
379 if ( o == _open_item ) {
380 readPhylogeniesFromFile();
382 if ( o == _open_url_item ) {
383 readPhylogeniesFromURL();
385 else if ( o == _new_item ) {
388 else if ( o == _close_item ) {
391 else if ( o == _load_species_tree_item ) {
392 readSpeciesTreeFromFile();
394 else if ( o == _obtain_detailed_taxonomic_information_jmi ) {
395 if ( isSubtreeDisplayed() ) {
398 obtainDetailedTaxonomicInformation();
400 else if ( o == _obtain_detailed_taxonomic_information_deleting_jmi ) {
401 if ( isSubtreeDisplayed() ) {
404 obtainDetailedTaxonomicInformationDelete();
406 else if ( o == _obtain_seq_information_jmi ) {
407 obtainSequenceInformation();
409 else if ( o == _read_values_jmi ) {
410 if ( isSubtreeDisplayed() ) {
413 addExpressionValuesFromFile();
415 else if ( o == _read_seqs_jmi ) {
416 if ( isSubtreeDisplayed() ) {
419 addSequencesFromFile();
421 else if ( o == _move_node_names_to_tax_sn_jmi ) {
422 moveNodeNamesToTaxSn();
424 else if ( o == _move_node_names_to_seq_names_jmi ) {
425 moveNodeNamesToSeqNames();
427 else if ( o == _extract_tax_code_from_node_names_jmi ) {
428 extractTaxDataFromNodeNames();
430 else if ( o == _internal_number_are_confidence_for_nh_parsing_cbmi ) {
431 updateOptions( getOptions() );
433 else if ( o == _replace_underscores_cbmi ) {
434 if ( ( _extract_taxonomy_no_rbmi != null ) && !_extract_taxonomy_no_rbmi.isSelected() ) {
435 _extract_taxonomy_no_rbmi.setSelected( true );
437 updateOptions( getOptions() );
439 else if ( o == _allow_errors_in_distance_to_parent_cbmi ) {
440 updateOptions( getOptions() );
442 else if ( o == _collapse_below_threshold ) {
443 if ( isSubtreeDisplayed() ) {
446 collapseBelowThreshold();
449 else if ( o == _collapse_below_branch_length ) {
450 if ( isSubtreeDisplayed() ) {
453 collapseBelowBranchLengthThreshold();
455 else if ( ( o == _extract_taxonomy_pfam_strict_rbmi ) || ( o == _extract_taxonomy_pfam_relaxed_rbmi )
456 || ( o == _extract_taxonomy_agressive_rbmi ) ) {
457 if ( _replace_underscores_cbmi != null ) {
458 _replace_underscores_cbmi.setSelected( false );
460 updateOptions( getOptions() );
462 else if ( o == _extract_taxonomy_no_rbmi ) {
463 updateOptions( getOptions() );
465 else if ( o == _inference_from_msa_item ) {
466 executePhyleneticInference( false );
468 else if ( o == _inference_from_seqs_item ) {
469 executePhyleneticInference( true );
471 _contentpane.repaint();
473 catch ( final Exception ex ) {
474 AptxUtil.unexpectedException( ex );
476 catch ( final Error err ) {
477 AptxUtil.unexpectedError( err );
482 _mainpanel.terminate();
483 _contentpane.removeAll();
489 public MainPanel getMainPanel() {
493 public Msa getMsa() {
497 public File getMsaFile() {
501 public List<MolecularSequence> getSeqs() {
505 public File getSeqsFile() {
509 public void readMsaFromFile() {
510 // Set an initial directory if none set yet
511 final File my_dir = getCurrentDir();
512 _msa_filechooser.setMultiSelectionEnabled( false );
513 // Open file-open dialog and set current directory
514 if ( my_dir != null ) {
515 _msa_filechooser.setCurrentDirectory( my_dir );
517 final int result = _msa_filechooser.showOpenDialog( _contentpane );
518 // All done: get the msa
519 final File file = _msa_filechooser.getSelectedFile();
520 setCurrentDir( _msa_filechooser.getCurrentDirectory() );
521 if ( ( file != null ) && !file.isDirectory() && ( result == JFileChooser.APPROVE_OPTION ) ) {
526 final InputStream is = new FileInputStream( file );
527 if ( FastaParser.isLikelyFasta( file ) ) {
528 msa = FastaParser.parseMsa( is );
531 msa = GeneralMsaParser.parseMsa( is );
534 catch ( final MsaFormatException e ) {
536 JOptionPane.showMessageDialog( getThisFrame(),
537 e.getLocalizedMessage(),
538 "Multiple sequence alignment format error",
539 JOptionPane.ERROR_MESSAGE );
542 catch ( final IOException e ) {
544 JOptionPane.showMessageDialog( getThisFrame(),
545 e.getLocalizedMessage(),
546 "Failed to read multiple sequence alignment",
547 JOptionPane.ERROR_MESSAGE );
550 catch ( final IllegalArgumentException e ) {
552 JOptionPane.showMessageDialog( getThisFrame(),
553 e.getLocalizedMessage(),
554 "Unexpected error during reading of multiple sequence alignment",
555 JOptionPane.ERROR_MESSAGE );
558 catch ( final Exception e ) {
561 JOptionPane.showMessageDialog( getThisFrame(),
562 e.getLocalizedMessage(),
563 "Unexpected error during reading of multiple sequence alignment",
564 JOptionPane.ERROR_MESSAGE );
567 if ( ( msa == null ) || ( msa.getNumberOfSequences() < 1 ) ) {
568 JOptionPane.showMessageDialog( getThisFrame(),
569 "Multiple sequence alignment is empty",
570 "Illegal Multiple Sequence Alignment",
571 JOptionPane.ERROR_MESSAGE );
574 if ( msa.getNumberOfSequences() < 4 ) {
575 JOptionPane.showMessageDialog( getThisFrame(),
576 "Multiple sequence alignment needs to contain at least 3 sequences",
577 "Illegal multiple sequence alignment",
578 JOptionPane.ERROR_MESSAGE );
581 if ( msa.getLength() < 2 ) {
582 JOptionPane.showMessageDialog( getThisFrame(),
583 "Multiple sequence alignment needs to contain at least 2 residues",
584 "Illegal multiple sequence alignment",
585 JOptionPane.ERROR_MESSAGE );
589 setMsaFile( _msa_filechooser.getSelectedFile() );
594 public void readSeqsFromFileforPI() {
595 // Set an initial directory if none set yet
596 final File my_dir = getCurrentDir();
597 _seqs_pi_filechooser.setMultiSelectionEnabled( false );
598 // Open file-open dialog and set current directory
599 if ( my_dir != null ) {
600 _seqs_pi_filechooser.setCurrentDirectory( my_dir );
602 final int result = _seqs_pi_filechooser.showOpenDialog( _contentpane );
603 // All done: get the seqs
604 final File file = _seqs_pi_filechooser.getSelectedFile();
605 setCurrentDir( _seqs_pi_filechooser.getCurrentDirectory() );
606 if ( ( file != null ) && !file.isDirectory() && ( result == JFileChooser.APPROVE_OPTION ) ) {
609 List<MolecularSequence> seqs = null;
611 if ( FastaParser.isLikelyFasta( new FileInputStream( file ) ) ) {
612 seqs = FastaParser.parse( new FileInputStream( file ) );
613 for( final MolecularSequence seq : seqs ) {
614 System.out.println( SequenceWriter.toFasta( seq, 60 ) );
621 catch ( final MsaFormatException e ) {
623 JOptionPane.showMessageDialog( getThisFrame(),
624 e.getLocalizedMessage(),
625 "Multiple sequence file format error",
626 JOptionPane.ERROR_MESSAGE );
629 catch ( final IOException e ) {
631 JOptionPane.showMessageDialog( getThisFrame(),
632 e.getLocalizedMessage(),
633 "Failed to read multiple sequence file",
634 JOptionPane.ERROR_MESSAGE );
637 catch ( final IllegalArgumentException e ) {
639 JOptionPane.showMessageDialog( getThisFrame(),
640 e.getLocalizedMessage(),
641 "Unexpected error during reading of multiple sequence file",
642 JOptionPane.ERROR_MESSAGE );
645 catch ( final Exception e ) {
648 JOptionPane.showMessageDialog( getThisFrame(),
649 e.getLocalizedMessage(),
650 "Unexpected error during reading of multiple sequence file",
651 JOptionPane.ERROR_MESSAGE );
654 if ( ( seqs == null ) || ( seqs.size() < 1 ) ) {
655 JOptionPane.showMessageDialog( getThisFrame(),
656 "Multiple sequence file is empty",
657 "Illegal multiple sequence file",
658 JOptionPane.ERROR_MESSAGE );
661 if ( seqs.size() < 4 ) {
662 JOptionPane.showMessageDialog( getThisFrame(),
663 "Multiple sequence file needs to contain at least 3 sequences",
664 "Illegal multiple sequence file",
665 JOptionPane.ERROR_MESSAGE );
668 // if ( msa.getLength() < 2 ) {
669 // JOptionPane.showMessageDialog( this,
670 // "Multiple sequence alignment needs to contain at least 2 residues",
671 // "Illegal multiple sequence file",
672 // JOptionPane.ERROR_MESSAGE );
676 setSeqsFile( _seqs_pi_filechooser.getSelectedFile() );
681 private void addExpressionValuesFromFile() {
682 if ( ( getCurrentTreePanel() == null ) || ( getCurrentTreePanel().getPhylogeny() == null ) ) {
683 JOptionPane.showMessageDialog( getThisFrame(),
684 "Need to load evolutionary tree first",
685 "Can Not Read Expression Values",
686 JOptionPane.WARNING_MESSAGE );
689 final File my_dir = getCurrentDir();
690 if ( my_dir != null ) {
691 _values_filechooser.setCurrentDirectory( my_dir );
693 final int result = _values_filechooser.showOpenDialog( _contentpane );
694 final File file = _values_filechooser.getSelectedFile();
695 if ( ( file != null ) && ( file.length() > 0 ) && ( result == JFileChooser.APPROVE_OPTION ) ) {
696 BasicTable<String> t = null;
698 t = BasicTableParser.parse( file, '\t' );
699 if ( t.getNumberOfColumns() < 2 ) {
700 t = BasicTableParser.parse( file, ',' );
702 if ( t.getNumberOfColumns() < 2 ) {
703 t = BasicTableParser.parse( file, ' ' );
706 catch ( final IOException e ) {
707 JOptionPane.showMessageDialog( getThisFrame(),
709 "Could Not Read Expression Value Table",
710 JOptionPane.ERROR_MESSAGE );
713 if ( t.getNumberOfColumns() < 2 ) {
714 JOptionPane.showMessageDialog( getThisFrame(),
715 "Table contains " + t.getNumberOfColumns() + " column(s)",
716 "Problem with Expression Value Table",
717 JOptionPane.ERROR_MESSAGE );
720 if ( t.getNumberOfRows() < 1 ) {
721 JOptionPane.showMessageDialog( getThisFrame(),
722 "Table contains zero rows",
723 "Problem with Expression Value Table",
724 JOptionPane.ERROR_MESSAGE );
727 final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
728 if ( t.getNumberOfRows() != phy.getNumberOfExternalNodes() ) {
729 JOptionPane.showMessageDialog( getThisFrame(),
730 "Table contains " + t.getNumberOfRows() + " rows, but tree contains "
731 + phy.getNumberOfExternalNodes() + " external nodes",
733 JOptionPane.WARNING_MESSAGE );
735 final DescriptiveStatistics stats = new BasicDescriptiveStatistics();
737 for( final PhylogenyNodeIterator iter = phy.iteratorPreorder(); iter.hasNext(); ) {
738 final PhylogenyNode node = iter.next();
739 final String node_name = node.getName();
740 if ( !ForesterUtil.isEmpty( node_name ) ) {
743 row = t.findRow( node_name );
745 catch ( final IllegalArgumentException e ) {
746 JOptionPane.showMessageDialog( getThisFrame(),
748 "Error Mapping Node Identifiers to Expression Value Identifiers",
749 JOptionPane.ERROR_MESSAGE );
753 if ( node.isExternal() ) {
758 final List<Double> l = new ArrayList<Double>();
759 for( int col = 1; col < t.getNumberOfColumns(); ++col ) {
762 d = Double.parseDouble( t.getValueAsString( col, row ) );
764 catch ( final NumberFormatException e ) {
765 JOptionPane.showMessageDialog( getThisFrame(),
766 "Could not parse \"" + t.getValueAsString( col, row )
767 + "\" into a decimal value",
768 "Issue with Expression Value Table",
769 JOptionPane.ERROR_MESSAGE );
775 if ( !l.isEmpty() ) {
777 node.getNodeData().setVector( l );
781 if ( not_found > 0 ) {
783 .showMessageDialog( getThisFrame(),
784 "Could not fine expression values for " + not_found + " external node(s)",
786 JOptionPane.WARNING_MESSAGE );
788 getCurrentTreePanel().setStatisticsForExpressionValues( stats );
792 private void addSequencesFromFile() {
793 if ( ( getCurrentTreePanel() == null ) || ( getCurrentTreePanel().getPhylogeny() == null ) ) {
794 JOptionPane.showMessageDialog( getThisFrame(),
795 "Need to load evolutionary tree first",
796 "Can Not Read Sequences",
797 JOptionPane.WARNING_MESSAGE );
800 final File my_dir = getCurrentDir();
801 if ( my_dir != null ) {
802 _sequences_filechooser.setCurrentDirectory( my_dir );
804 final int result = _sequences_filechooser.showOpenDialog( _contentpane );
805 final File file = _sequences_filechooser.getSelectedFile();
806 List<MolecularSequence> seqs = null;
807 if ( ( file != null ) && !file.isDirectory() && ( result == JFileChooser.APPROVE_OPTION ) ) {
809 final FileInputStream fis1 = new FileInputStream( file );
810 if ( FastaParser.isLikelyFasta( fis1 ) ) {
811 final FileInputStream fis2 = new FileInputStream( file );
812 seqs = FastaParser.parse( fis2 );
816 catch ( final Exception e ) {
821 JOptionPane.showMessageDialog( getThisFrame(),
822 "Format does not appear to be Fasta",
823 "Multiple sequence file format error",
824 JOptionPane.ERROR_MESSAGE );
830 catch ( final Exception e ) {
834 catch ( final MsaFormatException e ) {
836 JOptionPane.showMessageDialog( getThisFrame(),
837 e.getLocalizedMessage(),
838 "Multiple sequence file format error",
839 JOptionPane.ERROR_MESSAGE );
842 catch ( final IOException e ) {
844 JOptionPane.showMessageDialog( getThisFrame(),
845 e.getLocalizedMessage(),
846 "Failed to read multiple sequence file",
847 JOptionPane.ERROR_MESSAGE );
850 catch ( final Exception e ) {
853 JOptionPane.showMessageDialog( getThisFrame(),
854 e.getLocalizedMessage(),
855 "Unexpected error during reading of multiple sequence file",
856 JOptionPane.ERROR_MESSAGE );
859 if ( ( seqs == null ) || ( seqs.size() < 1 ) ) {
860 JOptionPane.showMessageDialog( getThisFrame(),
861 "Multiple sequence file is empty",
862 "Empty multiple sequence file",
863 JOptionPane.ERROR_MESSAGE );
868 if ( seqs != null ) {
869 for( final MolecularSequence seq : seqs ) {
870 System.out.println( seq.getIdentifier() );
872 final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
873 int total_counter = 0;
874 int attached_counter = 0;
875 for( final MolecularSequence seq : seqs ) {
877 final String seq_name = seq.getIdentifier();
878 if ( !ForesterUtil.isEmpty( seq_name ) ) {
879 List<PhylogenyNode> nodes = phy.getNodesViaSequenceName( seq_name );
880 if ( nodes.isEmpty() ) {
881 nodes = phy.getNodesViaSequenceSymbol( seq_name );
883 if ( nodes.isEmpty() ) {
884 nodes = phy.getNodesViaGeneName( seq_name );
886 if ( nodes.isEmpty() ) {
887 nodes = phy.getNodes( seq_name );
889 if ( nodes.size() > 1 ) {
890 JOptionPane.showMessageDialog( getThisFrame(),
891 "Sequence name \"" + seq_name + "\" is not unique",
892 "Sequence name not unique",
893 JOptionPane.ERROR_MESSAGE );
897 final String[] a = seq_name.split( "\\s" );
898 if ( nodes.isEmpty() && ( a.length > 1 ) ) {
899 final String seq_name_split = a[ 0 ];
900 nodes = phy.getNodesViaSequenceName( seq_name_split );
901 if ( nodes.isEmpty() ) {
902 nodes = phy.getNodesViaSequenceSymbol( seq_name_split );
904 if ( nodes.isEmpty() ) {
905 nodes = phy.getNodes( seq_name_split );
907 if ( nodes.size() > 1 ) {
908 JOptionPane.showMessageDialog( getThisFrame(),
909 "Split sequence name \"" + seq_name_split
910 + "\" is not unique",
911 "Sequence name not unique",
912 JOptionPane.ERROR_MESSAGE );
917 if ( nodes.size() == 1 ) {
919 final PhylogenyNode n = nodes.get( 0 );
920 if ( !n.getNodeData().isHasSequence() ) {
921 n.getNodeData().addSequence( new org.forester.phylogeny.data.Sequence() );
923 n.getNodeData().getSequence().setMolecularSequence( seq.getMolecularSequenceAsString() );
924 if ( ForesterUtil.isEmpty( n.getNodeData().getSequence().getName() ) ) {
925 n.getNodeData().getSequence().setName( seq_name );
930 if ( attached_counter > 0 ) {
932 int ext_nodes_with_seq = 0;
933 for( final PhylogenyNodeIterator iter = phy.iteratorExternalForward(); iter.hasNext(); ) {
935 final PhylogenyNode n = iter.next();
936 if ( n.getNodeData().isHasSequence()
937 && !ForesterUtil.isEmpty( n.getNodeData().getSequence().getMolecularSequence() ) ) {
938 ++ext_nodes_with_seq;
942 if ( ext_nodes == ext_nodes_with_seq ) {
943 s = "All " + ext_nodes_with_seq + " external nodes now have a molecular sequence attached to them.";
946 s = ext_nodes_with_seq + " out of " + ext_nodes
947 + " external nodes now have a molecular sequence attached to them.";
949 if ( ( attached_counter == total_counter ) && ( ext_nodes == ext_nodes_with_seq ) ) {
950 JOptionPane.showMessageDialog( getThisFrame(),
951 "Attached all " + total_counter + " sequences to tree nodes.\n" + s,
952 "All sequences attached",
953 JOptionPane.INFORMATION_MESSAGE );
956 JOptionPane.showMessageDialog( getThisFrame(),
957 "Attached " + attached_counter + " sequences out of a total of "
958 + total_counter + " sequences.\n" + s,
959 attached_counter + " sequences attached",
960 JOptionPane.WARNING_MESSAGE );
964 JOptionPane.showMessageDialog( getThisFrame(),
965 "No maching tree node for any of the " + total_counter + " sequences",
966 "Could not attach any sequences",
967 JOptionPane.ERROR_MESSAGE );
972 private void closeCurrentPane() {
973 if ( getMainPanel().getCurrentTreePanel() != null ) {
974 if ( getMainPanel().getCurrentTreePanel().isEdited() ) {
975 final int r = JOptionPane.showConfirmDialog( getThisFrame(),
976 "Close tab despite potentially unsaved changes?",
978 JOptionPane.YES_NO_OPTION );
979 if ( r != JOptionPane.YES_OPTION ) {
983 getMainPanel().closeCurrentPane();
984 activateSaveAllIfNeeded();
988 private void collapseBelowThreshold( final Phylogeny phy ) {
989 final PhylogenyNodeIterator it = phy.iteratorPostorder();
990 final List<PhylogenyNode> to_be_removed = new ArrayList<PhylogenyNode>();
991 double min_support = Double.MAX_VALUE;
992 boolean conf_present = false;
993 while ( it.hasNext() ) {
994 final PhylogenyNode n = it.next();
995 if ( !n.isExternal() && !n.isRoot() ) {
996 final List<Confidence> c = n.getBranchData().getConfidences();
997 if ( ( c != null ) && ( c.size() > 0 ) ) {
1000 for( final Confidence confidence : c ) {
1001 if ( confidence.getValue() > max ) {
1002 max = confidence.getValue();
1005 if ( max < getMinNotCollapseConfidenceValue() ) {
1006 to_be_removed.add( n );
1008 if ( max < min_support ) {
1014 if ( conf_present ) {
1015 for( final PhylogenyNode node : to_be_removed ) {
1016 PhylogenyMethods.removeNode( node, phy );
1018 if ( to_be_removed.size() > 0 ) {
1019 phy.externalNodesHaveChanged();
1020 phy.clearHashIdToNodeMap();
1021 phy.recalculateNumberOfExternalDescendants( true );
1022 getCurrentTreePanel().resetNodeIdToDistToLeafMap();
1023 getCurrentTreePanel().updateSetOfCollapsedExternalNodes();
1024 getCurrentTreePanel().calculateLongestExtNodeInfo();
1025 getCurrentTreePanel().setNodeInPreorderToNull();
1026 getCurrentTreePanel().recalculateMaxDistanceToRoot();
1027 getCurrentTreePanel().resetPreferredSize();
1028 getCurrentTreePanel().setEdited( true );
1029 getCurrentTreePanel().repaint();
1032 if ( to_be_removed.size() > 0 ) {
1033 JOptionPane.showMessageDialog( getThisFrame(),
1034 "Collapsed " + to_be_removed.size()
1035 + " branches with\nconfidence values below "
1036 + getMinNotCollapseConfidenceValue(),
1037 "Collapsed " + to_be_removed.size() + " branches",
1038 JOptionPane.INFORMATION_MESSAGE );
1041 JOptionPane.showMessageDialog( getThisFrame(),
1042 "No branch collapsed,\nminimum confidence value per branch is "
1044 "No branch collapsed",
1045 JOptionPane.INFORMATION_MESSAGE );
1049 JOptionPane.showMessageDialog( getThisFrame(),
1050 "No branch collapsed because no confidence values present",
1051 "No confidence values present",
1052 JOptionPane.INFORMATION_MESSAGE );
1056 private void collapseBelowBranchLengthThreshold() {
1057 if ( getCurrentTreePanel() != null ) {
1058 final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
1059 if ( ( phy != null ) && !phy.isEmpty() ) {
1060 final String s = ( String ) JOptionPane.showInputDialog( getThisFrame(),
1061 "Please enter the minimum branch length value\n",
1062 "Minimal Branch Length Value",
1063 JOptionPane.QUESTION_MESSAGE,
1066 getMinNotCollapseBlValue() );
1067 if ( !ForesterUtil.isEmpty( s ) ) {
1068 boolean success = true;
1070 final String m_str = s.trim();
1071 if ( !ForesterUtil.isEmpty( m_str ) ) {
1073 m = Double.parseDouble( m_str );
1075 catch ( final Exception ex ) {
1082 if ( success && ( m >= 0.0 ) ) {
1083 setMinNotCollapseBlValue( m );
1091 private void collapseBelowThreshold() {
1092 if ( getCurrentTreePanel() != null ) {
1093 final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
1094 if ( ( phy != null ) && !phy.isEmpty() ) {
1095 final String s = ( String ) JOptionPane.showInputDialog( getThisFrame(),
1096 "Please enter the minimum confidence value\n",
1097 "Minimal Confidence Value",
1098 JOptionPane.QUESTION_MESSAGE,
1101 getMinNotCollapseConfidenceValue() );
1102 if ( !ForesterUtil.isEmpty( s ) ) {
1103 boolean success = true;
1105 final String m_str = s.trim();
1106 if ( !ForesterUtil.isEmpty( m_str ) ) {
1108 m = Double.parseDouble( m_str );
1110 catch ( final Exception ex ) {
1117 if ( success && ( m >= 0.0 ) ) {
1118 setMinNotCollapseConfidenceValue( m );
1119 collapseBelowThreshold( phy );
1126 private void collapseBl( final Phylogeny phy ) {
1127 final PhylogenyNodeIterator it = phy.iteratorPostorder();
1128 final List<PhylogenyNode> to_be_removed = new ArrayList<PhylogenyNode>();
1129 double min_bl = Double.MAX_VALUE;
1130 boolean bl_present = false;
1131 while ( it.hasNext() ) {
1132 final PhylogenyNode n = it.next();
1133 if ( !n.isExternal() && !n.isRoot() ) {
1134 final double bl = n.getDistanceToParent();
1135 if ( bl != PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT ) {
1137 if ( bl < getMinNotCollapseBlValue() ) {
1138 to_be_removed.add( n );
1140 if ( bl < min_bl ) {
1147 for( final PhylogenyNode node : to_be_removed ) {
1148 PhylogenyMethods.removeNode( node, phy );
1150 if ( to_be_removed.size() > 0 ) {
1151 phy.externalNodesHaveChanged();
1152 phy.clearHashIdToNodeMap();
1153 phy.recalculateNumberOfExternalDescendants( true );
1154 getCurrentTreePanel().resetNodeIdToDistToLeafMap();
1155 getCurrentTreePanel().updateSetOfCollapsedExternalNodes();
1156 getCurrentTreePanel().calculateLongestExtNodeInfo();
1157 getCurrentTreePanel().setNodeInPreorderToNull();
1158 getCurrentTreePanel().recalculateMaxDistanceToRoot();
1159 getCurrentTreePanel().resetPreferredSize();
1160 getCurrentTreePanel().setEdited( true );
1161 getCurrentTreePanel().repaint();
1164 if ( to_be_removed.size() > 0 ) {
1165 JOptionPane.showMessageDialog( getThisFrame(),
1166 "Collapsed " + to_be_removed.size()
1167 + " branches with\nbranch length values below "
1168 + getMinNotCollapseBlValue(),
1169 "Collapsed " + to_be_removed.size() + " branches",
1170 JOptionPane.INFORMATION_MESSAGE );
1173 JOptionPane.showMessageDialog( getThisFrame(),
1174 "No branch collapsed,\nminimum branch length is " + min_bl,
1175 "No branch collapsed",
1176 JOptionPane.INFORMATION_MESSAGE );
1180 JOptionPane.showMessageDialog( getThisFrame(),
1181 "No branch collapsed because no branch length values present",
1182 "No branch length values present",
1183 JOptionPane.INFORMATION_MESSAGE );
1187 private PhyloXmlParser createPhyloXmlParser() {
1188 PhyloXmlParser xml_parser = null;
1189 if ( getConfiguration().isValidatePhyloXmlAgainstSchema() ) {
1191 xml_parser = PhyloXmlParser.createPhyloXmlParserXsdValidating();
1193 catch ( final Exception e ) {
1194 JOptionPane.showMessageDialog( getThisFrame(),
1195 e.getLocalizedMessage(),
1196 "failed to create validating XML parser",
1197 JOptionPane.WARNING_MESSAGE );
1200 if ( xml_parser == null ) {
1201 xml_parser = PhyloXmlParser.createPhyloXmlParser();
1206 private void executePhyleneticInference( final boolean from_unaligned_seqs ) {
1207 final PhyloInferenceDialog dialog = new PhyloInferenceDialog( this,
1208 getPhylogeneticInferenceOptions(),
1209 from_unaligned_seqs );
1211 if ( dialog.getValue() == JOptionPane.OK_OPTION ) {
1212 if ( !from_unaligned_seqs ) {
1213 if ( getMsa() != null ) {
1214 final PhylogeneticInferrer inferrer = new PhylogeneticInferrer( getMsa(),
1215 getPhylogeneticInferenceOptions()
1218 new Thread( inferrer ).start();
1221 JOptionPane.showMessageDialog( getThisFrame(),
1222 "No multiple sequence alignment selected",
1223 "Phylogenetic Inference Not Launched",
1224 JOptionPane.WARNING_MESSAGE );
1228 if ( getSeqs() != null ) {
1229 final PhylogeneticInferrer inferrer = new PhylogeneticInferrer( getSeqs(),
1230 getPhylogeneticInferenceOptions()
1233 new Thread( inferrer ).start();
1236 JOptionPane.showMessageDialog( getThisFrame(),
1237 "No input sequences selected",
1238 "Phylogenetic Inference Not Launched",
1239 JOptionPane.WARNING_MESSAGE );
1245 private void extractTaxDataFromNodeNames() throws PhyloXmlDataFormatException {
1246 final StringBuilder sb = new StringBuilder();
1247 final StringBuilder sb_failed = new StringBuilder();
1249 int counter_failed = 0;
1250 if ( getCurrentTreePanel() != null ) {
1251 final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
1252 if ( ( phy != null ) && !phy.isEmpty() ) {
1253 final PhylogenyNodeIterator it = phy.iteratorExternalForward();
1254 while ( it.hasNext() ) {
1255 final PhylogenyNode n = it.next();
1256 final String name = n.getName().trim();
1257 if ( !ForesterUtil.isEmpty( name ) ) {
1258 final String nt = ParserUtils.extractTaxonomyDataFromNodeName( n,
1259 TAXONOMY_EXTRACTION.AGGRESSIVE );
1260 if ( !ForesterUtil.isEmpty( nt ) ) {
1261 if ( counter < 15 ) {
1262 sb.append( name + ": " + nt + "\n" );
1264 else if ( counter == 15 ) {
1265 sb.append( "...\n" );
1270 if ( counter_failed < 15 ) {
1271 sb_failed.append( name + "\n" );
1273 else if ( counter_failed == 15 ) {
1274 sb_failed.append( "...\n" );
1280 if ( counter > 0 ) {
1282 String all = "all ";
1283 if ( counter_failed > 0 ) {
1285 failed = "\nCould not extract taxonomic data for " + counter_failed + " named external nodes:\n"
1288 JOptionPane.showMessageDialog( getThisFrame(),
1289 "Extracted taxonomic data from " + all + counter
1290 + " named external nodes:\n" + sb.toString() + failed,
1291 "Taxonomic Data Extraction Completed",
1292 counter_failed > 0 ? JOptionPane.WARNING_MESSAGE
1293 : JOptionPane.INFORMATION_MESSAGE );
1296 JOptionPane.showMessageDialog( getThisFrame(),
1297 "Could not extract any taxonomic data.\nMaybe node names are empty\n"
1298 + "or not in the forms \"XYZ_CAEEL\", \"XYZ_6239\", or \"XYZ_Caenorhabditis_elegans\"\n"
1299 + "or nodes already have taxonomic data?\n",
1300 "No Taxonomic Data Extracted",
1301 JOptionPane.ERROR_MESSAGE );
1307 private double getMinNotCollapseBlValue() {
1308 return _min_not_collapse_bl;
1311 private double getMinNotCollapseConfidenceValue() {
1312 return _min_not_collapse;
1315 private PhylogeneticInferenceOptions getPhylogeneticInferenceOptions() {
1316 if ( _phylogenetic_inference_options == null ) {
1317 _phylogenetic_inference_options = new PhylogeneticInferenceOptions();
1319 return _phylogenetic_inference_options;
1322 private boolean isUnsavedDataPresent() {
1323 final List<TreePanel> tps = getMainPanel().getTreePanels();
1324 for( final TreePanel tp : tps ) {
1325 if ( tp.isEdited() ) {
1332 private void moveNodeNamesToSeqNames() throws PhyloXmlDataFormatException {
1333 if ( getCurrentTreePanel() != null ) {
1334 final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
1335 if ( ( phy != null ) && !phy.isEmpty() ) {
1336 PhylogenyMethods.transferNodeNameToField( phy,
1337 PhylogenyMethods.PhylogenyNodeField.SEQUENCE_NAME,
1343 private void moveNodeNamesToTaxSn() throws PhyloXmlDataFormatException {
1344 if ( getCurrentTreePanel() != null ) {
1345 final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
1346 if ( ( phy != null ) && !phy.isEmpty() ) {
1347 PhylogenyMethods.transferNodeNameToField( phy,
1348 PhylogenyMethods.PhylogenyNodeField.TAXONOMY_SCIENTIFIC_NAME,
1354 private void newTree() {
1355 final Phylogeny[] phys = new Phylogeny[ 1 ];
1356 final Phylogeny phy = new Phylogeny();
1357 final PhylogenyNode node = new PhylogenyNode();
1358 phy.setRoot( node );
1359 phy.setRooted( true );
1361 AptxUtil.addPhylogeniesToTabs( phys, "", "", getConfiguration(), getMainPanel() );
1362 _mainpanel.getControlPanel().showWhole();
1363 _mainpanel.getCurrentTreePanel().setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR );
1364 _mainpanel.getOptions().setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR );
1366 getMainPanel().getMainFrame().setSelectedTypeInTypeMenu( PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR );
1368 activateSaveAllIfNeeded();
1372 private void obtainDetailedTaxonomicInformation() {
1373 if ( getCurrentTreePanel() != null ) {
1374 final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
1375 if ( ( phy != null ) && !phy.isEmpty() ) {
1376 final TaxonomyDataManager t = new TaxonomyDataManager( this,
1377 _mainpanel.getCurrentTreePanel(),
1381 new Thread( t ).start();
1386 private void obtainDetailedTaxonomicInformationDelete() {
1387 if ( getCurrentTreePanel() != null ) {
1388 final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
1389 if ( ( phy != null ) && !phy.isEmpty() ) {
1390 final TaxonomyDataManager t = new TaxonomyDataManager( this,
1391 _mainpanel.getCurrentTreePanel(),
1395 new Thread( t ).start();
1400 private void obtainSequenceInformation() {
1401 if ( getCurrentTreePanel() != null ) {
1402 final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
1403 if ( ( phy != null ) && !phy.isEmpty() ) {
1404 final SequenceDataRetriver u = new SequenceDataRetriver( this,
1405 _mainpanel.getCurrentTreePanel(),
1407 new Thread( u ).start();
1412 private void preProcessTreesUponReading( final Phylogeny[] phys ) {
1413 for( final Phylogeny phy : phys ) {
1414 if ( ( phy != null ) && !phy.isEmpty() ) {
1415 for( final PhylogenyNodeIterator it = phy.iteratorPreorder(); it.hasNext(); ) {
1416 final PhylogenyNode n = it.next();
1417 if ( n.isExternal() ) {
1418 if ( n.getNodeData().isHasSequence() ) {
1419 final Sequence s = n.getNodeData().getSequence();
1420 if ( ForesterUtil.isEmpty( s.getGeneName() ) || s.getGeneName().startsWith( "LOC" ) ) {
1421 if ( ( s.getAccession() != null )
1422 && !ForesterUtil.isEmpty( s.getAccession().getValue() ) ) {
1423 s.setGeneName( s.getAccession().getValue() );
1425 else if ( !ForesterUtil.isEmpty( n.getName() ) ) {
1426 s.setGeneName( n.getName() );
1436 private void readPhylogeniesFromFile() {
1437 boolean exception = false;
1438 Phylogeny[] phys = null;
1439 // Set an initial directory if none set yet
1440 final File my_dir = getCurrentDir();
1441 // Open file-open dialog and set current directory
1442 if ( my_dir != null ) {
1443 _open_filechooser.setCurrentDirectory( my_dir );
1445 final int result = _open_filechooser.showOpenDialog( _contentpane );
1446 // All done: get the file
1447 final File[] files = _open_filechooser.getSelectedFiles();
1448 setCurrentDir( _open_filechooser.getCurrentDirectory() );
1449 boolean nhx_or_nexus = false;
1450 if ( ( files != null ) && ( files.length > 0 ) && ( result == JFileChooser.APPROVE_OPTION ) ) {
1451 for( final File file : files ) {
1452 if ( ( file != null ) && !file.isDirectory() ) {
1453 if ( _mainpanel.getCurrentTreePanel() != null ) {
1454 _mainpanel.getCurrentTreePanel().setWaitCursor();
1457 _mainpanel.setWaitCursor();
1459 if ( ( _open_filechooser.getFileFilter() == MainFrame.nhfilter )
1460 || ( _open_filechooser.getFileFilter() == MainFrame.nhxfilter ) ) {
1462 final NHXParser nhx = new NHXParser();
1463 setSpecialOptionsForNhxParser( nhx );
1464 phys = PhylogenyMethods.readPhylogenies( nhx, file );
1465 nhx_or_nexus = true;
1467 catch ( final Exception e ) {
1469 exceptionOccuredDuringOpenFile( e );
1472 else if ( _open_filechooser.getFileFilter() == MainFrame.xmlfilter ) {
1473 warnIfNotPhyloXmlValidation( getConfiguration() );
1475 final PhyloXmlParser xml_parser = createPhyloXmlParser();
1476 phys = PhylogenyMethods.readPhylogenies( xml_parser, file );
1478 catch ( final Exception e ) {
1480 exceptionOccuredDuringOpenFile( e );
1483 else if ( _open_filechooser.getFileFilter() == MainFrame.tolfilter ) {
1485 phys = PhylogenyMethods.readPhylogenies( new TolParser(), file );
1487 catch ( final Exception e ) {
1489 exceptionOccuredDuringOpenFile( e );
1492 else if ( _open_filechooser.getFileFilter() == MainFrame.nexusfilter ) {
1494 final NexusPhylogeniesParser nex = new NexusPhylogeniesParser();
1495 setSpecialOptionsForNexParser( nex );
1496 phys = PhylogenyMethods.readPhylogenies( nex, file );
1497 nhx_or_nexus = true;
1499 catch ( final Exception e ) {
1501 exceptionOccuredDuringOpenFile( e );
1507 final PhylogenyParser parser = ParserUtils
1508 .createParserDependingOnFileType( file,
1510 .isValidatePhyloXmlAgainstSchema() );
1511 if ( parser instanceof NexusPhylogeniesParser ) {
1512 final NexusPhylogeniesParser nex = ( NexusPhylogeniesParser ) parser;
1513 setSpecialOptionsForNexParser( nex );
1514 nhx_or_nexus = true;
1516 else if ( parser instanceof NHXParser ) {
1517 final NHXParser nhx = ( NHXParser ) parser;
1518 setSpecialOptionsForNhxParser( nhx );
1519 nhx_or_nexus = true;
1521 else if ( parser instanceof PhyloXmlParser ) {
1522 warnIfNotPhyloXmlValidation( getConfiguration() );
1524 phys = PhylogenyMethods.readPhylogenies( parser, file );
1526 catch ( final Exception e ) {
1528 exceptionOccuredDuringOpenFile( e );
1531 if ( _mainpanel.getCurrentTreePanel() != null ) {
1532 _mainpanel.getCurrentTreePanel().setArrowCursor();
1535 _mainpanel.setArrowCursor();
1537 if ( !exception && ( phys != null ) && ( phys.length > 0 ) ) {
1538 boolean one_desc = false;
1539 if ( nhx_or_nexus ) {
1540 for( final Phylogeny phy : phys ) {
1541 if ( getOptions().isInternalNumberAreConfidenceForNhParsing() ) {
1542 PhylogenyMethods.transferInternalNodeNamesToConfidence( phy, "" );
1544 if ( PhylogenyMethods.getMinimumDescendentsPerInternalNodes( phy ) == 1 ) {
1550 if ( PREPROCESS_TREES ) {
1551 preProcessTreesUponReading( phys );
1553 AptxUtil.addPhylogeniesToTabs( phys,
1555 file.getAbsolutePath(),
1558 _mainpanel.getControlPanel().showWhole();
1559 if ( nhx_or_nexus && one_desc ) {
1560 JOptionPane.showMessageDialog( getThisFrame(),
1561 "One or more trees contain (a) node(s) with one descendant, "
1562 + ForesterUtil.LINE_SEPARATOR
1563 + "possibly indicating illegal parentheses within node names.",
1564 "Warning: Possible Error in New Hampshire Formatted Data",
1565 JOptionPane.WARNING_MESSAGE );
1571 activateSaveAllIfNeeded();
1575 private void readSpeciesTreeFromFile() {
1577 boolean exception = false;
1578 final File my_dir = getCurrentDir();
1579 _open_filechooser_for_species_tree.setSelectedFile( new File( "" ) );
1580 if ( my_dir != null ) {
1581 _open_filechooser_for_species_tree.setCurrentDirectory( my_dir );
1583 final int result = _open_filechooser_for_species_tree.showOpenDialog( _contentpane );
1584 final File file = _open_filechooser_for_species_tree.getSelectedFile();
1585 if ( ( file != null ) && ( result == JFileChooser.APPROVE_OPTION ) ) {
1586 if ( _open_filechooser_for_species_tree.getFileFilter() == MainFrame.xmlfilter ) {
1588 final Phylogeny[] trees = PhylogenyMethods
1589 .readPhylogenies( PhyloXmlParser.createPhyloXmlParserXsdValidating(), file );
1592 catch ( final Exception e ) {
1594 exceptionOccuredDuringOpenFile( e );
1597 else if ( _open_filechooser_for_species_tree.getFileFilter() == MainFrame.tolfilter ) {
1599 final Phylogeny[] trees = PhylogenyMethods.readPhylogenies( new TolParser(), file );
1602 catch ( final Exception e ) {
1604 exceptionOccuredDuringOpenFile( e );
1610 final Phylogeny[] trees = PhylogenyMethods
1611 .readPhylogenies( PhyloXmlParser.createPhyloXmlParserXsdValidating(), file );
1614 catch ( final Exception e ) {
1616 exceptionOccuredDuringOpenFile( e );
1619 if ( !exception && ( t != null ) && !t.isRooted() ) {
1622 JOptionPane.showMessageDialog( getThisFrame(),
1623 "Species tree is not rooted",
1624 "Species tree not loaded",
1625 JOptionPane.ERROR_MESSAGE );
1627 if ( !exception && ( t != null ) ) {
1628 final Set<Taxonomy> tax_set = new HashSet<Taxonomy>();
1629 for( final PhylogenyNodeIterator it = t.iteratorExternalForward(); it.hasNext(); ) {
1630 final PhylogenyNode node = it.next();
1631 if ( !node.getNodeData().isHasTaxonomy() ) {
1634 JOptionPane.showMessageDialog( getThisFrame(),
1635 "Species tree contains external node(s) without taxonomy information",
1636 "Species tree not loaded",
1637 JOptionPane.ERROR_MESSAGE );
1641 if ( tax_set.contains( node.getNodeData().getTaxonomy() ) ) {
1645 .showMessageDialog( getThisFrame(),
1646 "Taxonomy [" + node.getNodeData().getTaxonomy().asSimpleText()
1647 + "] is not unique in species tree",
1648 "Species tree not loaded",
1649 JOptionPane.ERROR_MESSAGE );
1653 tax_set.add( node.getNodeData().getTaxonomy() );
1658 if ( !exception && ( t != null ) ) {
1659 setSpeciesTree( t );
1660 JOptionPane.showMessageDialog( getThisFrame(),
1661 "Species tree successfully loaded",
1662 "Species tree loaded",
1663 JOptionPane.INFORMATION_MESSAGE );
1665 _contentpane.repaint();
1670 private void setArrowCursor() {
1672 _mainpanel.getCurrentTreePanel().setArrowCursor();
1674 catch ( final Exception ex ) {
1679 private void setMinNotCollapseBlValue( final double min_not_collapse_bl ) {
1680 _min_not_collapse_bl = min_not_collapse_bl;
1683 private void setMinNotCollapseConfidenceValue( final double min_not_collapse ) {
1684 _min_not_collapse = min_not_collapse;
1687 private void setPhylogeneticInferenceOptions( final PhylogeneticInferenceOptions phylogenetic_inference_options ) {
1688 _phylogenetic_inference_options = phylogenetic_inference_options;
1691 private void setSpecialOptionsForNexParser( final NexusPhylogeniesParser nex ) {
1692 nex.setReplaceUnderscores( getOptions().isReplaceUnderscoresInNhParsing() );
1693 nex.setTaxonomyExtraction( getOptions().getTaxonomyExtraction() );
1694 nex.setParseBeastStyleExtendedTags( getOptions().isParseBeastStyleExtendedNexusTags() );
1697 private void setSpecialOptionsForNhxParser( final NHXParser nhx ) {
1698 nhx.setReplaceUnderscores( getOptions().isReplaceUnderscoresInNhParsing() );
1699 nhx.setTaxonomyExtraction( getOptions().getTaxonomyExtraction() );
1700 nhx.setAllowErrorsInDistanceToParent( getOptions().isAllowErrorsInDistanceToParent() );
1701 nhx.setParseBeastStyleExtendedTags( getOptions().isParseBeastStyleExtendedNexusTags() );
1704 void buildAnalysisMenu() {
1705 _analysis_menu = MainFrame.createMenu( "Analysis", getConfiguration() );
1706 _analysis_menu.add( _gsdi_item = new JMenuItem( "GSDI (Generalized Speciation Duplication Inference)" ) );
1707 _analysis_menu.add( _gsdir_item = new JMenuItem( "GSDIR (GSDI with re-rooting)" ) );
1708 _analysis_menu.add( _load_species_tree_item = new JMenuItem( "Load Species Tree..." ) );
1709 customizeJMenuItem( _gsdi_item );
1710 customizeJMenuItem( _gsdir_item );
1711 customizeJMenuItem( _load_species_tree_item );
1712 _analysis_menu.addSeparator();
1713 _analysis_menu.add( _lineage_inference = new JMenuItem( INFER_ANCESTOR_TAXONOMIES ) );
1714 customizeJMenuItem( _lineage_inference );
1715 _lineage_inference.setToolTipText( "Inference of ancestor taxonomies/lineages" );
1716 _jmenubar.add( _analysis_menu );
1720 void buildFileMenu() {
1721 _file_jmenu = MainFrame.createMenu( "File", getConfiguration() );
1722 _file_jmenu.add( _open_item = new JMenuItem( "Read Tree from File..." ) );
1723 _file_jmenu.addSeparator();
1724 _file_jmenu.add( _open_url_item = new JMenuItem( "Read Tree from URL/Webservice..." ) );
1725 _file_jmenu.addSeparator();
1726 final WebservicesManager webservices_manager = WebservicesManager.getInstance();
1727 _load_phylogeny_from_webservice_menu_items = new JMenuItem[ webservices_manager
1728 .getAvailablePhylogeniesWebserviceClients().size() ];
1729 for( int i = 0; i < webservices_manager.getAvailablePhylogeniesWebserviceClients().size(); ++i ) {
1730 final PhylogeniesWebserviceClient client = webservices_manager.getAvailablePhylogeniesWebserviceClient( i );
1731 _load_phylogeny_from_webservice_menu_items[ i ] = new JMenuItem( client.getMenuName() );
1732 _file_jmenu.add( _load_phylogeny_from_webservice_menu_items[ i ] );
1734 if ( getConfiguration().isEditable() ) {
1735 _file_jmenu.addSeparator();
1736 _file_jmenu.add( _new_item = new JMenuItem( "New" ) );
1737 _new_item.setToolTipText( "to create a new tree with one node, as source for manual tree construction" );
1739 _file_jmenu.addSeparator();
1740 _file_jmenu.add( _save_item = new JMenuItem( "Save Tree As..." ) );
1741 _file_jmenu.add( _save_all_item = new JMenuItem( "Save All Trees As..." ) );
1742 _save_all_item.setToolTipText( "Write all phylogenies to one file." );
1743 _save_all_item.setEnabled( false );
1744 _file_jmenu.addSeparator();
1745 _file_jmenu.add( _write_to_pdf_item = new JMenuItem( "Export to PDF file ..." ) );
1746 if ( AptxUtil.canWriteFormat( "tif" ) || AptxUtil.canWriteFormat( "tiff" )
1747 || AptxUtil.canWriteFormat( "TIF" ) ) {
1748 _file_jmenu.add( _write_to_tif_item = new JMenuItem( "Export to TIFF file..." ) );
1750 _file_jmenu.add( _write_to_png_item = new JMenuItem( "Export to PNG file..." ) );
1751 _file_jmenu.add( _write_to_jpg_item = new JMenuItem( "Export to JPG file..." ) );
1752 if ( AptxUtil.canWriteFormat( "gif" ) ) {
1753 _file_jmenu.add( _write_to_gif_item = new JMenuItem( "Export to GIF file..." ) );
1755 if ( AptxUtil.canWriteFormat( "bmp" ) ) {
1756 _file_jmenu.add( _write_to_bmp_item = new JMenuItem( "Export to BMP file..." ) );
1758 _file_jmenu.addSeparator();
1759 _file_jmenu.add( _print_item = new JMenuItem( "Print..." ) );
1760 _file_jmenu.addSeparator();
1761 _file_jmenu.add( _close_item = new JMenuItem( "Close Tab" ) );
1762 _close_item.setToolTipText( "To close the current pane." );
1763 _close_item.setEnabled( true );
1764 _file_jmenu.addSeparator();
1765 _file_jmenu.add( _exit_item = new JMenuItem( "Exit" ) );
1766 customizeJMenuItem( _open_item );
1767 _open_item.setFont( new Font( _open_item.getFont().getFontName(),
1769 _open_item.getFont().getSize() + 4 ) );
1770 customizeJMenuItem( _open_url_item );
1771 for( int i = 0; i < webservices_manager.getAvailablePhylogeniesWebserviceClients().size(); ++i ) {
1772 customizeJMenuItem( _load_phylogeny_from_webservice_menu_items[ i ] );
1774 customizeJMenuItem( _save_item );
1775 if ( getConfiguration().isEditable() ) {
1776 customizeJMenuItem( _new_item );
1778 customizeJMenuItem( _close_item );
1779 customizeJMenuItem( _save_all_item );
1780 customizeJMenuItem( _write_to_pdf_item );
1781 customizeJMenuItem( _write_to_png_item );
1782 customizeJMenuItem( _write_to_jpg_item );
1783 customizeJMenuItem( _write_to_gif_item );
1784 customizeJMenuItem( _write_to_tif_item );
1785 customizeJMenuItem( _write_to_bmp_item );
1786 customizeJMenuItem( _print_item );
1787 customizeJMenuItem( _exit_item );
1788 _jmenubar.add( _file_jmenu );
1791 void buildOptionsMenu() {
1792 _options_jmenu = MainFrame.createMenu( OPTIONS_HEADER, getConfiguration() );
1793 _options_jmenu.addChangeListener( new ChangeListener() {
1796 public void stateChanged( final ChangeEvent e ) {
1797 MainFrame.setOvPlacementColorChooseMenuItem( _overview_placment_mi, getOptions() );
1798 MainFrame.setTextColorChooseMenuItem( _switch_colors_mi, getCurrentTreePanel() );
1799 MainFrame.setTextMinSupportMenuItem( _choose_minimal_confidence_mi,
1801 getCurrentTreePanel() );
1802 MainFrame.setTextForFontChooserMenuItem( _choose_font_mi,
1803 MainFrame.createCurrentFontDesc( getMainPanel()
1804 .getTreeFontSet() ) );
1805 // MainFrame.setTextForGraphicsSizeChooserMenuItem( _print_size_mi, getOptions() );
1806 MainFrame.setTextForPdfLineWidthChooserMenuItem( _choose_pdf_width_mi, getOptions() );
1807 MainFrame.setCycleNodeFillMenuItem( _cycle_node_fill_mi, getOptions() );
1808 MainFrame.setCycleNodeShapeMenuItem( _cycle_node_shape_mi, getOptions() );
1809 MainFrame.setCycleDataReturnMenuItem( _cycle_data_return, getOptions() );
1810 MainFrame.setTextNodeSizeMenuItem( _choose_node_size_mi, getOptions() );
1812 getMainPanel().getControlPanel().setVisibilityOfDomainStrucureCB();
1813 getMainPanel().getControlPanel().setVisibilityOfX();
1815 catch ( final Exception ignore ) {
1816 // do nothing, not important.
1820 _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( DISPLAY_SUBHEADER ), getConfiguration() ) );
1822 .add( _ext_node_dependent_cladogram_rbmi = new JRadioButtonMenuItem( MainFrame.NONUNIFORM_CLADOGRAMS_LABEL ) );
1823 _options_jmenu.add( _non_lined_up_cladograms_rbmi = new JRadioButtonMenuItem( NON_LINED_UP_CLADOGRAMS_LABEL ) );
1824 _radio_group_1 = new ButtonGroup();
1825 _radio_group_1.add( _ext_node_dependent_cladogram_rbmi );
1826 _radio_group_1.add( _non_lined_up_cladograms_rbmi );
1827 _options_jmenu.add( _show_overview_cbmi = new JCheckBoxMenuItem( SHOW_OVERVIEW_LABEL ) );
1828 _options_jmenu.add( _show_scale_cbmi = new JCheckBoxMenuItem( DISPLAY_SCALE_LABEL ) );
1830 .add( _show_default_node_shapes_internal_cbmi = new JCheckBoxMenuItem( DISPLAY_NODE_BOXES_LABEL_INT ) );
1832 .add( _show_default_node_shapes_external_cbmi = new JCheckBoxMenuItem( DISPLAY_NODE_BOXES_LABEL_EXT ) );
1834 .add( _show_default_node_shapes_for_marked_cbmi = new JCheckBoxMenuItem( MainFrame.DISPLAY_NODE_BOXES_LABEL_MARKED ) );
1837 .add( _collapsed_with_average_height_cbmi = new JCheckBoxMenuItem( "Proportional Height of Collapsed Subtrees" ) );
1841 .add( _show_abbreviated_labels_for_collapsed_nodes_cbmi = new JCheckBoxMenuItem( "Add Abbreviated Labels to Collapsed Subtrees" ) );
1846 .add( _line_up_renderable_data_cbmi = new JCheckBoxMenuItem( MainFrame.LINE_UP_RENDERABLE_DATA ) );
1850 if ( getConfiguration().doDisplayOption( Configuration.show_domain_architectures ) ) {
1852 .add( _right_line_up_domains_cbmi = new JCheckBoxMenuItem( MainFrame.RIGHT_LINE_UP_DOMAINS ) );
1853 _options_jmenu.add( _show_domain_labels = new JCheckBoxMenuItem( MainFrame.SHOW_DOMAIN_LABELS_LABEL ) );
1855 _options_jmenu.add( _show_annotation_ref_source = new JCheckBoxMenuItem( SHOW_ANN_REF_SOURCE_LABEL ) );
1856 _options_jmenu.add( _show_confidence_stddev_cbmi = new JCheckBoxMenuItem( SHOW_CONF_STDDEV_LABEL ) );
1857 _options_jmenu.add( _color_by_taxonomic_group_cbmi = new JCheckBoxMenuItem( COLOR_BY_TAXONOMIC_GROUP ) );
1858 _options_jmenu.add( _color_labels_same_as_parent_branch = new JCheckBoxMenuItem( COLOR_LABELS_LABEL ) );
1859 _color_labels_same_as_parent_branch.setToolTipText( MainFrame.COLOR_LABELS_TIP );
1860 _options_jmenu.add( _abbreviate_scientific_names = new JCheckBoxMenuItem( ABBREV_SN_LABEL ) );
1861 _options_jmenu.add( _label_direction_cbmi = new JCheckBoxMenuItem( LABEL_DIRECTION_LABEL ) );
1862 _label_direction_cbmi.setToolTipText( LABEL_DIRECTION_TIP );
1863 _options_jmenu.add( _screen_antialias_cbmi = new JCheckBoxMenuItem( SCREEN_ANTIALIAS_LABEL ) );
1864 _options_jmenu.add( _background_gradient_cbmi = new JCheckBoxMenuItem( BG_GRAD_LABEL ) );
1865 _options_jmenu.add( _cycle_node_shape_mi = new JMenuItem( MainFrame.CYCLE_NODE_SHAPE_LABEL ) );
1866 _options_jmenu.add( _cycle_node_fill_mi = new JMenuItem( MainFrame.CYCLE_NODE_FILL_LABEL ) );
1867 _options_jmenu.add( _choose_node_size_mi = new JMenuItem( MainFrame.CHOOSE_NODE_SIZE_LABEL ) );
1868 _options_jmenu.add( _choose_minimal_confidence_mi = new JMenuItem( "" ) );
1869 _options_jmenu.add( _overview_placment_mi = new JMenuItem( "" ) );
1870 _options_jmenu.add( _switch_colors_mi = new JMenuItem( "" ) );
1871 _options_jmenu.add( _choose_font_mi = new JMenuItem( "" ) );
1872 _options_jmenu.addSeparator();
1873 _options_jmenu.add( _cycle_data_return = new JMenuItem( "Cycle Data Return" ) );
1874 _options_jmenu.addSeparator();
1875 _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( SEARCH_SUBHEADER ), getConfiguration() ) );
1876 _options_jmenu.add( _search_case_senstive_cbmi = new JCheckBoxMenuItem( SEARCH_CASE_SENSITIVE_LABEL ) );
1877 _options_jmenu.add( _search_whole_words_only_cbmi = new JCheckBoxMenuItem( SEARCH_TERMS_ONLY_LABEL ) );
1878 _options_jmenu.add( _search_with_regex_cbmi = new JCheckBoxMenuItem( MainFrame.SEARCH_REGEX_LABEL ) );
1879 _search_with_regex_cbmi.setToolTipText( MainFrame.SEARCH_WITH_REGEX_TIP );
1880 _options_jmenu.add( _inverse_search_result_cbmi = new JCheckBoxMenuItem( INVERSE_SEARCH_RESULT_LABEL ) );
1882 .add( _color_all_found_nodes_when_coloring_subtree_cbmi = new JCheckBoxMenuItem( "Colorize All Found Nodes When Colorizing Subtree(s)" ) );
1883 _options_jmenu.addSeparator();
1885 .add( customizeMenuItemAsLabel( new JMenuItem( "Graphics Export & Printing:" ), getConfiguration() ) );
1886 _options_jmenu.add( _antialias_print_cbmi = new JCheckBoxMenuItem( "Antialias" ) );
1887 _options_jmenu.add( _print_black_and_white_cbmi = new JCheckBoxMenuItem( "Export in Black and White" ) );
1889 .add( _graphics_export_visible_only_cbmi = new JCheckBoxMenuItem( "Limit to Visible ('Screenshot') for PNG, JPG, and GIF export" ) );
1890 _options_jmenu.add( _choose_pdf_width_mi = new JMenuItem( "" ) );
1891 _options_jmenu.addSeparator();
1892 _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( "Newick/NHX/Nexus Read:" ), getConfiguration() ) );
1894 .add( _internal_number_are_confidence_for_nh_parsing_cbmi = new JCheckBoxMenuItem( "Internal Node Names are Confidence Values" ) );
1895 _options_jmenu.add( _replace_underscores_cbmi = new JCheckBoxMenuItem( "Replace Underscores with Spaces" ) );
1897 .add( _parse_beast_style_extended_nexus_tags_cbmi = new JCheckBoxMenuItem( "Parse BEAST-style extended Newick/Nexus tags" ) );
1898 _parse_beast_style_extended_nexus_tags_cbmi
1899 .setToolTipText( "to parse elements in the form of \"[&!color=#800080]\" in Newick/Nexus formatted trees" );
1901 .add( _allow_errors_in_distance_to_parent_cbmi = new JCheckBoxMenuItem( "Ignore Distance Values Format Errors" ) );
1902 _options_jmenu.add( _extract_taxonomy_no_rbmi = new JRadioButtonMenuItem( "No Taxonomy Extraction" ) );
1904 .add( _extract_taxonomy_pfam_strict_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids from Pfam-style Node Names" ) );
1906 .add( _extract_taxonomy_pfam_relaxed_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids from Pfam-style like Node Names" ) );
1908 .add( _extract_taxonomy_agressive_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids/Scientific Names from Node Names" ) );
1909 _extract_taxonomy_pfam_strict_rbmi
1910 .setToolTipText( "To extract taxonomy codes/ids from node names in the form of e.g. \"BCL2_MOUSE/123-304\" or \"BCL2_10090/123-304\"" );
1911 _extract_taxonomy_pfam_relaxed_rbmi
1912 .setToolTipText( "To extract taxonomy codes/ids from node names in the form of e.g. \"bax_MOUSE\" or \"bax_10090\"" );
1913 _extract_taxonomy_agressive_rbmi
1914 .setToolTipText( "To extract taxonomy codes/ids or scientific names from node names in the form of e.g. \"MOUSE\" or \"10090\" or \"xyz_Nematostella_vectensis\"" );
1915 _radio_group_2 = new ButtonGroup();
1916 _radio_group_2.add( _extract_taxonomy_no_rbmi );
1917 _radio_group_2.add( _extract_taxonomy_pfam_strict_rbmi );
1918 _radio_group_2.add( _extract_taxonomy_pfam_relaxed_rbmi );
1919 _radio_group_2.add( _extract_taxonomy_agressive_rbmi );
1920 _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( "Newick/Nexus Save:" ), getConfiguration() ) );
1922 .add( _use_brackets_for_conf_in_nh_export_cbmi = new JCheckBoxMenuItem( USE_BRACKETS_FOR_CONF_IN_NH_LABEL ) );
1923 _use_brackets_for_conf_in_nh_export_cbmi
1924 .setToolTipText( "e.g. \"0.1[90]\" for a branch with support 90 and a length of 0.1" );
1926 .add( _use_internal_names_for_conf_in_nh_export_cbmi = new JCheckBoxMenuItem( USE_INTERNAL_NAMES_FOR_CONF_IN_NH_LABEL ) );
1927 customizeJMenuItem( _choose_font_mi );
1928 customizeJMenuItem( _choose_minimal_confidence_mi );
1929 customizeJMenuItem( _switch_colors_mi );
1930 customizeJMenuItem( _choose_pdf_width_mi );
1931 customizeJMenuItem( _overview_placment_mi );
1932 customizeCheckBoxMenuItem( _show_default_node_shapes_external_cbmi,
1933 getOptions().isShowDefaultNodeShapesExternal() );
1934 customizeCheckBoxMenuItem( _show_default_node_shapes_internal_cbmi,
1935 getOptions().isShowDefaultNodeShapesInternal() );
1936 customizeCheckBoxMenuItem( _show_default_node_shapes_for_marked_cbmi,
1937 getOptions().isShowDefaultNodeShapesForMarkedNodes() );
1938 customizeJMenuItem( _cycle_node_shape_mi );
1939 customizeJMenuItem( _cycle_node_fill_mi );
1940 customizeJMenuItem( _choose_node_size_mi );
1941 customizeJMenuItem( _cycle_data_return );
1942 customizeCheckBoxMenuItem( _color_labels_same_as_parent_branch,
1943 getOptions().isColorLabelsSameAsParentBranch() );
1944 customizeCheckBoxMenuItem( _color_by_taxonomic_group_cbmi, getOptions().isColorByTaxonomicGroup() );
1945 customizeCheckBoxMenuItem( _screen_antialias_cbmi, getOptions().isAntialiasScreen() );
1946 customizeCheckBoxMenuItem( _background_gradient_cbmi, getOptions().isBackgroundColorGradient() );
1947 customizeCheckBoxMenuItem( _show_domain_labels, getOptions().isShowDomainLabels() );
1948 customizeCheckBoxMenuItem( _show_annotation_ref_source, getOptions().isShowAnnotationRefSource() );
1949 customizeCheckBoxMenuItem( _abbreviate_scientific_names, getOptions().isAbbreviateScientificTaxonNames() );
1950 customizeCheckBoxMenuItem( _search_case_senstive_cbmi, getOptions().isSearchCaseSensitive() );
1951 customizeCheckBoxMenuItem( _show_scale_cbmi, getOptions().isShowScale() );
1952 customizeCheckBoxMenuItem( _collapsed_with_average_height_cbmi, getOptions().isCollapsedWithAverageHeigh() );
1953 customizeCheckBoxMenuItem( _show_abbreviated_labels_for_collapsed_nodes_cbmi, getOptions().isShowAbbreviatedLabelsForCollapsedNodes() );
1955 customizeRadioButtonMenuItem( _non_lined_up_cladograms_rbmi,
1956 getOptions().getCladogramType() == CLADOGRAM_TYPE.NON_LINED_UP );
1957 customizeRadioButtonMenuItem( _ext_node_dependent_cladogram_rbmi,
1958 getOptions().getCladogramType() == CLADOGRAM_TYPE.LINED_UP );
1959 customizeCheckBoxMenuItem( _show_overview_cbmi, getOptions().isShowOverview() );
1960 customizeCheckBoxMenuItem( _label_direction_cbmi,
1961 getOptions().getNodeLabelDirection() == NODE_LABEL_DIRECTION.RADIAL );
1962 customizeCheckBoxMenuItem( _antialias_print_cbmi, getOptions().isAntialiasPrint() );
1963 customizeCheckBoxMenuItem( _print_black_and_white_cbmi, getOptions().isPrintBlackAndWhite() );
1964 customizeCheckBoxMenuItem( _internal_number_are_confidence_for_nh_parsing_cbmi,
1965 getOptions().isInternalNumberAreConfidenceForNhParsing() );
1966 customizeRadioButtonMenuItem( _extract_taxonomy_no_rbmi,
1967 getOptions().getTaxonomyExtraction() == TAXONOMY_EXTRACTION.NO );
1968 customizeRadioButtonMenuItem( _extract_taxonomy_pfam_strict_rbmi,
1969 getOptions().getTaxonomyExtraction() == TAXONOMY_EXTRACTION.PFAM_STYLE_STRICT );
1970 customizeRadioButtonMenuItem( _extract_taxonomy_pfam_relaxed_rbmi,
1971 getOptions().getTaxonomyExtraction() == TAXONOMY_EXTRACTION.PFAM_STYLE_RELAXED );
1972 customizeRadioButtonMenuItem( _extract_taxonomy_agressive_rbmi,
1973 getOptions().getTaxonomyExtraction() == TAXONOMY_EXTRACTION.AGGRESSIVE );
1974 customizeCheckBoxMenuItem( _replace_underscores_cbmi, getOptions().isReplaceUnderscoresInNhParsing() );
1975 customizeCheckBoxMenuItem( _allow_errors_in_distance_to_parent_cbmi,
1976 getOptions().isReplaceUnderscoresInNhParsing() );
1977 customizeCheckBoxMenuItem( _search_with_regex_cbmi, getOptions().isSearchWithRegex() );
1978 customizeCheckBoxMenuItem( _search_whole_words_only_cbmi, getOptions().isMatchWholeTermsOnly() );
1979 customizeCheckBoxMenuItem( _inverse_search_result_cbmi, getOptions().isInverseSearchResult() );
1980 customizeCheckBoxMenuItem( _color_all_found_nodes_when_coloring_subtree_cbmi,
1981 getOptions().isColorAllFoundNodesWhenColoringSubtree() );
1982 customizeCheckBoxMenuItem( _parse_beast_style_extended_nexus_tags_cbmi,
1983 getOptions().isParseBeastStyleExtendedNexusTags() );
1984 customizeCheckBoxMenuItem( _graphics_export_visible_only_cbmi, getOptions().isGraphicsExportVisibleOnly() );
1985 customizeCheckBoxMenuItem( _show_confidence_stddev_cbmi, getOptions().isShowConfidenceStddev() );
1986 customizeCheckBoxMenuItem( _use_brackets_for_conf_in_nh_export_cbmi,
1988 .getNhConversionSupportValueStyle() == NH_CONVERSION_SUPPORT_VALUE_STYLE.IN_SQUARE_BRACKETS );
1989 customizeCheckBoxMenuItem( _use_internal_names_for_conf_in_nh_export_cbmi,
1991 .getNhConversionSupportValueStyle() == NH_CONVERSION_SUPPORT_VALUE_STYLE.AS_INTERNAL_NODE_NAMES );
1992 customizeCheckBoxMenuItem( _line_up_renderable_data_cbmi, getOptions().isLineUpRendarableNodeData() );
1993 customizeCheckBoxMenuItem( _right_line_up_domains_cbmi, getOptions().isRightLineUpDomains() );
1994 _jmenubar.add( _options_jmenu );
1997 void buildPhylogeneticInferenceMenu() {
1998 final InferenceManager im = getInferenceManager();
1999 _inference_menu = MainFrame.createMenu( "Inference", getConfiguration() );
2000 _inference_menu.add( _inference_from_msa_item = new JMenuItem( "From Multiple Sequence Alignment..." ) );
2001 customizeJMenuItem( _inference_from_msa_item );
2002 _inference_from_msa_item.setToolTipText( "Basic phylogenetic inference from MSA" );
2003 if ( im.canDoMsa() ) {
2004 _inference_menu.add( _inference_from_seqs_item = new JMenuItem( "From Unaligned Sequences..." ) );
2005 customizeJMenuItem( _inference_from_seqs_item );
2006 _inference_from_seqs_item
2007 .setToolTipText( "Basic phylogenetic inference including multiple sequence alignment" );
2011 .add( _inference_from_seqs_item = new JMenuItem( "From Unaligned Sequences (no program found)" ) );
2012 customizeJMenuItem( _inference_from_seqs_item );
2013 _inference_from_seqs_item.setEnabled( false );
2015 _jmenubar.add( _inference_menu );
2018 void buildToolsMenu() {
2019 _tools_menu = createMenu( "Tools", getConfiguration() );
2020 _tools_menu.add( _confcolor_item = new JMenuItem( "Colorize Branches Depending on Confidence" ) );
2021 customizeJMenuItem( _confcolor_item );
2022 _tools_menu.add( _color_rank_jmi = new JMenuItem( "Colorize Subtrees via Taxonomic Rank" ) );
2023 customizeJMenuItem( _color_rank_jmi );
2024 _color_rank_jmi.setToolTipText( "for example, at \"Class\" level, colorize mammal specific subtree red" );
2025 _tools_menu.add( _taxcolor_item = new JMenuItem( "Taxonomy Colorize Branches" ) );
2026 customizeJMenuItem( _taxcolor_item );
2027 _tools_menu.addSeparator();
2028 _tools_menu.add( _remove_visual_styles_item = new JMenuItem( "Delete All Visual Styles From Nodes" ) );
2029 _remove_visual_styles_item
2030 .setToolTipText( "To remove all node visual styles (fonts, colors) from the current phylogeny" );
2031 customizeJMenuItem( _remove_visual_styles_item );
2032 _tools_menu.add( _remove_branch_color_item = new JMenuItem( "Delete All Colors From Branches" ) );
2033 _remove_branch_color_item.setToolTipText( "To remove all branch color values from the current phylogeny" );
2034 customizeJMenuItem( _remove_branch_color_item );
2035 _tools_menu.addSeparator();
2036 _tools_menu.add( _annotate_item = new JMenuItem( "Annotate Sequences of Selected Nodes" ) );
2037 customizeJMenuItem( _annotate_item );
2038 _tools_menu.addSeparator();
2039 _tools_menu.add( _midpoint_root_item = new JMenuItem( "Midpoint-Root" ) );
2040 customizeJMenuItem( _midpoint_root_item );
2041 _tools_menu.addSeparator();
2042 _tools_menu.add( _delete_selected_nodes_item = new JMenuItem( "Delete Selected Nodes" ) );
2043 _delete_selected_nodes_item.setToolTipText( "To delete all selected external nodes" );
2044 customizeJMenuItem( _delete_selected_nodes_item );
2045 _tools_menu.add( _delete_not_selected_nodes_item = new JMenuItem( "Retain Selected Nodes" ) );
2046 _delete_not_selected_nodes_item.setToolTipText( "To delete all not selected external nodes" );
2047 customizeJMenuItem( _delete_not_selected_nodes_item );
2048 _tools_menu.addSeparator();
2049 _tools_menu.add( _collapse_species_specific_subtrees = new JMenuItem( "Collapse Single Taxonomy-Subtrees" ) );
2050 customizeJMenuItem( _collapse_species_specific_subtrees );
2051 _collapse_species_specific_subtrees.setToolTipText( "To (reversibly) collapse subtrees associated with only one taxonomy (such as species specific subtrees)" );
2053 .add( _collapse_below_threshold = new JMenuItem( "Collapse Branches with Confidence Below Threshold into Multifurcations" ) );
2054 customizeJMenuItem( _collapse_below_threshold );
2055 _collapse_below_threshold
2056 .setToolTipText( "To (permanently) collapse branches with confidence values below a threshold into multifurcations (in the case of multiple confidences per branch: without at least one confidence value above a threshold)" );
2059 .add( _collapse_below_branch_length = new JMenuItem( "Collapse Branches with Branch Lengths Below Threshold into Multifurcations" ) );
2060 customizeJMenuItem( _collapse_below_branch_length );
2061 _collapse_below_branch_length
2062 .setToolTipText( "To (permanently) collapse branches with branches with branch lengths below a threshold into multifurcations" );
2064 _tools_menu.addSeparator();
2066 .add( _extract_tax_code_from_node_names_jmi = new JMenuItem( "Extract Taxonomic Data from Node Names" ) );
2067 customizeJMenuItem( _extract_tax_code_from_node_names_jmi );
2068 _extract_tax_code_from_node_names_jmi
2069 .setToolTipText( "To extract SwissProt/Uniprot taxonomic codes (mnemonics) from nodes names in the form of 'xyz_CAEEL', Uniprot/NCBI identifiers form of 'xyz_6239', or scientific names form of 'xyz_Caenorhabditis_elegans'" );
2071 .add( _move_node_names_to_tax_sn_jmi = new JMenuItem( "Transfer Node Names to Taxonomic Scientific Names" ) );
2072 customizeJMenuItem( _move_node_names_to_tax_sn_jmi );
2073 _move_node_names_to_tax_sn_jmi.setToolTipText( "To interpret node names as taxonomic scientific names" );
2074 _tools_menu.add( _move_node_names_to_seq_names_jmi = new JMenuItem( "Transfer Node Names to Sequence Names" ) );
2075 customizeJMenuItem( _move_node_names_to_seq_names_jmi );
2076 _move_node_names_to_seq_names_jmi.setToolTipText( "To interpret node names as sequence (protein, gene) names" );
2077 _tools_menu.addSeparator();
2078 _tools_menu.add( _obtain_seq_information_jmi = new JMenuItem( "Obtain Sequence Information" ) );
2079 customizeJMenuItem( _obtain_seq_information_jmi );
2080 _obtain_seq_information_jmi.setToolTipText( "To add additional sequence information" );
2082 .add( _obtain_detailed_taxonomic_information_jmi = new JMenuItem( OBTAIN_DETAILED_TAXONOMIC_INFORMATION ) );
2083 customizeJMenuItem( _obtain_detailed_taxonomic_information_jmi );
2084 _obtain_detailed_taxonomic_information_jmi
2085 .setToolTipText( "To add additional taxonomic information (from UniProt Taxonomy)" );
2087 .add( _obtain_detailed_taxonomic_information_deleting_jmi = new JMenuItem( "Obtain Detailed Taxonomic Information (deletes nodes!)" ) );
2088 customizeJMenuItem( _obtain_detailed_taxonomic_information_deleting_jmi );
2089 _obtain_detailed_taxonomic_information_deleting_jmi
2090 .setToolTipText( "To add additional taxonomic information, deletes nodes for which taxonomy cannot found (from UniProt Taxonomy)" );
2091 _tools_menu.addSeparator();
2092 _tools_menu.add( _read_values_jmi = new JMenuItem( "Attach Vector/Expression Values" ) );
2093 customizeJMenuItem( _read_values_jmi );
2094 _read_values_jmi.setToolTipText( "To attach vector (e.g. gene expression) values to tree nodes (beta)" );
2095 _jmenubar.add( _tools_menu );
2096 _tools_menu.add( _read_seqs_jmi = new JMenuItem( "Attach Molecular Sequences" ) );
2097 customizeJMenuItem( _read_seqs_jmi );
2099 .setToolTipText( "To attach molecular sequences to tree nodes (from Fasta-formatted file) (beta)" );
2100 _jmenubar.add( _tools_menu );
2105 if ( isUnsavedDataPresent() ) {
2106 final int r = JOptionPane.showConfirmDialog( getThisFrame(),
2107 "Exit despite potentially unsaved changes?",
2109 JOptionPane.YES_NO_OPTION );
2110 if ( r != JOptionPane.YES_OPTION ) {
2118 removeAllTextFrames();
2119 _mainpanel.terminate();
2120 _contentpane.removeAll();
2121 setVisible( false );
2123 // System.exit( 0 ); //TODO reconfirm that this is OK, then remove.
2126 void readPhylogeniesFromURL() {
2128 Phylogeny[] phys = null;
2129 final String message = "Please enter a complete URL, for example \"http://purl.org/phylo/treebase/phylows/study/TB2:S15480?format=nexus\"";
2130 final String url_string = JOptionPane
2131 .showInputDialog( getThisFrame(),
2133 "Use URL/webservice to obtain a phylogeny",
2134 JOptionPane.QUESTION_MESSAGE );
2135 boolean nhx_or_nexus = false;
2136 if ( ( url_string != null ) && ( url_string.length() > 0 ) ) {
2138 url = new URL( url_string );
2139 PhylogenyParser parser = null;
2140 if ( url.getHost().toLowerCase().indexOf( "tolweb" ) >= 0 ) {
2141 parser = new TolParser();
2144 parser = ParserUtils
2145 .createParserDependingOnUrlContents( url,
2146 getConfiguration().isValidatePhyloXmlAgainstSchema() );
2148 if ( parser instanceof NexusPhylogeniesParser ) {
2149 nhx_or_nexus = true;
2151 else if ( parser instanceof NHXParser ) {
2152 nhx_or_nexus = true;
2154 if ( _mainpanel.getCurrentTreePanel() != null ) {
2155 _mainpanel.getCurrentTreePanel().setWaitCursor();
2158 _mainpanel.setWaitCursor();
2160 final PhylogenyFactory factory = ParserBasedPhylogenyFactory.getInstance();
2161 phys = factory.create( url.openStream(), parser );
2163 catch ( final MalformedURLException e ) {
2164 JOptionPane.showMessageDialog( getThisFrame(),
2165 "Malformed URL: " + url + "\n" + e.getLocalizedMessage(),
2167 JOptionPane.ERROR_MESSAGE );
2169 catch ( final IOException e ) {
2170 JOptionPane.showMessageDialog( getThisFrame(),
2171 "Could not read from " + url + "\n"
2172 + ForesterUtil.wordWrap( e.getLocalizedMessage(), 80 ),
2173 "Failed to read URL",
2174 JOptionPane.ERROR_MESSAGE );
2176 catch ( final Exception e ) {
2177 JOptionPane.showMessageDialog( getThisFrame(),
2178 ForesterUtil.wordWrap( e.getLocalizedMessage(), 80 ),
2179 "Unexpected Exception",
2180 JOptionPane.ERROR_MESSAGE );
2183 if ( _mainpanel.getCurrentTreePanel() != null ) {
2184 _mainpanel.getCurrentTreePanel().setArrowCursor();
2187 _mainpanel.setArrowCursor();
2190 if ( ( phys != null ) && ( phys.length > 0 ) ) {
2191 if ( nhx_or_nexus && getOptions().isInternalNumberAreConfidenceForNhParsing() ) {
2192 for( final Phylogeny phy : phys ) {
2193 PhylogenyMethods.transferInternalNodeNamesToConfidence( phy, "" );
2196 AptxUtil.addPhylogeniesToTabs( phys,
2197 new File( url.getFile() ).getName(),
2198 new File( url.getFile() ).toString(),
2201 _mainpanel.getControlPanel().showWhole();
2204 activateSaveAllIfNeeded();
2208 void setMsa( final Msa msa ) {
2212 void setMsaFile( final File msa_file ) {
2213 _msa_file = msa_file;
2216 void setSeqs( final List<MolecularSequence> seqs ) {
2220 void setSeqsFile( final File seqs_file ) {
2221 _seqs_file = seqs_file;
2224 public static MainFrameApplication createInstance( final Phylogeny[] phys, final Configuration config ) {
2225 return new MainFrameApplication( phys, config );
2228 public static MainFrame createInstance( final Phylogeny[] phys,
2229 final Configuration config,
2231 final File current_dir ) {
2232 return new MainFrameApplication( phys, config, title, current_dir );
2235 static MainFrame createInstance( final Phylogeny[] phys, final Configuration config, final String title ) {
2236 return new MainFrameApplication( phys, config, title );
2239 static MainFrame createInstance( final Phylogeny[] phys, final String config_file_name, final String title ) {
2240 return new MainFrameApplication( phys, config_file_name, title );
2243 static void warnIfNotPhyloXmlValidation( final Configuration c ) {
2244 if ( !c.isValidatePhyloXmlAgainstSchema() ) {
2245 JOptionPane.showMessageDialog( null,
2246 ForesterUtil.wordWrap(
2247 "phyloXML XSD-based validation is turned off [enable with line 'validate_against_phyloxml_xsd_schem: true' in configuration file]",
2250 JOptionPane.WARNING_MESSAGE );
2253 } // MainFrameApplication.