in progress
[jalview.git] / forester / java / src / org / forester / application / confadd.java
1 // $Id:
2 //
3 // FORESTER -- software libraries and applications
4 // for evolutionary biology research and applications.
5 //
6 // Copyright (C) 2008-2009 Christian M. Zmasek
7 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
8 // All rights reserved
9 //
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.
14 //
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.
19 //
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
23 //
24 // Contact: phylosoft @ gmail . com
25 // WWW: www.phylosoft.org/forester
26
27 package org.forester.application;
28
29 import java.io.File;
30 import java.io.IOException;
31 import java.util.ArrayList;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Set;
35
36 import org.forester.io.parsers.util.ParserUtils;
37 import org.forester.io.writers.PhylogenyWriter;
38 import org.forester.phylogeny.Phylogeny;
39 import org.forester.phylogeny.PhylogenyNode;
40 import org.forester.phylogeny.factories.ParserBasedPhylogenyFactory;
41 import org.forester.phylogeny.factories.PhylogenyFactory;
42 import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
43 import org.forester.tools.ConfidenceAssessor;
44 import org.forester.util.CommandLineArguments;
45 import org.forester.util.ForesterUtil;
46
47 public class confadd {
48
49     final static private String HELP_OPTION_1    = "help";
50     final static private String HELP_OPTION_2    = "h";
51     final static private String FIRST_OPTION     = "f";
52     final static private String LAST_OPTION      = "l";
53     final static private String STRICT_OPTION    = "s";
54     final static private String NORMALIZE_OPTION = "n";
55     final static private String PRG_NAME         = "confadd";
56     final static private String PRG_VERSION      = "1.01";
57     final static private String PRG_DATE         = "2010.10.26";
58     final static private String E_MAIL           = "phylosoft@gmail.com";
59     final static private String WWW              = "www.phylosoft.org/forester/";
60
61     public static void main( final String args[] ) {
62          ForesterUtil.printProgramInformation( PRG_NAME, null, PRG_VERSION, PRG_DATE, E_MAIL, WWW, ForesterUtil.getForesterLibraryInformation() );
63         
64         CommandLineArguments cla = null;
65         try {
66             cla = new CommandLineArguments( args );
67         }
68         catch ( final Exception e ) {
69             ForesterUtil.fatalError( PRG_NAME, e.getMessage() );
70         }
71         if ( cla.isOptionSet( HELP_OPTION_1 ) || cla.isOptionSet( HELP_OPTION_2 ) || ( args.length == 0 ) ) {
72             printHelp();
73             System.exit( 0 );
74         }
75         if ( args.length < 4 ) {
76             System.out.println();
77             System.out.println( "[" + PRG_NAME + "] incorrect number of arguments" );
78             System.out.println();
79             printHelp();
80             System.exit( -1 );
81         }
82         if ( cla.getNumberOfNames() != 4 ) {
83             System.out.println();
84             System.out.println( "[" + PRG_NAME + "] incorrect number of arguments" );
85             System.out.println();
86             printHelp();
87             System.exit( -1 );
88         }
89         final List<String> allowed_options = new ArrayList<String>();
90         allowed_options.add( FIRST_OPTION );
91         allowed_options.add( LAST_OPTION );
92         allowed_options.add( STRICT_OPTION );
93         allowed_options.add( NORMALIZE_OPTION );
94         final String dissallowed_options = cla.validateAllowedOptionsAsString( allowed_options );
95         if ( dissallowed_options.length() > 0 ) {
96             ForesterUtil.fatalError( PRG_NAME, "unknown option(s): " + dissallowed_options );
97         }
98         final String confidence_type = cla.getName( 0 );
99         final File target_file = cla.getFile( 1 );
100         final File evaluators_file = cla.getFile( 2 );
101         final File outfile = cla.getFile( 3 );
102         if ( ForesterUtil.isEmpty( confidence_type ) ) {
103             ForesterUtil.fatalError( PRG_NAME, "attempt to use empty confidence type" );
104         }
105         if ( outfile.exists() ) {
106             ForesterUtil.fatalError( PRG_NAME, "[" + outfile + "] already exists" );
107         }
108         if ( !target_file.exists() ) {
109             ForesterUtil.fatalError( PRG_NAME, "target [" + target_file + "] does not exist" );
110         }
111         if ( !evaluators_file.exists() ) {
112             ForesterUtil.fatalError( PRG_NAME, "evaluators [" + evaluators_file + "] does not exist" );
113         }
114         boolean strict = false;
115         int first = 0;
116         int last = 0;
117         double norm = 0;
118         try {
119             if ( cla.isOptionSet( STRICT_OPTION ) ) {
120                 if ( cla.isOptionHasAValue( STRICT_OPTION ) ) {
121                     ForesterUtil.fatalError( PRG_NAME, "no value allowed for -" + STRICT_OPTION + " allowed" );
122                 }
123                 strict = true;
124             }
125             if ( cla.isOptionSet( FIRST_OPTION ) ) {
126                 first = cla.getOptionValueAsInt( FIRST_OPTION );
127             }
128             if ( cla.isOptionSet( LAST_OPTION ) ) {
129                 last = cla.getOptionValueAsInt( LAST_OPTION );
130             }
131             if ( cla.isOptionSet( NORMALIZE_OPTION ) ) {
132                 norm = cla.getOptionValueAsDouble( NORMALIZE_OPTION );
133             }
134         }
135         catch ( final Exception e ) {
136             ForesterUtil.fatalError( PRG_NAME, "error in command line: " + e.getLocalizedMessage() );
137         }
138         if ( ( first < 0 ) || ( last < 0 ) ) {
139             ForesterUtil
140                     .fatalError( PRG_NAME,
141                                  "attempt to set first or last evaluator topology to use to a number less than zero" );
142         }
143         if ( norm < 0 ) {
144             ForesterUtil.fatalError( PRG_NAME, "illegal value for normalizer [" + norm + "]" );
145         }
146         Phylogeny[] targets = null;
147         Phylogeny[] evaluators = null;
148         final PhylogenyFactory factory = ParserBasedPhylogenyFactory.getInstance();
149         try {
150             targets = factory.create( target_file, ParserUtils.createParserDependingOnFileType( target_file, true ) );
151         }
152         catch ( final IOException e ) {
153             ForesterUtil.fatalError( PRG_NAME,
154                                      "failed to read target phylogenies from [" + target_file + "]: "
155                                              + e.getLocalizedMessage() );
156         }
157         int counter = 0;
158         for( final Phylogeny target : targets ) {
159             try {
160                 checkUniquenessOfExternalNodes( target, "target " + counter );
161             }
162             catch ( final IllegalArgumentException e ) {
163                 ForesterUtil.fatalError( PRG_NAME, e.getLocalizedMessage() );
164             }
165             counter++;
166         }
167         if ( targets.length == 1 ) {
168             ForesterUtil.programMessage( PRG_NAME, "read in one target" );
169         }
170         else {
171             ForesterUtil.programMessage( PRG_NAME, "read in a total of " + targets.length + " targets" );
172         }
173         try {
174             evaluators = factory.create( evaluators_file,
175                                          ParserUtils.createParserDependingOnFileType( evaluators_file, true ) );
176         }
177         catch ( final IOException e ) {
178             ForesterUtil.fatalError( PRG_NAME, "failed to read evaluator topologies from [" + evaluators_file + "]: "
179                     + e.getLocalizedMessage() );
180         }
181         counter = 0;
182         for( final Phylogeny evaluator : evaluators ) {
183             try {
184                 checkUniquenessOfExternalNodes( evaluator, "evaluator " + counter );
185             }
186             catch ( final IllegalArgumentException e ) {
187                 ForesterUtil.fatalError( PRG_NAME, e.getLocalizedMessage() );
188             }
189             counter++;
190         }
191         ForesterUtil.programMessage( PRG_NAME, "read in a total of " + evaluators.length + " evaluator topologies" );
192         System.gc();
193         if ( last == 0 ) {
194             last = evaluators.length - 1;
195         }
196         if ( ( last >= evaluators.length ) || ( last <= first ) ) {
197             ForesterUtil.fatalError( PRG_NAME, "illegal value for first or last evaluator topology to use [" + first
198                     + ", " + last + "]" );
199         }
200         double value = 1;
201         if ( norm > 0 ) {
202             value = norm / ( 1 + last - first );
203         }
204         ForesterUtil.programMessage( PRG_NAME, "first topology to use: " + first );
205         String is_last = "";
206         if ( last == ( evaluators.length - 1 ) ) {
207             is_last = " (corresponds to last topology in file)";
208         }
209         ForesterUtil.programMessage( PRG_NAME, "last topology to use : " + last + is_last );
210         ForesterUtil.programMessage( PRG_NAME, "sum of topologies used as evaluators: " + ( last - first + 1 ) );
211         if ( norm > 0 ) {
212             ForesterUtil.programMessage( PRG_NAME, "normalizer: " + norm + " (" + ForesterUtil.round( value, 6 ) + ")" );
213         }
214         else {
215             ForesterUtil.programMessage( PRG_NAME, "normalizer: n/a" );
216         }
217         ForesterUtil.programMessage( PRG_NAME, "strict: " + strict );
218         for( final Phylogeny target : targets ) {
219             try {
220                 ConfidenceAssessor.evaluate( confidence_type, evaluators, target, strict, value, first, last );
221             }
222             catch ( final IllegalArgumentException e ) {
223                 ForesterUtil.fatalError( PRG_NAME, e.getLocalizedMessage() );
224             }
225         }
226         try {
227             final PhylogenyWriter writer = new PhylogenyWriter();
228             writer.toPhyloXML( targets, 0, outfile, ForesterUtil.LINE_SEPARATOR );
229         }
230         catch ( final IOException e ) {
231             ForesterUtil.fatalError( PRG_NAME, "failed to write to [" + outfile + "]: " + e.getLocalizedMessage() );
232         }
233         ForesterUtil.programMessage( PRG_NAME, "wrote output to: [" + outfile + "]" );
234         ForesterUtil.programMessage( PRG_NAME, "OK" );
235         System.out.println();
236     }
237
238     private static void printHelp() {
239         System.out.println( "Usage:" );
240         System.out.println();
241         System.out.println( PRG_NAME
242                 + " [options] <confidence type> <target tree file> <evaluators tree file> <outfile>" );
243         System.out.println();
244         System.out.println( "options:" );
245         System.out.println();
246         System.out.println( " -" + STRICT_OPTION
247                 + "    : strict [default: non-strict]: all nodes between 'target' and 'evaluators' must match" );
248         System.out.println( " -" + NORMALIZE_OPTION
249                 + "=<d>: normalize to this value (e.g. 100 for most bootstrap analyses) [default: no normalization]" );
250         System.out.println( " -" + FIRST_OPTION + "=<i>: first evaluator topology to use (0-based) [default: 0]" );
251         System.out.println( " -" + LAST_OPTION
252                 + "=<i>: last evaluator topology to use (0-based) [default: use all until final topology]" );
253         System.out.println();
254     }
255
256     private static void checkUniquenessOfExternalNodes( final Phylogeny phy, final String msg )
257             throws IllegalArgumentException {
258         final Set<PhylogenyNode> ext_nodes = new HashSet<PhylogenyNode>( phy.getNumberOfExternalNodes() );
259         for( final PhylogenyNodeIterator it = phy.iteratorExternalForward(); it.hasNext(); ) {
260             final PhylogenyNode node = it.next();
261             if ( ext_nodes.contains( node ) ) {
262                 throw new IllegalArgumentException( "external node [" + node.toString() + "] of " + msg
263                         + " is not unique" );
264             }
265             ext_nodes.add( node );
266         }
267     }
268 }