3f1af3462ff2ed13f612240806b76d2777397831
[jalview.git] / forester / java / src / org / forester / application / support_transfer.java
1 // $Id:
2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
4 //
5 // Copyright (C) 2008-2009 Christian M. Zmasek
6 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
7 // All rights reserved
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 //
23 // Contact: phylosoft @ gmail . com
24 // WWW: www.phylosoft.org/forester
25
26 package org.forester.application;
27
28 import java.io.File;
29 import java.io.IOException;
30 import java.util.List;
31
32 import org.forester.io.parsers.PhylogenyParser;
33 import org.forester.io.parsers.nhx.NHXParser;
34 import org.forester.io.parsers.util.ParserUtils;
35 import org.forester.io.writers.PhylogenyWriter;
36 import org.forester.phylogeny.Phylogeny;
37 import org.forester.phylogeny.PhylogenyMethods;
38 import org.forester.phylogeny.PhylogenyNode;
39 import org.forester.phylogeny.data.Confidence;
40 import org.forester.phylogeny.data.PhylogenyDataUtil;
41 import org.forester.phylogeny.factories.ParserBasedPhylogenyFactory;
42 import org.forester.phylogeny.factories.PhylogenyFactory;
43 import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
44
45 public final class support_transfer {
46
47     /**
48      * Transfers branch length values from one Phylogeny to another. It is
49      * mainly a "main method" for method "copyBranchLengthValuesFrom( Phylogeny )"
50      * of org.forester.phylogeny.Phylogeny, to be used in other (Perl) programs.
51      * 
52      * @param args[0]
53      *            Filename (String) for Phylogeny which has correct branch
54      *            length values
55      * @param args[1]
56      *            String Filename (String) for Phylogeny to which the branch
57      *            lengths of the first Phylogeny are to be copied, both Trees
58      *            must only differ in their branch length values, i.e. topology
59      *            and sequence names, etc. must be the same
60      * @param args[2]
61      *            String Filename (String) for outputfile
62      * @param args[3]
63      *            String [number of tree with correct bl to use in case treefile contains more than one, default 0]            
64      
65      */
66     public static void main( final String args[] ) {
67         Phylogeny phylogeny_w_bl = null; // Has correct branch lengths
68         Phylogeny phylogeny_w_support_vals = null; // Has bootsrap in the b.l.
69         // field (will be
70         // transferred
71         // to the bootstrap field by the Phylogeny constructor) or
72         // has regular boostraps (NHX, :B=...).
73         File infile_bl = null;
74         File infile_support_vals = null;
75         File outfile = null;
76         int index_of_tree_w_bl = 0;
77         if ( ( args.length != 3 ) && ( args.length != 4 ) ) {
78             System.err.println( "SupportTransfer: Wrong number" + " of arguments. Usage: \"java transfersBranchLenghts"
79                     + " <treefile with correct b.l.> <treefile with bootstraps>" + "<outputfile> "
80                     + "[number of tree with correct bl to use in case treefile contains more than one, default 0]\"" );
81             System.exit( -1 );
82         }
83         if ( args.length == 4 ) {
84             index_of_tree_w_bl = ( new Integer( args[ 3 ] ) ).intValue();
85         }
86         try {
87             infile_bl = new File( args[ 0 ] );
88             infile_support_vals = new File( args[ 1 ] );
89             outfile = new File( args[ 2 ] );
90             if ( outfile.exists() ) {
91                 System.out.println( "transfersBranchLenghts: " + outfile.getAbsolutePath() + " does already exist." );
92                 System.exit( -1 );
93             }
94             final PhylogenyFactory factory = ParserBasedPhylogenyFactory.getInstance();
95             final PhylogenyParser pp_bl = ParserUtils.createParserDependingOnFileType( infile_bl, true );
96             final PhylogenyParser pp_s = ParserUtils.createParserDependingOnFileType( infile_support_vals, true );
97             if ( pp_bl instanceof NHXParser ) {
98                 ( ( NHXParser ) pp_bl ).setTaxonomyExtraction( NHXParser.TAXONOMY_EXTRACTION.YES );
99             }
100             phylogeny_w_bl = factory.create( infile_bl, pp_bl )[ index_of_tree_w_bl ];
101             phylogeny_w_support_vals = factory.create( infile_support_vals, pp_s )[ 0 ];
102         }
103         catch ( final IOException e ) {
104             System.out.println( "SupportTransfer: Could not read tree(s): " + e );
105             System.exit( -1 );
106         }
107         try {
108             final double max_bs = PhylogenyMethods.getMaximumConfidenceValue( phylogeny_w_support_vals );
109             PhylogenyMethods.normalizeBootstrapValues( phylogeny_w_support_vals, max_bs, 100 );
110             support_transfer.transferSupportValues( phylogeny_w_support_vals, phylogeny_w_bl );
111         }
112         catch ( final IllegalArgumentException e ) {
113             System.out.println( e.getMessage() );
114             System.exit( -1 );
115         }
116         try {
117             final PhylogenyWriter writer = new PhylogenyWriter();
118             writer.toPhyloXML( outfile, phylogeny_w_bl, 0 );
119         }
120         catch ( final IOException e ) {
121             System.out.println( "Failure to write phylogeny \'" + outfile + "\" [" + e.getMessage() + "]" );
122             System.exit( -1 );
123         }
124     }
125
126     /**
127      * Moves the values in the branch length field to the bootstrap field, for
128      * each PhylogenyNode of this Phylogeny. Converts a Phylogeny originating
129      * from a phylip treefile after bootstrapping and which therefore has its
130      * bootstrap values where the branch lenghts would be.
131      */
132     public final static void moveBranchLengthsToBootstrap( final Phylogeny p ) {
133         for( final PhylogenyNodeIterator iter = p.iteratorPreorder(); iter.hasNext(); ) {
134             final PhylogenyNode node = iter.next();
135             if ( node.isInternal() && ( node.getDistanceToParent() > 0 ) ) {
136                 PhylogenyMethods.setBootstrapConfidence( node, node.getDistanceToParent() );
137             }
138             else {
139                 PhylogenyMethods.setBootstrapConfidence( node, Confidence.CONFIDENCE_DEFAULT_VALUE );
140             }
141             node.setDistanceToParent( PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT );
142         }
143     } // moveBranchLengthsToBootstrap()
144
145     /**
146      * Modifies Phylogeny to with the support values from Phylogeny from.
147      * Important (but obvious): The topology of both trees needs to be the same.
148      * The method is not robust, and might produce wrong results if the internal
149      * topology differs or if the external node names are not unique.
150      * 
151      * @param from
152      *            the Phylogeny to copy the support values from
153      * @param to
154      *            the Phylogeny to copy the support values to
155      */
156     public final static void transferSupportValues( final Phylogeny from, final Phylogeny to ) {
157         to: for( final PhylogenyNodeIterator it_to = to.iteratorPostorder(); it_to.hasNext(); ) {
158             final PhylogenyNode node_to = it_to.next();
159             if ( !node_to.isExternal() ) {
160                 final List<String> ext_children_to = node_to.getAllExternalDescendantsNames();
161                 for( final PhylogenyNodeIterator it_from = from.iteratorPostorder(); it_from.hasNext(); ) {
162                     final PhylogenyNode node_from = it_from.next();
163                     final List<String> ext_children_from = node_from.getAllExternalDescendantsNames();
164                     if ( ( ext_children_from.size() == ext_children_to.size() )
165                             && ext_children_from.containsAll( ext_children_to ) ) {
166                         PhylogenyMethods.setBootstrapConfidence( node_to,
167                                                                  PhylogenyMethods.getConfidenceValue( node_from ) );
168                         continue to;
169                     }
170                 }
171                 final String message = "Attempt to transfer support values from nonidentical topologies";
172                 throw new IllegalArgumentException( message );
173             }
174         }
175     }
176 }