in pprogress...
[jalview.git] / forester / java / src / org / forester / rio / RIOUtil.java
1
2 package org.forester.rio;
3
4 import java.io.File;
5 import java.io.IOException;
6 import java.math.RoundingMode;
7 import java.util.ArrayList;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.SortedMap;
11 import java.util.SortedSet;
12 import java.util.TreeSet;
13
14 import javax.swing.JOptionPane;
15
16 import org.forester.archaeopteryx.AptxUtil;
17 import org.forester.datastructures.IntMatrix;
18 import org.forester.io.parsers.IteratingPhylogenyParser;
19 import org.forester.io.parsers.PhylogenyParser;
20 import org.forester.io.parsers.nexus.NexusPhylogeniesParser;
21 import org.forester.io.parsers.nhx.NHXParser;
22 import org.forester.io.parsers.nhx.NHXParser.TAXONOMY_EXTRACTION;
23 import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
24 import org.forester.io.parsers.phyloxml.PhyloXmlParser;
25 import org.forester.io.parsers.util.ParserUtils;
26 import org.forester.io.writers.PhylogenyWriter;
27 import org.forester.phylogeny.Phylogeny;
28 import org.forester.phylogeny.PhylogenyMethods;
29 import org.forester.phylogeny.PhylogenyNode;
30 import org.forester.phylogeny.PhylogenyMethods.DESCENDANT_SORT_PRIORITY;
31 import org.forester.phylogeny.data.Sequence;
32 import org.forester.phylogeny.factories.ParserBasedPhylogenyFactory;
33 import org.forester.phylogeny.factories.PhylogenyFactory;
34 import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
35 import org.forester.rio.RIO.REROOTING;
36 import org.forester.sdi.GSDIR;
37 import org.forester.sdi.SDIException;
38 import org.forester.sdi.SDIutil;
39 import org.forester.sdi.SDIutil.ALGORITHM;
40 import org.forester.util.BasicDescriptiveStatistics;
41 import org.forester.util.BasicTable;
42 import org.forester.util.BasicTableParser;
43 import org.forester.util.EasyWriter;
44 import org.forester.util.ForesterUtil;
45
46 public final class RIOUtil {
47
48     public static final void executeAnalysis( final File gene_trees_file,
49                                               final File species_tree_file,
50                                               final File orthology_outtable,
51                                               final File orthology_outtable_with_mappings,
52                                               final File orthology_groups_outfile,
53                                               final File logfile,
54                                               final String outgroup,
55                                               final REROOTING rerooting,
56                                               final int gt_first,
57                                               final int gt_last,
58                                               final File return_species_tree,
59                                               final File return_min_dup_gene_tree,
60                                               final File return_median_dup_gene_tree,
61                                               final boolean transfer_taxonomy,
62                                               final ALGORITHM algorithm,
63                                               final boolean use_gene_trees_dir,
64                                               final EasyWriter log,
65                                               final double ortholog_group_cutoff,
66                                               final boolean perform_id_mapping,
67                                               final File id_mapping_dir,
68                                               final String id_mapping_suffix ) {
69         try {
70             final SortedMap<String, String> id_map;
71             if ( perform_id_mapping ) {
72                 id_map = obtainMapping( id_mapping_dir, gene_trees_file.getName(), id_mapping_suffix );
73             }
74             else {
75                 id_map = null;
76             }
77             final RIO rio;
78             boolean iterating = false;
79             final PhylogenyParser p = ParserUtils.createParserDependingOnFileType( gene_trees_file, true );
80             if ( p instanceof PhyloXmlParser ) {
81                 rio = RIO.executeAnalysis( gene_trees_file,
82                                            species_tree_file,
83                                            algorithm,
84                                            rerooting,
85                                            outgroup,
86                                            gt_first,
87                                            gt_last,
88                                            logfile != null,
89                                            true,
90                                            transfer_taxonomy );
91             }
92             else {
93                 iterating = true;
94                 if ( p instanceof NHXParser ) {
95                     final NHXParser nhx = ( NHXParser ) p;
96                     nhx.setReplaceUnderscores( false );
97                     nhx.setIgnoreQuotes( true );
98                     nhx.setTaxonomyExtraction( TAXONOMY_EXTRACTION.AGGRESSIVE );
99                 }
100                 else if ( p instanceof NexusPhylogeniesParser ) {
101                     final NexusPhylogeniesParser nex = ( NexusPhylogeniesParser ) p;
102                     nex.setReplaceUnderscores( false );
103                     nex.setIgnoreQuotes( true );
104                     nex.setTaxonomyExtraction( TAXONOMY_EXTRACTION.AGGRESSIVE );
105                 }
106                 else {
107                     throw new RuntimeException( "unknown parser type: " + p );
108                 }
109                 final IteratingPhylogenyParser ip = ( IteratingPhylogenyParser ) p;
110                 ip.setSource( gene_trees_file );
111                 rio = RIO.executeAnalysis( ip,
112                                            species_tree_file,
113                                            algorithm,
114                                            rerooting,
115                                            outgroup,
116                                            gt_first,
117                                            gt_last,
118                                            logfile != null,
119                                            !use_gene_trees_dir,
120                                            transfer_taxonomy );
121             }
122             if ( !use_gene_trees_dir ) {
123                 if ( algorithm == ALGORITHM.GSDIR ) {
124                     System.out.println( "Taxonomy linking based on           :\t" + rio.getGSDIRtaxCompBase() );
125                 }
126             }
127             final IntMatrix m;
128             if ( iterating ) {
129                 m = rio.getOrthologTable();
130             }
131             else {
132                 m = RIO.calculateOrthologTable( rio.getAnalyzedGeneTrees(), true );
133             }
134             ////////////////////////////////////////////
135             ////////////////////////////////////////////
136             //TODO
137             final boolean perform_gsdir_on_best_tree = true;
138             final File best_trees_dir = new File( "best_trees" );
139             final String best_trees_suffix = ".xml";
140             final GSDIR gsdir_for_best_tree;
141             if ( perform_gsdir_on_best_tree ) {
142                 final Phylogeny best_tree = obtainTree( best_trees_dir, gene_trees_file.getName(), best_trees_suffix );
143                 final Phylogeny species_tree = SDIutil
144                         .parseSpeciesTree( best_tree, species_tree_file, false, true, TAXONOMY_EXTRACTION.NO );
145                 PhylogenyMethods.deleteInternalNodesWithOnlyOneDescendent( species_tree );
146                 best_tree.setRooted( true );
147                 species_tree.setRooted( true );
148                 if ( !best_tree.isCompletelyBinaryAllow3ChildrenAtRoot() ) {
149                     throw new IOException( "gene tree matching to ["
150                             + ForesterUtil.removeFileExtension( gene_trees_file.getName() )
151                             + "] is not completely binary" );
152                 }
153                 final PhylogenyNodeIterator it = best_tree.iteratorExternalForward();
154                 while ( it.hasNext() ) {
155                     final PhylogenyNode n = it.next();
156                     final String name = n.getName().trim();
157                     if ( !ForesterUtil.isEmpty( name ) ) {
158                         try {
159                             ParserUtils.extractTaxonomyDataFromNodeName( n, TAXONOMY_EXTRACTION.AGGRESSIVE );
160                         }
161                         catch ( final PhyloXmlDataFormatException e ) {
162                             // Ignore.
163                         }
164                     }
165                 }
166                 gsdir_for_best_tree = new GSDIR( best_tree, species_tree, true, true, true );
167                 final Phylogeny result_gene_tree = gsdir_for_best_tree.getMinDuplicationsSumGeneTree();
168                 System.out.println( gsdir_for_best_tree.getMinDuplicationsSum() );
169                 result_gene_tree.setRerootable( false );
170                 PhylogenyMethods.orderAppearance( result_gene_tree.getRoot(),
171                                                   true,
172                                                   true,
173                                                   DESCENDANT_SORT_PRIORITY.NODE_NAME );
174                 writeTree( result_gene_tree, new File( gene_trees_file.getName() + "____.xml" ), null, id_map );
175             }
176             else {
177                 gsdir_for_best_tree = null;
178             }
179             ////////////////////////////////////////////
180             ////////////////////////////////////////////
181             final BasicDescriptiveStatistics stats = rio.getDuplicationsStatistics();
182             if ( perform_id_mapping ) {
183                 writeOrthologyTable( orthology_outtable, stats.getN(), m, !use_gene_trees_dir, id_map, true );
184                 writeOrthologyTable( orthology_outtable_with_mappings,
185                                      stats.getN(),
186                                      m,
187                                      !use_gene_trees_dir,
188                                      id_map,
189                                      false );
190             }
191             else {
192                 writeOrthologyTable( orthology_outtable, stats.getN(), m, !use_gene_trees_dir, null, false );
193             }
194             final int ortholog_groups = writeOrtologGroups( orthology_groups_outfile,
195                                                             ortholog_group_cutoff,
196                                                             stats.getN(),
197                                                             m,
198                                                             !use_gene_trees_dir,
199                                                             false,
200                                                             id_map );
201             final int ortholog_groups_005 = writeOrtologGroups( null, 0.05, stats.getN(), m, false, true, null );
202             final int ortholog_groups_025 = writeOrtologGroups( null, 0.25, stats.getN(), m, false, true, null );
203             final int ortholog_groups_05 = writeOrtologGroups( null, 0.5, stats.getN(), m, false, true, null );
204             final int ortholog_groups_075 = writeOrtologGroups( null, 0.75, stats.getN(), m, false, true, null );
205             final int ortholog_groups_095 = writeOrtologGroups( null, 0.95, stats.getN(), m, false, true, null );
206             if ( ( algorithm != ALGORITHM.SDIR ) && ( logfile != null ) ) {
207                 writeLogFile( logfile,
208                               rio,
209                               species_tree_file,
210                               gene_trees_file,
211                               orthology_outtable,
212                               org.forester.application.rio.PRG_NAME,
213                               org.forester.application.rio.PRG_VERSION,
214                               org.forester.application.rio.PRG_DATE,
215                               ForesterUtil.getForesterLibraryInformation(),
216                               !use_gene_trees_dir );
217             }
218             if ( return_species_tree != null ) {
219                 writeTree( rio.getSpeciesTree(),
220                            return_species_tree,
221                            use_gene_trees_dir ? null : "Wrote (stripped) species tree to    :\t",
222                            null );
223             }
224             if ( return_min_dup_gene_tree != null && rio.getMinDuplicationsGeneTree() != null ) {
225                 final int min = ( int ) rio.getDuplicationsStatistics().getMin();
226                 writeTree( rio.getMinDuplicationsGeneTree(),
227                            new File( return_min_dup_gene_tree.toString() + min + ".xml" ),
228                            use_gene_trees_dir ? null : "Wrote one min duplication gene tree :\t",
229                            id_map );
230             }
231             if ( return_median_dup_gene_tree != null && rio.getDuplicationsToTreeMap() != null ) {
232                 final int med = ( int ) rio.getDuplicationsStatistics().median();
233                 writeTree( rio.getDuplicationsToTreeMap().get( med ),
234                            new File( return_median_dup_gene_tree.toString() + med + ".xml" ),
235                            use_gene_trees_dir ? null : "Wrote one med duplication gene tree :\t",
236                            id_map );
237             }
238             final java.text.DecimalFormat df = new java.text.DecimalFormat( "0.##" );
239             final int min = ( int ) stats.getMin();
240             final int max = ( int ) stats.getMax();
241             final int median = ( int ) stats.median();
242             int min_count = 0;
243             int max_count = 0;
244             int median_count = 0;
245             for( double d : stats.getData() ) {
246                 if ( ( ( int ) d ) == min ) {
247                     ++min_count;
248                 }
249                 if ( ( ( int ) d ) == max ) {
250                     ++max_count;
251                 }
252                 if ( ( ( int ) d ) == median ) {
253                     ++median_count;
254                 }
255             }
256             final double min_count_percentage = ( 100.0 * min_count ) / stats.getN();
257             final double max_count_percentage = ( 100.0 * max_count ) / stats.getN();
258             final double median_count_percentage = ( 100.0 * median_count ) / stats.getN();
259             if ( use_gene_trees_dir ) {
260                 String name = gene_trees_file.getName();
261                 if ( name.indexOf( "." ) > 0 ) {
262                     name = name.substring( 0, name.lastIndexOf( "." ) );
263                 }
264                 log.print( name );
265                 log.print( "\t" );
266                 log.print( Integer.toString( rio.getExtNodesOfAnalyzedGeneTrees() ) );
267                 log.print( "\t" );
268                 log.print( Integer.toString( ortholog_groups ) );
269                 //
270                 log.print( "\t" );
271                 log.print( Integer.toString( ortholog_groups_005 ) );
272                 log.print( "\t" );
273                 log.print( Integer.toString( ortholog_groups_025 ) );
274                 log.print( "\t" );
275                 log.print( Integer.toString( ortholog_groups_05 ) );
276                 log.print( "\t" );
277                 log.print( Integer.toString( ortholog_groups_075 ) );
278                 log.print( "\t" );
279                 log.print( Integer.toString( ortholog_groups_095 ) );
280                 //
281                 log.print( "\t" );
282                 if ( stats.getN() > 3 ) {
283                     log.print( df.format( median ) );
284                 }
285                 else {
286                     log.print( "" );
287                 }
288                 log.print( "\t" );
289                 log.print( df.format( stats.arithmeticMean() ) );
290                 log.print( "\t" );
291                 if ( stats.getN() > 3 ) {
292                     log.print( df.format( stats.sampleStandardDeviation() ) );
293                 }
294                 else {
295                     log.print( "" );
296                 }
297                 log.print( "\t" );
298                 log.print( Integer.toString( min ) );
299                 log.print( "\t" );
300                 log.print( Integer.toString( max ) );
301                 log.print( "\t" );
302                 log.print( Integer.toString( rio.getRemovedGeneTreeNodes().size() ) );
303                 log.print( "\t" );
304                 log.print( Integer.toString( stats.getN() ) );
305                 log.println();
306             }
307             else {
308                 System.out.println( "Gene tree internal nodes            :\t" + rio.getIntNodesOfAnalyzedGeneTrees() );
309                 System.out.println( "Gene tree external nodes            :\t" + rio.getExtNodesOfAnalyzedGeneTrees() );
310                 System.out.println( "Mean number of duplications         :\t" + df.format( stats.arithmeticMean() )
311                         + "\t" + df.format( ( 100.0 * stats.arithmeticMean() ) / rio.getIntNodesOfAnalyzedGeneTrees() )
312                         + "%\t(sd: " + df.format( stats.sampleStandardDeviation() ) + ")" );
313                 if ( stats.getN() > 3 ) {
314                     System.out.println( "Median number of duplications       :\t" + df.format( median ) + "\t"
315                             + df.format( ( 100.0 * median ) / rio.getIntNodesOfAnalyzedGeneTrees() ) + "%" );
316                 }
317                 System.out.println( "Minimum duplications                :\t" + min + "\t"
318                         + df.format( ( 100.0 * min ) / rio.getIntNodesOfAnalyzedGeneTrees() ) + "%" );
319                 System.out.println( "Maximum duplications                :\t" + ( int ) max + "\t"
320                         + df.format( ( 100.0 * max ) / rio.getIntNodesOfAnalyzedGeneTrees() ) + "%" );
321                 System.out.println( "Gene trees with median duplications :\t" + median_count + "\t"
322                         + df.format( median_count_percentage ) + "%" );
323                 System.out.println( "Gene trees with minimum duplications:\t" + min_count + "\t"
324                         + df.format( min_count_percentage ) + "%" );
325                 System.out.println( "Gene trees with maximum duplications:\t" + max_count + "\t"
326                         + df.format( max_count_percentage ) + "%" );
327                 if ( algorithm == ALGORITHM.GSDIR ) {
328                     System.out.println( "Removed ext gene tree nodes         :\t"
329                             + rio.getRemovedGeneTreeNodes().size() );
330                 }
331             }
332         }
333         catch ( final RIOException e ) {
334             ForesterUtil.fatalError( e.getLocalizedMessage() );
335         }
336         catch ( final SDIException e ) {
337             ForesterUtil.fatalError( e.getLocalizedMessage() );
338         }
339         catch ( final IOException e ) {
340             ForesterUtil.fatalError( e.getLocalizedMessage() );
341         }
342         catch ( final OutOfMemoryError e ) {
343             ForesterUtil.outOfMemoryError( e );
344         }
345         catch ( final Exception e ) {
346             ForesterUtil.unexpectedFatalError( e );
347         }
348         catch ( final Error e ) {
349             ForesterUtil.unexpectedFatalError( e );
350         }
351     }
352
353     private static final void writeOrthologyTable( final File table_outfile,
354                                                    final int gene_trees_analyzed,
355                                                    final IntMatrix m,
356                                                    final boolean verbose,
357                                                    final SortedMap<String, String> id_map,
358                                                    final boolean replace_ids )
359             throws IOException {
360         final EasyWriter w = ForesterUtil.createEasyWriter( table_outfile );
361         final java.text.DecimalFormat df = new java.text.DecimalFormat( "0.####" );
362         df.setDecimalSeparatorAlwaysShown( false );
363         df.setRoundingMode( RoundingMode.HALF_UP );
364         for( int i = 0; i < m.size(); ++i ) {
365             w.print( "\t" );
366             if ( replace_ids ) {
367                 if ( !id_map.containsKey( m.getLabel( i ) ) ) {
368                     throw new IOException( "no id mapping for \"" + m.getLabel( i ) + "\" (attempting to write ["
369                             + table_outfile + "])" );
370                 }
371                 w.print( id_map.get( m.getLabel( i ) ) );
372             }
373             else {
374                 w.print( m.getLabel( i ) );
375             }
376         }
377         w.println();
378         for( int x = 0; x < m.size(); ++x ) {
379             if ( replace_ids ) {
380                 w.print( id_map.get( m.getLabel( x ) ) );
381             }
382             else {
383                 w.print( m.getLabel( x ) );
384             }
385             for( int y = 0; y < m.size(); ++y ) {
386                 w.print( "\t" );
387                 if ( x == y ) {
388                     if ( m.get( x, y ) != gene_trees_analyzed ) {
389                         ForesterUtil.unexpectedFatalError( "diagonal value is off" );
390                     }
391                     w.print( "-" );
392                 }
393                 else {
394                     w.print( df.format( ( ( double ) m.get( x, y ) ) / gene_trees_analyzed ) );
395                 }
396             }
397             w.println();
398         }
399         if ( !replace_ids && id_map != null && id_map.size() > 0 ) {
400             w.println();
401             id_map.forEach( ( k, v ) -> {
402                 try {
403                     w.println( k + "\t" + v );
404                 }
405                 catch ( final IOException e ) {
406                     //ignore
407                 }
408             } );
409         }
410         w.close();
411         if ( verbose ) {
412             System.out.println( "Wrote table to                      :\t" + table_outfile.getCanonicalPath() );
413         }
414     }
415
416     private static final int writeOrtologGroups( final File outfile,
417                                                  final double cutoff,
418                                                  final int gene_trees_analyzed,
419                                                  final IntMatrix m,
420                                                  final boolean verbose,
421                                                  final boolean calc_conly,
422                                                  final SortedMap<String, String> id_map )
423             throws IOException {
424         List<SortedSet<String>> groups = new ArrayList<SortedSet<String>>();
425         BasicDescriptiveStatistics stats = new BasicDescriptiveStatistics();
426         int below_075 = 0;
427         int below_05 = 0;
428         int below_025 = 0;
429         for( int x = 1; x < m.size(); ++x ) {
430             final String a = m.getLabel( x );
431             for( int y = 0; y < x; ++y ) {
432                 final String b = m.getLabel( y );
433                 final double s = ( ( double ) m.get( x, y ) ) / gene_trees_analyzed;
434                 stats.addValue( s );
435                 if ( s < 0.75 ) {
436                     below_075++;
437                     if ( s < 0.5 ) {
438                         below_05++;
439                         if ( s < 0.25 ) {
440                             below_025++;
441                         }
442                     }
443                 }
444                 if ( s >= cutoff ) {
445                     boolean found = false;
446                     for( final SortedSet<String> group : groups ) {
447                         if ( group.contains( a ) ) {
448                             group.add( b );
449                             found = true;
450                         }
451                         if ( group.contains( b ) ) {
452                             group.add( a );
453                             found = true;
454                         }
455                     }
456                     if ( !found ) {
457                         final SortedSet<String> new_group = new TreeSet<String>();
458                         new_group.add( a );
459                         new_group.add( b );
460                         groups.add( new_group );
461                     }
462                 }
463             }
464         }
465         //Deal with singlets:
466         for( int x = 0; x < m.size(); ++x ) {
467             final String a = m.getLabel( x );
468             boolean found = false;
469             for( final SortedSet<String> group : groups ) {
470                 if ( group.contains( a ) ) {
471                     found = true;
472                     break;
473                 }
474             }
475             if ( !found ) {
476                 final SortedSet<String> new_group = new TreeSet<String>();
477                 new_group.add( a );
478                 groups.add( new_group );
479             }
480         }
481         if ( calc_conly ) {
482             return groups.size();
483         }
484         final java.text.DecimalFormat df = new java.text.DecimalFormat( "0.####" );
485         df.setDecimalSeparatorAlwaysShown( false );
486         df.setRoundingMode( RoundingMode.HALF_UP );
487         final EasyWriter w = ForesterUtil.createEasyWriter( outfile );
488         int counter = 1;
489         for( final SortedSet<String> group : groups ) {
490             w.print( Integer.toString( counter++ ) );
491             for( final String s : group ) {
492                 w.print( "\t" );
493                 if ( id_map != null && id_map.size() > 0 ) {
494                     if ( !id_map.containsKey( s ) ) {
495                         throw new IOException( "no id mapping for \"" + s + "\" (attempting to write [" + outfile
496                                 + "])" );
497                     }
498                     w.print( id_map.get( s ) );
499                 }
500                 else {
501                     w.print( s );
502                 }
503             }
504             w.println();
505         }
506         w.println();
507         w.println( "# Cutoff\t" + df.format( cutoff ) );
508         w.println();
509         w.println( "# Orthology support statistics:" );
510         if ( stats.getN() > 3 ) {
511             w.println( "# Median\t" + df.format( stats.median() ) );
512         }
513         w.println( "# Mean\t" + df.format( stats.arithmeticMean() ) );
514         if ( stats.getN() > 3 ) {
515             w.println( "# SD\t" + df.format( stats.sampleStandardDeviation() ) );
516         }
517         w.println( "# Min\t" + df.format( stats.getMin() ) );
518         w.println( "# Max\t" + df.format( stats.getMax() ) );
519         w.println( "# Total\t" + df.format( stats.getN() ) );
520         w.println( "# Below 0.75\t" + below_075 + "\t" + df.format( ( 100.0 * below_075 / stats.getN() ) ) + "%" );
521         w.println( "# Below 0.5\t" + below_05 + "\t" + df.format( ( 100.0 * below_05 / stats.getN() ) ) + "%" );
522         w.println( "# Below 0.25\t" + below_025 + "\t" + df.format( ( 100.0 * below_025 / stats.getN() ) ) + "%" );
523         w.close();
524         if ( verbose ) {
525             System.out.println( "Number of ortholog groups           :\t" + groups.size() );
526             System.out.println( "Wrote orthologs groups table to     :\t" + outfile.getCanonicalPath() );
527         }
528         return groups.size();
529     }
530
531     private static void writeTree( final Phylogeny p,
532                                    final File f,
533                                    final String comment,
534                                    final SortedMap<String, String> id_map )
535             throws IOException {
536         if ( id_map != null && id_map.size() > 0 ) {
537             final PhylogenyNodeIterator it = p.iteratorExternalForward();
538             while ( it.hasNext() ) {
539                 final PhylogenyNode n = it.next();
540                 if ( !id_map.containsKey( n.getName() ) ) {
541                     throw new IOException( "no id mapping for \"" + n.getName() + "\" (attempting to write [" + f
542                             + "])" );
543                 }
544                 final Sequence seq = new Sequence();
545                 seq.setName( id_map.get( n.getName() ) );
546                 n.getNodeData().addSequence( seq );
547             }
548         }
549         final PhylogenyWriter writer = new PhylogenyWriter();
550         writer.toPhyloXML( f, p, 0 );
551         if ( comment != null ) {
552             System.out.println( comment + f.getCanonicalPath() );
553         }
554     }
555
556     private static void writeLogFile( final File logfile,
557                                       final RIO rio,
558                                       final File species_tree_file,
559                                       final File gene_trees_file,
560                                       final File outtable,
561                                       final String prg_name,
562                                       final String prg_v,
563                                       final String prg_date,
564                                       final String f,
565                                       final boolean verbose )
566             throws IOException {
567         final EasyWriter out = ForesterUtil.createEasyWriter( logfile );
568         out.println( "# " + prg_name );
569         out.println( "# version : " + prg_v );
570         out.println( "# date    : " + prg_date );
571         out.println( "# based on: " + f );
572         out.println( "# ----------------------------------" );
573         out.println( "Gene trees                          :\t" + gene_trees_file.getCanonicalPath() );
574         out.println( "Species tree                        :\t" + species_tree_file.getCanonicalPath() );
575         out.println( "All vs all orthology table          :\t" + outtable.getCanonicalPath() );
576         out.flush();
577         out.println( rio.getLog().toString() );
578         out.close();
579         if ( verbose ) {
580             System.out.println( "Wrote log to                        :\t" + logfile.getCanonicalPath() );
581         }
582     }
583
584     private final static SortedMap<String, String> obtainMapping( final File dir,
585                                                                   final String prefix,
586                                                                   final String suffix )
587             throws IOException {
588         final File the_one = ForesterUtil.getMatchingFile( dir, prefix, suffix );
589         final BasicTable<String> t = BasicTableParser.parse( the_one, '\t' );
590         return t.getColumnsAsMap( 0, 1 );
591     }
592
593     private final static Phylogeny obtainTree( final File dir, final String prefix, final String suffix )
594             throws IOException {
595         final File the_one = ForesterUtil.getMatchingFile( dir, prefix, suffix );
596         final PhylogenyFactory factory = ParserBasedPhylogenyFactory.getInstance();
597         return factory.create( the_one, PhyloXmlParser.createPhyloXmlParserXsdValidating() )[ 0 ];
598     }
599 }