JAL-2847 needed methods made public
[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: https://sites.google.com/site/cmzmasek/home/software/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.parsers.phyloxml.PhyloXmlDataFormatException;
38 import org.forester.io.parsers.util.ParserUtils;
39 import org.forester.io.writers.PhylogenyWriter;
40 import org.forester.phylogeny.Phylogeny;
41 import org.forester.phylogeny.PhylogenyMethods;
42 import org.forester.phylogeny.PhylogenyMethods.DESCENDANT_SORT_PRIORITY;
43 import org.forester.phylogeny.factories.ParserBasedPhylogenyFactory;
44 import org.forester.phylogeny.factories.PhylogenyFactory;
45 import org.forester.util.CommandLineArguments;
46 import org.forester.util.ForesterUtil;
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_UNIPROT_TAXONOMY_ID_SPLIT_1 = "i1";
60     final static private String FIELD_UNIPROT_TAXONOMY_ID_SPLIT_2 = "i2";
61     final static private String FIELD_DUMMY                       = "dummy";
62     final static private String INTERNAL_NAMES_ARE_BOOT_SUPPPORT  = "i";
63     final static private String MIDPOINT_REROOT                   = "m";
64     final static private String EXTRACT_TAXONOMY                  = "xt";
65     final static private String EXTRACT_TAXONOMY_PF               = "xp";
66     final static private String ORDER_SUBTREES                    = "o";
67     final static private String NO_TREE_LEVEL_INDENDATION         = "ni";
68     final static private String REPLACE_UNDER_SCORES              = "ru";
69     final static private String IGNORE_QUOTES                     = "iqs";
70     final static private String CONFIDENCE_TYPE                   = "c";
71     final static private String PRG_NAME                          = "phyloxml_converter";
72     final static private String PRG_VERSION                       = "1.303";
73     final static private String PRG_DATE                          = "170510";
74     final static private String E_MAIL                            = "phyloxml@gmail.com";
75     final static private String WWW                               = "sites.google.com/site/cmzmasek/home/software/forester/phyloxml-converter";
76
77     public static void main( final String args[] ) throws PhyloXmlDataFormatException {
78         ForesterUtil.printProgramInformation( PRG_NAME, PRG_VERSION, PRG_DATE, E_MAIL, WWW );
79         CommandLineArguments cla = null;
80         try {
81             cla = new CommandLineArguments( args );
82         }
83         catch ( final Exception e ) {
84             ForesterUtil.fatalError( PRG_NAME, e.getMessage() );
85         }
86         if ( cla.isOptionSet( HELP_OPTION_1 ) || cla.isOptionSet( HELP_OPTION_2 ) || ( args.length == 0 ) ) {
87             printHelp();
88             System.exit( 0 );
89         }
90         if ( args.length < 3 ) {
91             System.out.println();
92             System.out.println( "[" + PRG_NAME + "] incorrect number of arguments" );
93             System.out.println();
94             printHelp();
95             System.exit( -1 );
96         }
97         final List<String> allowed_options = new ArrayList<String>();
98         allowed_options.add( NO_TREE_LEVEL_INDENDATION );
99         allowed_options.add( FIELD_OPTION );
100         allowed_options.add( MIDPOINT_REROOT );
101         allowed_options.add( ORDER_SUBTREES );
102         allowed_options.add( INTERNAL_NAMES_ARE_BOOT_SUPPPORT );
103         allowed_options.add( REPLACE_UNDER_SCORES );
104         allowed_options.add( EXTRACT_TAXONOMY );
105         allowed_options.add( EXTRACT_TAXONOMY_PF );
106         allowed_options.add( IGNORE_QUOTES );
107         allowed_options.add( CONFIDENCE_TYPE );
108         if ( cla.getNumberOfNames() != 2 ) {
109             System.out.println();
110             System.out.println( "[" + PRG_NAME + "] incorrect number of arguments" );
111             System.out.println();
112             printHelp();
113             System.exit( -1 );
114         }
115         final String dissallowed_options = cla.validateAllowedOptionsAsString( allowed_options );
116         if ( dissallowed_options.length() > 0 ) {
117             ForesterUtil.fatalError( PRG_NAME, "unknown option(s): " + dissallowed_options );
118         }
119         final List<String> mandatory_options = new ArrayList<String>();
120         mandatory_options.add( FIELD_OPTION );
121         final String missing_options = cla.validateMandatoryOptionsAsString( mandatory_options );
122         if ( missing_options.length() > 0 ) {
123             ForesterUtil.fatalError( PRG_NAME, "missing option(s): " + missing_options );
124         }
125         if ( !cla.isOptionValueSet( FIELD_OPTION ) ) {
126             System.out.println();
127             printHelp();
128             System.exit( -1 );
129         }
130         final String field_option_value = cla.getOptionValue( FIELD_OPTION );
131         PhylogenyMethods.PhylogenyNodeField field = null;
132         if ( field_option_value.equals( FIELD_CLADE_NAME ) ) {
133             field = PhylogenyMethods.PhylogenyNodeField.CLADE_NAME;
134         }
135         else if ( field_option_value.equals( FIELD_TAXONOMY_CODE ) ) {
136             field = PhylogenyMethods.PhylogenyNodeField.TAXONOMY_CODE;
137         }
138         else if ( field_option_value.equals( FIELD_TAXONOMY_SCI_NAME ) ) {
139             field = PhylogenyMethods.PhylogenyNodeField.TAXONOMY_SCIENTIFIC_NAME;
140         }
141         else if ( field_option_value.equals( FIELD_TAXONOMY_COMM_NAME ) ) {
142             field = PhylogenyMethods.PhylogenyNodeField.TAXONOMY_COMMON_NAME;
143         }
144         else if ( field_option_value.equals( FIELD_SEQUENCE_GENE_NAME ) ) {
145             field = PhylogenyMethods.PhylogenyNodeField.SEQUENCE_NAME;
146         }
147         else if ( field_option_value.equals( FIELD_SEQUENCE_SYMBOL ) ) {
148             field = PhylogenyMethods.PhylogenyNodeField.SEQUENCE_SYMBOL;
149         }
150         else if ( field_option_value.equals( FIELD_UNIPROT_TAXONOMY_ID_SPLIT_1 ) ) {
151             field = PhylogenyMethods.PhylogenyNodeField.TAXONOMY_ID_UNIPROT_1;
152         }
153         else if ( field_option_value.equals( FIELD_UNIPROT_TAXONOMY_ID_SPLIT_2 ) ) {
154             field = PhylogenyMethods.PhylogenyNodeField.TAXONOMY_ID_UNIPROT_2;
155         }
156         else if ( field_option_value.equals( FIELD_DUMMY ) ) {
157         }
158         else {
159             ForesterUtil
160                     .fatalError( PRG_NAME,
161                                  "unknown value for -\"" + FIELD_OPTION + "\" option: \"" + field_option_value + "\"" );
162         }
163         boolean ignore_quotes = false;
164         if ( cla.isOptionSet( IGNORE_QUOTES ) ) {
165             ignore_quotes = true;
166         }
167         boolean int_values_are_boots = false;
168         if ( cla.isOptionSet( INTERNAL_NAMES_ARE_BOOT_SUPPPORT ) ) {
169             int_values_are_boots = true;
170         }
171         String conf_type = "unknown";
172         if ( cla.isOptionSet( CONFIDENCE_TYPE ) ) {
173             final String str = cla.getOptionValueAsCleanString( CONFIDENCE_TYPE );
174             if ( !ForesterUtil.isEmpty( str ) ) {
175                 conf_type = str;
176             }
177         }
178         boolean midpoint_reroot = false;
179         if ( cla.isOptionSet( MIDPOINT_REROOT ) ) {
180             midpoint_reroot = true;
181         }
182         boolean order_subtrees = false;
183         if ( cla.isOptionSet( ORDER_SUBTREES ) ) {
184             order_subtrees = true;
185         }
186         boolean replace_underscores = false;
187         if ( cla.isOptionSet( REPLACE_UNDER_SCORES ) ) {
188             replace_underscores = true;
189         }
190         boolean no_indendation = false;
191         if ( cla.isOptionSet( NO_TREE_LEVEL_INDENDATION ) ) {
192             no_indendation = true;
193         }
194         boolean extr_taxonomy = false;
195         if ( cla.isOptionSet( EXTRACT_TAXONOMY ) ) {
196             extr_taxonomy = true;
197         }
198         boolean extr_taxonomy_pf_only = false;
199         if ( cla.isOptionSet( EXTRACT_TAXONOMY_PF ) ) {
200             extr_taxonomy_pf_only = true;
201         }
202         final File infile = cla.getFile( 0 );
203         final File outfile = cla.getFile( 1 );
204         if ( outfile.exists() ) {
205             ForesterUtil.fatalError( PRG_NAME, "[" + outfile + "] already exists" );
206         }
207         if ( !infile.exists() ) {
208             ForesterUtil.fatalError( PRG_NAME, "[" + infile + "] does not exist" );
209         }
210         Phylogeny[] phys = null;
211         try {
212             final PhylogenyFactory factory = ParserBasedPhylogenyFactory.getInstance();
213             final PhylogenyParser parser = ParserUtils.createParserDependingOnFileType( infile, true );
214             if ( parser instanceof NHXParser ) {
215                 if ( ( field != PhylogenyMethods.PhylogenyNodeField.TAXONOMY_CODE )
216                         && ( field != PhylogenyMethods.PhylogenyNodeField.TAXONOMY_COMMON_NAME )
217                         && ( field != PhylogenyMethods.PhylogenyNodeField.TAXONOMY_SCIENTIFIC_NAME ) ) {
218                     if ( extr_taxonomy_pf_only ) {
219                         ( ( NHXParser ) parser )
220                                 .setTaxonomyExtraction( NHXParser.TAXONOMY_EXTRACTION.PFAM_STYLE_STRICT );
221                         replace_underscores = false;
222                     }
223                     else if ( extr_taxonomy ) {
224                         ( ( NHXParser ) parser )
225                                 .setTaxonomyExtraction( NHXParser.TAXONOMY_EXTRACTION.PFAM_STYLE_RELAXED );
226                         replace_underscores = false;
227                     }
228                 }
229                 else {
230                     ( ( NHXParser ) parser ).setTaxonomyExtraction( NHXParser.TAXONOMY_EXTRACTION.NO );
231                 }
232                 ( ( NHXParser ) parser ).setReplaceUnderscores( replace_underscores );
233                 ( ( NHXParser ) parser ).setIgnoreQuotes( ignore_quotes );
234             }
235             else if ( parser instanceof NexusPhylogeniesParser ) {
236                 ( ( NexusPhylogeniesParser ) parser ).setReplaceUnderscores( replace_underscores );
237                 ( ( NexusPhylogeniesParser ) parser ).setIgnoreQuotes( false );
238             }
239             phys = factory.create( infile, parser );
240         }
241         catch ( final IOException e ) {
242             ForesterUtil.fatalError( PRG_NAME, "failed to read phylogeny from [" + infile + "]: " + e.getMessage() );
243         }
244         if ( int_values_are_boots ) {
245             for( final Phylogeny phy : phys ) {
246                 PhylogenyMethods.transferInternalNamesToConfidenceValues( phy, conf_type );
247             }
248         }
249         if ( field != null ) {
250             for( final Phylogeny phy : phys ) {
251                 PhylogenyMethods.transferNodeNameToField( phy, field, false );
252             }
253         }
254         if ( midpoint_reroot ) {
255             try {
256                 for( final Phylogeny phy : phys ) {
257                     PhylogenyMethods.midpointRoot( phy );
258                 }
259             }
260             catch ( final Exception e ) {
261                 System.out.println( "" );
262                 ForesterUtil.printWarningMessage( PRG_NAME, "midpoint rerooting failed: " + e.getLocalizedMessage() );
263             }
264         }
265         if ( order_subtrees ) {
266             for( final Phylogeny phy : phys ) {
267                 PhylogenyMethods.orderAppearance( phy.getRoot(), true, true, DESCENDANT_SORT_PRIORITY.TAXONOMY );
268                 phy.externalNodesHaveChanged();
269                 phy.clearHashIdToNodeMap();
270                 phy.recalculateNumberOfExternalDescendants( true );
271             }
272         }
273         try {
274             final PhylogenyWriter writer = new PhylogenyWriter();
275             if ( no_indendation ) {
276                 writer.setIndentPhyloxml( false );
277             }
278             writer.toPhyloXML( phys, 0, outfile, ForesterUtil.LINE_SEPARATOR );
279         }
280         catch ( final IOException e ) {
281             ForesterUtil.fatalError( PRG_NAME, "failed to write to [" + outfile + "]: " + e.getMessage() );
282         }
283         System.out.println( "[" + PRG_NAME + "] wrote: [" + outfile + "]" );
284         System.out.println( "[" + PRG_NAME + "] OK" );
285         System.out.println();
286     }
287
288     private static void printHelp() {
289         System.out.println( "Usage:" );
290         System.out.println();
291         System.out.println( PRG_NAME + " -" + FIELD_OPTION
292                 + "=<field option> [options] <infile in New Hamphshire, NHX, Nexus, ToL XML, or phyloXML format> <outfile>" );
293         System.out.println();
294         System.out.println( " field options: " );
295         System.out.println();
296         System.out.println( "   " + FIELD_CLADE_NAME + ":    transfer name to node/clade name" );
297         System.out.println( "   " + FIELD_TAXONOMY_CODE + ":    transfer name to taxonomy code" );
298         System.out.println( "   " + FIELD_TAXONOMY_SCI_NAME + ":    transfer name to taxonomy scientific name" );
299         System.out.println( "   " + FIELD_TAXONOMY_COMM_NAME + ":    transfer name to taxonomy common name" );
300         System.out.println( "   " + FIELD_SEQUENCE_GENE_NAME + ":    transfer name to sequence name" );
301         System.out.println( "   " + FIELD_SEQUENCE_SYMBOL + ":    transfer name to sequence symbol" );
302         System.out.println( "   " + FIELD_DUMMY + ": to convert NHX formatted trees to phyloXML" );
303         System.out.println( "   " + FIELD_UNIPROT_TAXONOMY_ID_SPLIT_1
304                 + ":    transfer/split name to taxonomy uniprot identifier" );
305         System.out.println( "          (split at underscore if \"id_name\" pattern, e.g. \"817_SusD\")" );
306         System.out.println( "   " + FIELD_UNIPROT_TAXONOMY_ID_SPLIT_2
307                 + ":    transfer/split name to taxonomy uniprot identifier" );
308         System.out.println( "          (split at underscore if \"name_id\" pattern, e.g. \"SusD_817\")" );
309         System.out.println();
310         System.out.println( " options: " );
311         System.out.println( " -" + INTERNAL_NAMES_ARE_BOOT_SUPPPORT
312                 + "       : internal names in NH or NHX tree are confidence values" );
313         System.out.println( " -" + CONFIDENCE_TYPE + "=<conf>"
314                 + ": confidence type (e.g. \"bootstrap\", default is \"unknown\")" );
315         System.out.println( " -" + REPLACE_UNDER_SCORES + "      : replace all underscores with spaces" );
316         System.out.println( " -" + MIDPOINT_REROOT + "       : midpoint reroot" );
317         System.out.println( " -" + ORDER_SUBTREES + "       : order subtrees" );
318         System.out.println( " -" + EXTRACT_TAXONOMY
319                 + "      : extract taxonomy to taxonomy code from \"seqname_TAXON\"-style names (cannot be used with the following field options: "
320                 + FIELD_TAXONOMY_CODE + ", " + FIELD_TAXONOMY_COMM_NAME + ", " + FIELD_TAXONOMY_SCI_NAME + ")" );
321         System.out.println( " -" + EXTRACT_TAXONOMY_PF
322                 + "      : extract taxonomy to taxonomy code from Pfam (\"seqname_TAXON/x-y\") style names only (cannot be used with the following field options: "
323                 + FIELD_TAXONOMY_CODE + ", " + FIELD_TAXONOMY_COMM_NAME + ", " + FIELD_TAXONOMY_SCI_NAME + ")" );
324         System.out.println( " -" + NO_TREE_LEVEL_INDENDATION + "      : no tree level indendation in phyloXML output" );
325         System.out.println( " -" + IGNORE_QUOTES + "     : ignore quotes and whitespace (e.g. \"a b\" becomes ab)" );
326         System.out.println();
327     }
328 }