initial commit
[jalview.git] / forester / java / src / org / forester / application / phyloxml_converter.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.List;
33
34 import org.forester.io.parsers.PhylogenyParser;
35 import org.forester.io.parsers.nexus.NexusPhylogeniesParser;
36 import org.forester.io.parsers.nhx.NHXParser;
37 import org.forester.io.writers.PhylogenyWriter;
38 import org.forester.phylogeny.Phylogeny;
39 import org.forester.phylogeny.PhylogenyMethods;
40 import org.forester.phylogeny.PhylogenyNode;
41 import org.forester.phylogeny.factories.ParserBasedPhylogenyFactory;
42 import org.forester.phylogeny.factories.PhylogenyFactory;
43 import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
44 import org.forester.util.CommandLineArguments;
45 import org.forester.util.ForesterUtil;
46 import org.forester.util.ForesterUtil.PhylogenyNodeField;
47
48 public class phyloxml_converter {
49
50     final static private String  HELP_OPTION_1                    = "help";
51     final static private String  HELP_OPTION_2                    = "h";
52     final static private String  FIELD_OPTION                     = "f";
53     final static private String  FIELD_CLADE_NAME                 = "nn";
54     final static private String  FIELD_TAXONOMY_CODE              = "tc";
55     final static private String  FIELD_TAXONOMY_SCI_NAME          = "sn";
56     final static private String  FIELD_TAXONOMY_COMM_NAME         = "cn";
57     final static private String  FIELD_SEQUENCE_GENE_NAME         = "gn";
58     final static private String  FIELD_SEQUENCE_SYMBOL            = "sy";
59     final static private String  FIELD_DUMMY                      = "dummy";
60     final static private String  INTERNAL_NAMES_ARE_BOOT_SUPPPORT = "i";
61     final static private String  MIDPOINT_REROOT                  = "m";
62     final static private String  EXTRACT_TAXONOMY                 = "xt";
63     final static private String  EXTRACT_TAXONOMY_PF              = "xp";
64     final static private String  ORDER_SUBTREES                   = "o";
65     final static private String  NO_TREE_LEVEL_INDENDATION        = "ni";
66     final static private String  REPLACE_UNDER_SCORES             = "ru";
67     final static private String  PRG_NAME                         = "phyloxml_converter";
68     final static private String  PRG_VERSION                      = "1.21";
69     final static private String  PRG_DATE                         = "2010.10.02";
70     final static private String  E_MAIL                           = "czmasek@burnham.org";
71     final static private String  WWW                              = "www.phylosoft.org/forester/";
72     final static private boolean SPECIAL                          = false;
73
74     public static void main( final String args[] ) {
75         ForesterUtil.printProgramInformation( PRG_NAME, PRG_VERSION, PRG_DATE, E_MAIL, WWW );
76         CommandLineArguments cla = null;
77         try {
78             cla = new CommandLineArguments( args );
79         }
80         catch ( final Exception e ) {
81             ForesterUtil.fatalError( PRG_NAME, e.getMessage() );
82         }
83         if ( cla.isOptionSet( HELP_OPTION_1 ) || cla.isOptionSet( HELP_OPTION_2 ) || ( args.length == 0 ) ) {
84             printHelp();
85             System.exit( 0 );
86         }
87         if ( args.length < 3 ) {
88             System.out.println();
89             System.out.println( "[" + PRG_NAME + "] incorrect number of arguments" );
90             System.out.println();
91             printHelp();
92             System.exit( -1 );
93         }
94         final List<String> allowed_options = new ArrayList<String>();
95         allowed_options.add( NO_TREE_LEVEL_INDENDATION );
96         allowed_options.add( FIELD_OPTION );
97         allowed_options.add( MIDPOINT_REROOT );
98         allowed_options.add( ORDER_SUBTREES );
99         allowed_options.add( INTERNAL_NAMES_ARE_BOOT_SUPPPORT );
100         allowed_options.add( REPLACE_UNDER_SCORES );
101         allowed_options.add( EXTRACT_TAXONOMY );
102         allowed_options.add( EXTRACT_TAXONOMY_PF );
103         if ( cla.getNumberOfNames() != 2 ) {
104             System.out.println();
105             System.out.println( "[" + PRG_NAME + "] incorrect number of arguments" );
106             System.out.println();
107             printHelp();
108             System.exit( -1 );
109         }
110         final String dissallowed_options = cla.validateAllowedOptionsAsString( allowed_options );
111         if ( dissallowed_options.length() > 0 ) {
112             ForesterUtil.fatalError( PRG_NAME, "unknown option(s): " + dissallowed_options );
113         }
114         final List<String> mandatory_options = new ArrayList<String>();
115         mandatory_options.add( FIELD_OPTION );
116         final String missing_options = cla.validateMandatoryOptionsAsString( mandatory_options );
117         if ( missing_options.length() > 0 ) {
118             ForesterUtil.fatalError( PRG_NAME, "missing option(s): " + missing_options );
119         }
120         if ( !cla.isOptionValueSet( FIELD_OPTION ) ) {
121             System.out.println();
122             printHelp();
123             System.exit( -1 );
124         }
125         final String field_option_value = cla.getOptionValue( FIELD_OPTION );
126         PhylogenyNodeField field = null;
127         if ( field_option_value.equals( FIELD_CLADE_NAME ) ) {
128             field = PhylogenyNodeField.CLADE_NAME;
129         }
130         else if ( field_option_value.equals( FIELD_TAXONOMY_CODE ) ) {
131             field = PhylogenyNodeField.TAXONOMY_CODE;
132         }
133         else if ( field_option_value.equals( FIELD_TAXONOMY_SCI_NAME ) ) {
134             field = PhylogenyNodeField.TAXONOMY_SCIENTIFIC_NAME;
135         }
136         else if ( field_option_value.equals( FIELD_TAXONOMY_COMM_NAME ) ) {
137             field = PhylogenyNodeField.TAXONOMY_COMMON_NAME;
138         }
139         else if ( field_option_value.equals( FIELD_SEQUENCE_GENE_NAME ) ) {
140             field = PhylogenyNodeField.SEQUENCE_NAME;
141         }
142         else if ( field_option_value.equals( FIELD_SEQUENCE_SYMBOL ) ) {
143             field = PhylogenyNodeField.SEQUENCE_SYMBOL;
144         }
145         else if ( field_option_value.equals( FIELD_DUMMY ) ) {
146         }
147         else {
148             ForesterUtil.fatalError( PRG_NAME, "unknown value for -\"" + FIELD_OPTION + "\" option: \""
149                     + field_option_value + "\"" );
150         }
151         boolean int_values_are_boots = false;
152         if ( cla.isOptionSet( INTERNAL_NAMES_ARE_BOOT_SUPPPORT ) ) {
153             int_values_are_boots = true;
154         }
155         boolean midpoint_reroot = false;
156         if ( cla.isOptionSet( MIDPOINT_REROOT ) ) {
157             midpoint_reroot = true;
158         }
159         boolean order_subtrees = false;
160         if ( cla.isOptionSet( ORDER_SUBTREES ) ) {
161             order_subtrees = true;
162         }
163         boolean replace_underscores = false;
164         if ( cla.isOptionSet( REPLACE_UNDER_SCORES ) ) {
165             replace_underscores = true;
166         }
167         boolean no_indendation = false;
168         if ( cla.isOptionSet( NO_TREE_LEVEL_INDENDATION ) ) {
169             no_indendation = true;
170         }
171         boolean extr_taxonomy = false;
172         if ( cla.isOptionSet( EXTRACT_TAXONOMY ) ) {
173             extr_taxonomy = true;
174         }
175         boolean extr_taxonomy_pf_only = false;
176         if ( cla.isOptionSet( EXTRACT_TAXONOMY_PF ) ) {
177             extr_taxonomy_pf_only = true;
178         }
179         final File infile = cla.getFile( 0 );
180         final File outfile = cla.getFile( 1 );
181         if ( outfile.exists() ) {
182             ForesterUtil.fatalError( PRG_NAME, "[" + outfile + "] already exists" );
183         }
184         if ( !infile.exists() ) {
185             ForesterUtil.fatalError( PRG_NAME, "[" + infile + "] does not exist" );
186         }
187         Phylogeny[] phys = null;
188         try {
189             final PhylogenyFactory factory = ParserBasedPhylogenyFactory.getInstance();
190             final PhylogenyParser parser = ForesterUtil.createParserDependingOnFileType( infile, true );
191             if ( parser instanceof NHXParser ) {
192                 if ( ( field != PhylogenyNodeField.TAXONOMY_CODE )
193                         && ( field != PhylogenyNodeField.TAXONOMY_COMMON_NAME )
194                         && ( field != PhylogenyNodeField.TAXONOMY_SCIENTIFIC_NAME ) ) {
195                     if ( extr_taxonomy_pf_only ) {
196                         ( ( NHXParser ) parser )
197                                 .setTaxonomyExtraction( ForesterUtil.TAXONOMY_EXTRACTION.PFAM_STYLE_ONLY );
198                         replace_underscores = false;
199                     }
200                     else if ( extr_taxonomy ) {
201                         ( ( NHXParser ) parser ).setTaxonomyExtraction( ForesterUtil.TAXONOMY_EXTRACTION.YES );
202                         replace_underscores = false;
203                     }
204                 }
205                 else {
206                     ( ( NHXParser ) parser ).setTaxonomyExtraction( ForesterUtil.TAXONOMY_EXTRACTION.NO );
207                 }
208                 ( ( NHXParser ) parser ).setReplaceUnderscores( replace_underscores );
209                 ( ( NHXParser ) parser ).setIgnoreQuotes( false );
210             }
211             else if ( parser instanceof NexusPhylogeniesParser ) {
212                 ( ( NexusPhylogeniesParser ) parser ).setReplaceUnderscores( replace_underscores );
213                 ( ( NexusPhylogeniesParser ) parser ).setIgnoreQuotes( false );
214             }
215             phys = factory.create( infile, parser );
216         }
217         catch ( final IOException e ) {
218             ForesterUtil.fatalError( PRG_NAME, "failed to read phylogeny from [" + infile + "]: " + e.getMessage() );
219         }
220         if ( SPECIAL ) {
221             for( final Phylogeny phy : phys ) {
222                 performSpecialProcessing( phy );
223             }
224         }
225         if ( int_values_are_boots ) {
226             for( final Phylogeny phy : phys ) {
227                 ForesterUtil.transferInternalNamesToBootstrapSupport( phy );
228             }
229         }
230         if ( field != null ) {
231             for( final Phylogeny phy : phys ) {
232                 ForesterUtil.transferNodeNameToField( phy, field );
233             }
234         }
235         if ( midpoint_reroot ) {
236             try {
237                 for( final Phylogeny phy : phys ) {
238                     PhylogenyMethods.midpointRoot( phy );
239                 }
240             }
241             catch ( final Exception e ) {
242                 System.out.println( "" );
243                 ForesterUtil.printWarningMessage( PRG_NAME, "midpoint rerooting failed: " + e.getLocalizedMessage() );
244             }
245         }
246         if ( order_subtrees ) {
247             for( final Phylogeny phy : phys ) {
248                 phy.orderAppearance( true );
249             }
250         }
251         try {
252             final PhylogenyWriter writer = new PhylogenyWriter();
253             if ( no_indendation ) {
254                 writer.setIndentPhyloxml( false );
255             }
256             writer.toPhyloXML( phys, 0, outfile, ForesterUtil.LINE_SEPARATOR );
257         }
258         catch ( final IOException e ) {
259             ForesterUtil.fatalError( PRG_NAME, "failed to write to [" + outfile + "]: " + e.getMessage() );
260         }
261         System.out.println( "[" + PRG_NAME + "] wrote: [" + outfile + "]" );
262         System.out.println( "[" + PRG_NAME + "] OK" );
263         System.out.println();
264     }
265
266     private static void performSpecialProcessing( final Phylogeny phy ) {
267         // Can place some kind of custom processing here.
268         //        final List<PhylogenyNode> remove_us = new ArrayList<PhylogenyNode>();
269         //        int counter = 0;
270         //        for( final PhylogenyNodeIterator it = phy.iteratorPostorder(); it.hasNext(); ) {
271         //            final PhylogenyNode node = it.next();
272         //            final String name = node.getNodeName().toLowerCase();
273         //            if ( name.startsWith( "environmental_samples" ) || name.startsWith( "unclassified" )
274         //                    || name.startsWith( "bacteria" ) || name.startsWith( "other" )
275         //                    || name.startsWith( "viroids" ) || name.startsWith( "viruses" ) ) {
276         //                remove_us.add( node );
277         //                System.out.println( counter++ );
278         //            }
279         //        }
280         //        phy.hashIDs();
281         //        for( final PhylogenyNode node : remove_us ) {
282         //            if ( phy.getNode( node.getNodeId() ) != null ) {
283         //                phy.deleteSubtree( node );
284         //                System.out.println( "deleted: " + node );
285         //            }
286         //        }
287         //        phy.hashIDs();
288         //
289         //        for( final PhylogenyNodeIterator it = phy.iteratorPostorder(); it.hasNext(); ) {
290         //            final PhylogenyNode node = it.next();
291         //            node.getNodeData().setTaxonomy( null );
292         //        }
293         //        phy.reRoot( phy.getFirstExternalNode() );
294         //        PhylogenyMethods.midpointRoot( phy );
295         //        phy.orderAppearance( true );
296         for( final PhylogenyNodeIterator it = phy.iteratorPostorder(); it.hasNext(); ) {
297             final PhylogenyNode node = it.next();
298             final String name = node.getName();
299             if ( !ForesterUtil.isEmpty( name ) ) {
300                 //                final Taxonomy taxo = new Taxonomy();
301                 //                if ( node.isExternal() ) {
302                 //                    taxo.setTaxonomyCode( name );
303                 //                    node.getNodeData().setTaxonomy( taxo );
304                 //                }
305                 //                else if ( name.indexOf( '_' ) == -1 || name.length() > 6 ) {
306                 //                    taxo.setScientificName( name );
307                 //                    node.getNodeData().setTaxonomy( taxo );
308                 //                }
309                 //                node.setName( "" );
310                 //                if ( name.indexOf( "BF" ) >= 0 ) {
311                 //                    taxo.setTaxonomyCode( "BACFR" );
312                 //                }
313                 //                else if ( name.indexOf( "BT" ) >= 0 ) {
314                 //                    taxo.setTaxonomyCode( "BACTN" );
315                 //                }
316                 //                else if ( name.indexOf( "MXAN" ) >= 0 ) {
317                 //                    taxo.setTaxonomyCode( "MYXXD" );
318                 //                }
319                 //                else if ( name.indexOf( "STIAU" ) >= 0 ) {
320                 //                    taxo.setTaxonomyCode( "STIAU" );
321                 //                }
322                 //                else if ( name.indexOf( "BOVA" ) >= 0 ) {
323                 //                    taxo.setTaxonomyCode( "BACOV" );
324                 //                }
325                 //                else if ( name.indexOf( "BUNI" ) >= 0 ) {
326                 //                    taxo.setTaxonomyCode( "BACUN" );
327                 //                }
328                 //                else if ( name.indexOf( "Pgin" ) >= 0 ) {
329                 //                    taxo.setTaxonomyCode( "PORGI" );
330                 //                }
331                 //                else if ( name.equals( "3CGH" ) || name.equals( "3CK7" ) ) {
332                 //                    taxo.setTaxonomyCode( "BACTN" );
333                 //                }
334                 // node.getNodeData().setTaxonomy( taxo );
335             }
336         }
337     }
338
339     private static void printHelp() {
340         System.out.println( "Usage:" );
341         System.out.println();
342         System.out
343                 .println( PRG_NAME
344                         + " -"
345                         + FIELD_OPTION
346                         + "=<field option> [options] <infile in New Hamphshire, NHX, Nexus, ToL XML, or phyloXML format> <outfile>" );
347         System.out.println();
348         System.out.println( " field options: " );
349         System.out.println();
350         System.out.println( "   " + FIELD_CLADE_NAME + ": transfer name to node/clade name" );
351         System.out.println( "   " + FIELD_TAXONOMY_CODE + ": transfer name to taxonomy code" );
352         System.out.println( "   " + FIELD_TAXONOMY_SCI_NAME + ": transfer name to taxonomy scientific name" );
353         System.out.println( "   " + FIELD_TAXONOMY_COMM_NAME + ": transfer name to taxonomy common name" );
354         System.out.println( "   " + FIELD_SEQUENCE_GENE_NAME + ": transfer name to sequence name" );
355         System.out.println( "   " + FIELD_SEQUENCE_SYMBOL + ": transfer name to sequence symbol" );
356         System.out.println();
357         System.out.println( " options: " );
358         System.out.println( " -" + INTERNAL_NAMES_ARE_BOOT_SUPPPORT
359                 + " : internal names in NH or NHX tree are bootstrap support values" );
360         System.out.println( " -" + REPLACE_UNDER_SCORES + ": replace all underscores with spaces" );
361         System.out.println( " -" + MIDPOINT_REROOT + " : midpoint reroot" );
362         System.out.println( " -" + ORDER_SUBTREES + " : order subtrees" );
363         System.out
364                 .println( " -"
365                         + EXTRACT_TAXONOMY
366                         + ": extract taxonomy to taxonomy code from \"seqname_TAXON\"-style names (cannot be used with the following field options: "
367                         + FIELD_TAXONOMY_CODE + ", " + FIELD_TAXONOMY_COMM_NAME + ", " + FIELD_TAXONOMY_SCI_NAME + ")" );
368         System.out
369                 .println( " -"
370                         + EXTRACT_TAXONOMY_PF
371                         + ": extract taxonomy to taxonomy code from Pfam (\"seqname_TAXON/x-y\") style names only (cannot be used with the following field options: "
372                         + FIELD_TAXONOMY_CODE + ", " + FIELD_TAXONOMY_COMM_NAME + ", " + FIELD_TAXONOMY_SCI_NAME + ")" );
373         System.out.println( " -" + NO_TREE_LEVEL_INDENDATION + ": no tree level indendation in phyloXML output" );
374         System.out.println();
375     }
376 }