fac270c39f09864a5338ad63751b5c7ac0d8d14d
[jalview.git] / forester / java / src / org / forester / application / rio.java
1 // $Id:
2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
4 //
5 // Copyright (C) 2017 Christian M. Zmasek
6 // All rights reserved
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 //
22 // WWW: https://sites.google.com/site/cmzmasek/home/software/forester
23
24 package org.forester.application;
25
26 import java.io.File;
27 import java.io.FilenameFilter;
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.List;
32
33 import org.forester.rio.RIO;
34 import org.forester.rio.RIO.REROOTING;
35 import org.forester.rio.RIOUtil;
36 import org.forester.sdi.SDIutil.ALGORITHM;
37 import org.forester.util.CommandLineArguments;
38 import org.forester.util.EasyWriter;
39 import org.forester.util.ForesterUtil;
40
41 public class rio {
42
43     public final static String PRG_NAME                       = "rio";
44     public final static String PRG_VERSION                    = "5.000";
45     public final static String PRG_DATE                       = "170411";
46     final static private String E_MAIL                         = "phyloxml@gmail.com";
47     final static private String WWW                            = "https://sites.google.com/site/cmzmasek/home/software/forester";
48     final static private String HELP_OPTION_1                  = "help";
49     final static private String LOGFILE_SUFFIX                 = "_RIO_log.tsv";
50     final static private String STRIPPED_SPECIES_TREE_SUFFIX   = "_RIO_sst.xml";
51     final static private String ORTHO_OUTTABLE_SUFFIX          = "_RIO_orthologies.tsv";
52     final static private String OUT_MIN_DUP_GENE_TREE_SUFFIX   = "_RIO_gene_tree_min_dup_";
53     final static private String OUT_MED_DUP_GENE_TREE_SUFFIX   = "_RIO_gene_tree_med_dup_";
54     final static private String ORTHOLOG_GROUPS_SUFFIX         = "_RIO_ortholog_groups.tsv";
55     final static private String HELP_OPTION_2                  = "h";
56     final static private String GT_FIRST                       = "f";
57     final static private String GT_LAST                        = "l";
58     final static private String REROOTING_OPT                  = "r";
59     final static private String OUTGROUP                       = "o";
60     final static private String USE_SDIR                       = "s";
61     final static private String GENE_TREES_SUFFIX_OPTION       = "g";
62     final static private String ORTHOLOG_GROUPS_CUTOFF_OPTION  = "c";
63     final static private double ORTHOLOG_GROUPS_CUTOFF_DEFAULT = 0.5;
64
65     public static void main( final String[] args ) {
66         ForesterUtil.printProgramInformation( PRG_NAME,
67                                               "resampled inference of orthologs",
68                                               PRG_VERSION,
69                                               PRG_DATE,
70                                               E_MAIL,
71                                               WWW,
72                                               ForesterUtil.getForesterLibraryInformation() );
73         CommandLineArguments cla = null;
74         try {
75             cla = new CommandLineArguments( args );
76         }
77         catch ( final Exception e ) {
78             ForesterUtil.fatalError( e.getMessage() );
79         }
80         if ( cla.isOptionSet( HELP_OPTION_1 ) || cla.isOptionSet( HELP_OPTION_2 ) || ( args.length == 0 ) ) {
81             printHelp();
82         }
83         if ( ( args.length < 3 ) || ( args.length > 11 ) || ( cla.getNumberOfNames() < 3 ) ) {
84             System.out.println();
85             System.out.println( "error: incorrect number of arguments" );
86             System.out.println();
87             printHelp();
88         }
89         final List<String> allowed_options = new ArrayList<String>();
90         allowed_options.add( GT_FIRST );
91         allowed_options.add( GT_LAST );
92         allowed_options.add( REROOTING_OPT );
93         allowed_options.add( OUTGROUP );
94         allowed_options.add( USE_SDIR );
95         allowed_options.add( GENE_TREES_SUFFIX_OPTION );
96         allowed_options.add( ORTHOLOG_GROUPS_CUTOFF_OPTION );
97         final String dissallowed_options = cla.validateAllowedOptionsAsString( allowed_options );
98         if ( dissallowed_options.length() > 0 ) {
99             ForesterUtil.fatalError( "unknown option(s): " + dissallowed_options );
100         }
101         final File gene_trees_file = cla.getFile( 0 );
102         final boolean use_dir;
103         File indir = null;
104         File outdir = null;
105         if ( gene_trees_file.isDirectory() ) {
106             if ( !gene_trees_file.exists() ) {
107                 ForesterUtil.fatalError( "gene trees directory \"" + gene_trees_file + "\" does not exist" );
108             }
109             use_dir = true;
110             indir = gene_trees_file;
111         }
112         else {
113             use_dir = false;
114         }
115         final File species_tree_file = cla.getFile( 1 );
116         File orthology_outtable = null;
117         if ( use_dir ) {
118             outdir = cla.getFile( 2 );
119         }
120         else {
121             orthology_outtable = cla.getFile( 2 );
122         }
123         File logfile;
124         if ( use_dir ) {
125             if ( ( cla.getNumberOfNames() < 4 ) ) {
126                 System.out.println();
127                 System.out.println( "error: incorrect number of arguments" );
128                 System.out.println();
129                 printHelp();
130             }
131             logfile = cla.getFile( 3 );
132             if ( logfile.exists() ) {
133                 ForesterUtil.fatalError( "\"" + logfile + "\" already exists" );
134             }
135         }
136         else {
137             if ( cla.getNumberOfNames() > 3 ) {
138                 logfile = cla.getFile( 3 );
139                 if ( logfile.exists() ) {
140                     ForesterUtil.fatalError( "\"" + logfile + "\" already exists" );
141                 }
142             }
143             else {
144                 logfile = null;
145             }
146         }
147         boolean sdir = false;
148         if ( cla.isOptionSet( USE_SDIR ) ) {
149             if ( cla.isOptionHasAValue( USE_SDIR ) ) {
150                 ForesterUtil.fatalError( "no value allowed for -" + USE_SDIR );
151             }
152             sdir = true;
153             if ( !use_dir && logfile != null ) {
154                 ForesterUtil.fatalError( "no logfile output for SDIR algorithm" );
155             }
156         }
157         String outgroup = null;
158         if ( cla.isOptionSet( OUTGROUP ) ) {
159             if ( sdir ) {
160                 ForesterUtil.fatalError( "no outgroup option for SDIR algorithm" );
161             }
162             if ( use_dir ) {
163                 ForesterUtil.fatalError( "no outgroup option for operating on gene trees directory" );
164             }
165             if ( !cla.isOptionHasAValue( OUTGROUP ) ) {
166                 ForesterUtil.fatalError( "no value for -" + OUTGROUP );
167             }
168             outgroup = cla.getOptionValueAsCleanString( OUTGROUP );
169         }
170         REROOTING rerooting = REROOTING.BY_ALGORITHM;
171         if ( cla.isOptionSet( REROOTING_OPT ) ) {
172             if ( !cla.isOptionHasAValue( REROOTING_OPT ) ) {
173                 ForesterUtil.fatalError( "no value for -" + REROOTING_OPT );
174             }
175             if ( sdir ) {
176                 ForesterUtil.fatalError( "no re-rooting option for SDIR algorithm" );
177             }
178             final String rerooting_str = cla.getOptionValueAsCleanString( REROOTING_OPT ).toLowerCase();
179             if ( rerooting_str.equals( "none" ) ) {
180                 rerooting = REROOTING.NONE;
181             }
182             else if ( rerooting_str.equals( "midpoint" ) ) {
183                 rerooting = REROOTING.MIDPOINT;
184             }
185             else if ( rerooting_str.equals( "outgroup" ) ) {
186                 if ( use_dir ) {
187                     ForesterUtil.fatalError( "no outgroup option for operating on gene trees directory" );
188                 }
189                 rerooting = REROOTING.OUTGROUP;
190             }
191             else {
192                 ForesterUtil
193                         .fatalError( "values for re-rooting are: 'none', 'midpoint', or 'outgroup' (minizming duplications is default)" );
194             }
195         }
196         if ( ForesterUtil.isEmpty( outgroup ) && ( rerooting == REROOTING.OUTGROUP ) ) {
197             ForesterUtil.fatalError( "selected re-rooting by outgroup, but outgroup not set" );
198         }
199         if ( !ForesterUtil.isEmpty( outgroup ) && ( rerooting != REROOTING.OUTGROUP ) ) {
200             ForesterUtil.fatalError( "outgroup set, but selected re-rooting by other approach" );
201         }
202         int gt_first = RIO.DEFAULT_RANGE;
203         int gt_last = RIO.DEFAULT_RANGE;
204         if ( cla.isOptionSet( GT_FIRST ) ) {
205             if ( sdir ) {
206                 ForesterUtil.fatalError( "no gene tree range option for SDIR algorithm" );
207             }
208             if ( !cla.isOptionHasAValue( GT_FIRST ) ) {
209                 ForesterUtil.fatalError( "no value for -" + GT_FIRST );
210             }
211             try {
212                 gt_first = cla.getOptionValueAsInt( GT_FIRST );
213             }
214             catch ( final IOException e ) {
215                 ForesterUtil.fatalError( "could not parse integer for -" + GT_FIRST + " option" );
216             }
217             if ( gt_first < 0 ) {
218                 ForesterUtil.fatalError( "attempt to set index of first tree to analyze to: " + gt_first );
219             }
220         }
221         if ( cla.isOptionSet( GT_LAST ) ) {
222             if ( sdir ) {
223                 ForesterUtil.fatalError( "no gene tree range option for SDIR algorithm" );
224             }
225             if ( !cla.isOptionHasAValue( GT_LAST ) ) {
226                 ForesterUtil.fatalError( "no value for -" + GT_LAST );
227             }
228             try {
229                 gt_last = cla.getOptionValueAsInt( GT_LAST );
230             }
231             catch ( final IOException e ) {
232                 ForesterUtil.fatalError( "could not parse integer for -" + GT_LAST + " option" );
233             }
234             if ( gt_last < 0 ) {
235                 ForesterUtil.fatalError( "attempt to set index of last tree to analyze to: " + gt_last );
236             }
237         }
238         if ( ( ( gt_last != RIO.DEFAULT_RANGE ) && ( gt_first != RIO.DEFAULT_RANGE ) ) && ( ( gt_last < gt_first ) ) ) {
239             ForesterUtil.fatalError( "attempt to set range (0-based) of gene to analyze to: from " + gt_first + " to "
240                     + gt_last );
241         }
242         double ortholog_group_cutoff = ORTHOLOG_GROUPS_CUTOFF_DEFAULT;
243         if ( cla.isOptionSet( ORTHOLOG_GROUPS_CUTOFF_OPTION ) ) {
244             if ( sdir ) {
245                 ForesterUtil.fatalError( "ortholog groups cutoff for SDIR algorithm" );
246             }
247             if ( !cla.isOptionHasAValue( ORTHOLOG_GROUPS_CUTOFF_OPTION ) ) {
248                 ForesterUtil.fatalError( "no value for -" + ORTHOLOG_GROUPS_CUTOFF_OPTION );
249             }
250             try {
251                 ortholog_group_cutoff = cla.getOptionValueAsDouble( ORTHOLOG_GROUPS_CUTOFF_OPTION );
252             }
253             catch ( final IOException e ) {
254                 ForesterUtil.fatalError( "could not parse double for -" + ORTHOLOG_GROUPS_CUTOFF_OPTION + " option" );
255             }
256             if ( ortholog_group_cutoff < 0 ) {
257                 ForesterUtil.fatalError( "attempt to set ortholog groups cutoff to: " + ortholog_group_cutoff );
258             }
259             if ( ortholog_group_cutoff > 1 ) {
260                 ForesterUtil.fatalError( "attempt to set ortholog groups cutoff to: " + ortholog_group_cutoff );
261             }
262         }
263         if ( !use_dir ) {
264             ForesterUtil.fatalErrorIfFileNotReadable( gene_trees_file );
265         }
266         final String gene_trees_suffix;
267         if ( cla.isOptionSet( GENE_TREES_SUFFIX_OPTION ) ) {
268             if ( !use_dir ) {
269                 ForesterUtil.fatalError( "no gene tree suffix option when operating on indivual gene trees" );
270             }
271             if ( !cla.isOptionHasAValue( GENE_TREES_SUFFIX_OPTION ) ) {
272                 ForesterUtil.fatalError( "no value for -" + GENE_TREES_SUFFIX_OPTION );
273             }
274             gene_trees_suffix = cla.getOptionValueAsCleanString( GENE_TREES_SUFFIX_OPTION );
275         }
276         else {
277             gene_trees_suffix = ".mlt";
278         }
279         ForesterUtil.fatalErrorIfFileNotReadable( species_tree_file );
280         if ( !use_dir && orthology_outtable.exists() ) {
281             ForesterUtil.fatalError( "\"" + orthology_outtable + "\" already exists" );
282         }
283         long time = 0;
284         try {
285             if ( use_dir ) {
286                 System.out.println( "Gene trees in-dir                   :\t" + indir.getCanonicalPath() );
287                 System.out.println( "Gene trees suffix                   :\t" + gene_trees_suffix );
288             }
289             else {
290                 System.out.println( "Gene trees                          :\t" + gene_trees_file.getCanonicalPath() );
291             }
292             System.out.println( "Species tree                        :\t" + species_tree_file.getCanonicalPath() );
293         }
294         catch ( final IOException e ) {
295             ForesterUtil.fatalError( e.getLocalizedMessage() );
296         }
297         if ( use_dir ) {
298             System.out.println( "Out-dir                             :\t" + outdir );
299         }
300         else {
301             System.out.println( "All vs all orthology results table  :\t" + orthology_outtable );
302         }
303         if ( logfile != null ) {
304             System.out.println( "Logfile                             :\t" + logfile );
305         }
306         System.out.println( "Ortholog groups cutoff              :\t" + ortholog_group_cutoff );
307         if ( gt_first != RIO.DEFAULT_RANGE ) {
308             System.out.println( "First gene tree to analyze          :\t" + gt_first );
309         }
310         if ( gt_last != RIO.DEFAULT_RANGE ) {
311             System.out.println( "Last gene tree to analyze           :\t" + gt_last );
312         }
313         String rerooting_str = "";
314         switch ( rerooting ) {
315             case BY_ALGORITHM: {
316                 rerooting_str = "by minimizing duplications";
317                 break;
318             }
319             case MIDPOINT: {
320                 rerooting_str = "by midpoint method";
321                 break;
322             }
323             case OUTGROUP: {
324                 rerooting_str = "by outgroup: " + outgroup;
325                 break;
326             }
327             case NONE: {
328                 rerooting_str = "none";
329                 break;
330             }
331         }
332         System.out.println( "Re-rooting                          : \t" + rerooting_str );
333         if ( !sdir ) {
334             System.out.println( "Non binary species tree             :\tallowed" );
335         }
336         else {
337             System.out.println( "Non binary species tree             :\tdisallowed" );
338         }
339         time = System.currentTimeMillis();
340         final ALGORITHM algorithm;
341         if ( sdir ) {
342             algorithm = ALGORITHM.SDIR;
343         }
344         else {
345             algorithm = ALGORITHM.GSDIR;
346         }
347         EasyWriter log = null;
348         if ( use_dir ) {
349             if ( outdir.exists() ) {
350                 if ( !outdir.isDirectory() ) {
351                     ForesterUtil.fatalError( PRG_NAME,
352                                              "out-directory [" + outdir + "] already exists but is not a directory" );
353                 }
354             }
355             else {
356                 final boolean success = outdir.mkdirs();
357                 if ( !success ) {
358                     ForesterUtil.fatalError( PRG_NAME, "could not create out-directory [" + outdir + "]" );
359                 }
360             }
361             final String species_tree_file_name = species_tree_file.getName();
362             final File gene_trees_files[] = indir.listFiles( new FilenameFilter() {
363
364                 @Override
365                 public boolean accept( final File dir, final String name ) {
366                     return ( ( name.endsWith( gene_trees_suffix ) ) && !( name.equals( species_tree_file_name ) ) );
367                 }
368             } );
369             if ( gene_trees_files.length < 1 ) {
370                 ForesterUtil.fatalError( PRG_NAME,
371                                          "in-directory [" + indir
372                                                  + "] does not contain any gene tree files with suffix "
373                                                  + gene_trees_suffix );
374             }
375             try {
376                 log = ForesterUtil.createEasyWriter( logfile );
377             }
378             catch ( final IOException e ) {
379                 ForesterUtil.fatalError( PRG_NAME, "could not create [" + logfile + "]" );
380             }
381             Arrays.sort( gene_trees_files );
382             try {
383                 log.print( "# program" );
384                 log.print( "\t" );
385                 log.print( PRG_NAME );
386                 log.println();
387                 log.print( "# version" );
388                 log.print( "\t" );
389                 log.print( PRG_VERSION );
390                 log.println();
391                 log.print( "# date" );
392                 log.print( "\t" );
393                 log.print( PRG_DATE );
394                 log.println();
395                 log.print( "# Algorithm " );
396                 log.print( "\t" );
397                 log.print( algorithm.toString() );
398                 log.println();
399                 log.print( "# Gene trees in-dir" );
400                 log.print( "\t" );
401                 log.print( indir.getCanonicalPath() );
402                 log.println();
403                 log.print( "# Gene trees suffix" );
404                 log.print( "\t" );
405                 log.print( gene_trees_suffix );
406                 log.println();
407                 log.print( "# Species tree" );
408                 log.print( "\t" );
409                 log.print( species_tree_file.getCanonicalPath() );
410                 log.println();
411                 log.print( "# Out-dir" );
412                 log.print( "\t" );
413                 log.print( outdir.getCanonicalPath() );
414                 log.println();
415                 log.print( "# Logfile" );
416                 log.print( "\t" );
417                 log.print( logfile.getCanonicalPath() );
418                 log.println();
419                 log.print( "# Ortholog groups cutoff" );
420                 log.print( "\t" );
421                 log.print( Double.toString( ortholog_group_cutoff ) );
422                 log.println();
423                 if ( gt_first != RIO.DEFAULT_RANGE ) {
424                     log.print( "# First gene tree to analyze" );
425                     log.print( "\t" );
426                     log.print( Integer.toString( gt_first ) );
427                     log.println();
428                 }
429                 if ( gt_last != RIO.DEFAULT_RANGE ) {
430                     log.print( "# Last gene tree to analyze" );
431                     log.print( "\t" );
432                     log.print( Integer.toString( gt_last ) );
433                     log.println();
434                 }
435                 log.print( "# Re-rooting" );
436                 log.print( "\t" );
437                 log.print( rerooting_str );
438                 log.println();
439                 log.print( "# Non binary species tree" );
440                 log.print( "\t" );
441                 if ( !sdir ) {
442                     log.print( "allowed" );
443                 }
444                 else {
445                     log.print( "disallowed" );
446                 }
447                 log.println();
448                 log.println();
449                 log.print( "NAME" );
450                 log.print( "\t" );
451                 log.print( "EXT NODES" );
452                 log.print( "\t" );
453                 log.print(  ortholog_group_cutoff + " O GROUPS" );
454                 log.print( "\t" );
455                 log.print( "0.05 O GROUPS" );
456                 log.print( "\t" );
457                 log.print( "0.25 O GROUPS" );
458                 log.print( "\t" );
459                 log.print( "0.5 O GROUPS" );
460                 log.print( "\t" );
461                 log.print( "0.75 O GROUPS" );
462                 log.print( "\t" );
463                 log.print( "0.95 O GROUPS" );
464                 log.print( "\t" );
465                 log.print( "MEDIAN DUP" );
466                 log.print( "\t" );
467                 log.print( "MEAN DUP" );
468                 log.print( "\t" );
469                 log.print( "MEAN DUP SD" );
470                 log.print( "\t" );
471                 log.print( "MIN DUP" );
472                 log.print( "\t" );
473                 log.print( "MAX DUP" );
474                 log.print( "\t" );
475                 log.print( "REMOVED EXT NODES" );
476                 log.print( "\t" );
477                 log.print( "N" );
478                 log.println();
479             }
480             catch ( IOException e ) {
481                 ForesterUtil.fatalError( PRG_NAME, e.getLocalizedMessage() );
482             }
483             int counter = 1;
484             for( final File gf : gene_trees_files ) {
485                 String outname = gf.getName();
486                 System.out
487                         .print( "\r                                                                                            " );
488                 System.out.print( "\r" + counter + "/" + gene_trees_files.length + ": " + outname );
489                 counter++;
490                 if ( outname.indexOf( "." ) > 0 ) {
491                     outname = outname.substring( 0, outname.lastIndexOf( "." ) );
492                 }
493                 try {
494                     RIOUtil.executeAnalysis( gf,
495                                      species_tree_file,
496                                      new File( outdir.getCanonicalFile() + "/" + outname + ORTHO_OUTTABLE_SUFFIX ),
497                                      new File( outdir.getCanonicalFile() + "/" + outname + ORTHOLOG_GROUPS_SUFFIX ),
498                                      new File( outdir.getCanonicalFile() + "/" + outname + LOGFILE_SUFFIX ),
499                                      outgroup,
500                                      rerooting,
501                                      gt_first,
502                                      gt_last,
503                                      new File( outdir.getCanonicalFile() + "/" + outname
504                                              + STRIPPED_SPECIES_TREE_SUFFIX ),
505                                      new File( outdir.getCanonicalFile() + "/" + outname
506                                              + OUT_MIN_DUP_GENE_TREE_SUFFIX ),
507                                      new File( outdir.getCanonicalFile() + "/" + outname
508                                              + OUT_MED_DUP_GENE_TREE_SUFFIX ),
509                                      true,
510                                      algorithm,
511                                      true,
512                                      log,
513                                      ortholog_group_cutoff );
514                 }
515                 catch ( IOException e ) {
516                     ForesterUtil.fatalError( PRG_NAME, e.getLocalizedMessage() );
517                 }
518             }
519             System.out
520                     .print( "\r                                                                                        " );
521             System.out.println();
522         }
523         else {
524             String outname = orthology_outtable.toString();
525             if ( outname.indexOf( "." ) > 0 ) {
526                 outname = outname.substring( 0, outname.lastIndexOf( "." ) );
527             }
528             RIOUtil.executeAnalysis( gene_trees_file,
529                              species_tree_file,
530                              orthology_outtable,
531                              new File( outname + ORTHOLOG_GROUPS_SUFFIX ),
532                              logfile,
533                              outgroup,
534                              rerooting,
535                              gt_first,
536                              gt_last,
537                              new File( outname + STRIPPED_SPECIES_TREE_SUFFIX ),
538                              new File( outname + OUT_MIN_DUP_GENE_TREE_SUFFIX ),
539                              new File( outname + OUT_MED_DUP_GENE_TREE_SUFFIX ),
540                              algorithm == ALGORITHM.GSDIR,
541                              algorithm,
542                              false,
543                              null,
544                              ortholog_group_cutoff );
545         }
546         if ( !use_dir ) {
547             time = System.currentTimeMillis() - time;
548             System.out.println( "Time                                :\t" + time + "ms" );
549         }
550         else {
551             try {
552                 log.close();
553             }
554             catch ( IOException e ) {
555                 ForesterUtil.fatalError( PRG_NAME, e.getLocalizedMessage() );
556             }
557             time = System.currentTimeMillis() - time;
558             System.out.println( "Time                                :\t" + time + "ms" );
559         }
560         System.exit( 0 );
561     }
562
563     private final static void printHelp() {
564         System.out.println( "Usage" );
565         System.out.println();
566         System.out.println( PRG_NAME
567                 + " [options] <gene trees infile> <species tree infile> <all vs all orthology table outfile> [logfile]" );
568         System.out.println();
569         System.out.println( PRG_NAME + " [options] <gene trees indir> <species tree infile> <outdir> <logfile>" );
570         System.out.println();
571         System.out.println();
572         System.out.println( " Options" );
573         System.out.println( "  -" + GT_FIRST + "=<first>     : first gene tree to analyze (0-based index)" );
574         System.out.println( "  -" + GT_LAST + "=<last>      : last gene tree to analyze (0-based index)" );
575         System.out.println( "  -" + ORTHOLOG_GROUPS_CUTOFF_OPTION
576                 + "=<cutoff>    : cutoff value for ortholog groups (default: " + ORTHOLOG_GROUPS_CUTOFF_DEFAULT + ")" );
577         System.out.println( "  -" + REROOTING_OPT
578                 + "=<re-rooting>: re-rooting method for gene trees, possible values or 'none', 'midpoint'," );
579         System.out.println( "                   or 'outgroup' (default: by minizming duplications)" );
580         System.out.println( "  -" + OUTGROUP
581                 + "=<outgroup>  : for rooting by outgroup, name of outgroup (external gene tree node)" );
582         System.out.println( "  -" + USE_SDIR
583                 + "             : to use SDIR instead of GSDIR (faster, but non-binary species trees are" );
584         System.out.println( "                   disallowed, as are most options)" );
585         System.out.println( "  -" + GENE_TREES_SUFFIX_OPTION
586                 + "=<suffix>    : suffix for gene trees when operating on gene tree directories (default: .mlt)" );
587         System.out.println();
588         System.out.println( " Formats" );
589         System.out
590                 .println( "  The gene trees, as well as the species tree, ideally are in phyloXML (www.phyloxml.org) format," );
591         System.out
592                 .println( "  but can also be in New Hamphshire (Newick) or Nexus format as long as species information can be" );
593         System.out
594                 .println( "  extracted from the gene names (e.g. \"HUMAN\" from \"BCL2_HUMAN\") and matched to a single species" );
595         System.out.println( "  in the species tree." );
596         System.out.println();
597         System.out.println( " Examples" );
598         System.out.println( "  rio -s gene_trees.nh species.xml outtable.tsv" );
599         System.out.println( "  rio gene_trees.nh species.xml outtable.tsv log.txt" );
600         System.out.println( "  rio -c=0.9 -f=10 -l=100 -r=none gene_trees.xml species.xml outtable.tsv log.txt" );
601         System.out.println( "  rio -g=.xml gene_trees_dir species.xml out_dir log.tsv" );
602         System.out.println();
603         System.exit( -1 );
604     }
605 }