+ else {
+ execute( base_algorithm,
+ most_parsimonous_duplication_model,
+ allow_stripping_of_gene_tree,
+ transfer_taxonomy,
+ gene_tree_file,
+ species_tree_file,
+ out_file,
+ log_file );
+ }
+ }
+
+ private final static void executeDir( final ALGORITHM base_algorithm,
+ final boolean most_parsimonous_duplication_model,
+ final boolean allow_stripping_of_gene_tree,
+ final boolean transfer_taxonomy,
+ final File gene_tree_files[],
+ final File species_tree_file,
+ final File outdir )
+ throws IOException {
+ final File log_file = new File( outdir, LOGFILE_NAME );
+ if ( ForesterUtil.isWritableFile( log_file ) != null ) {
+ ForesterUtil.fatalError( gsdi.PRG_NAME, ForesterUtil.isWritableFile( log_file ) );
+ }
+ EasyWriter log_writer = null;
+ try {
+ log_writer = ForesterUtil.createEasyWriter( log_file );
+ }
+ catch ( final IOException e ) {
+ ForesterUtil.fatalError( gsdi.PRG_NAME, "Failed to create [" + log_file + "]: " + e.getMessage() );
+ }
+ log_writer.println( "# " + PRG_NAME );
+ log_writer.println( "# Version\t" + PRG_VERSION );
+ log_writer.println( "# Date\t" + PRG_DATE );
+ log_writer.println( "# Forester version\t" + ForesterConstants.FORESTER_VERSION );
+ log_writer.println( "# Species tree\t" + species_tree_file.getCanonicalPath() );
+ if ( base_algorithm == ALGORITHM.GSDI ) {
+ log_writer.println( "# Algorithm\tGSDI" );
+ }
+ else if ( base_algorithm == ALGORITHM.GSDIR ) {
+ log_writer.println( "# Algorithm\tGSDIR" );
+ }
+ log_writer.println( "# Use most parsimonous duplication model\t" + most_parsimonous_duplication_model );
+ log_writer.println( "# Allow stripping of gene tree nodes\t" + allow_stripping_of_gene_tree );
+ log_writer.println( "# Start time\t" + new SimpleDateFormat( "yyyyMMdd HH:mm:ss" ).format( new Date() ) );
+ log_writer.println();
+ log_writer.print( "Gene-tree file\t" );
+ log_writer.print( "Gene-tree name/#\t" );
+ log_writer.print( "Ext. nodes\t" );
+ log_writer.print( "Speciations\t" );
+ log_writer.print( "Duplications\t" );
+ if ( !most_parsimonous_duplication_model ) {
+ log_writer.print( "Spec. or Dup.\t" );
+ }
+ if ( allow_stripping_of_gene_tree ) {
+ log_writer.print( "Stripped gene-tree ext. nodes\t" );
+ }
+ log_writer.print( "Taxonomy mapping" );
+ log_writer.println();
+ int counter = 0;
+ Arrays.sort( gene_tree_files );
+ for( final File gene_tree_file : gene_tree_files ) {
+ String outname = gene_tree_file.getName();
+ if ( outname.indexOf( "." ) > 0 ) {
+ outname = outname.substring( 0, outname.lastIndexOf( "." ) );
+ }
+ outname = outname + OUTTREE_SUFFIX;
+ counter += executeOneTreeInDir( base_algorithm,
+ most_parsimonous_duplication_model,
+ allow_stripping_of_gene_tree,
+ transfer_taxonomy,
+ gene_tree_file,
+ species_tree_file,
+ new File( outdir, outname ),
+ log_writer );
+ log_writer.flush();
+ System.out.print( "\r" + counter );
+ }
+ System.out.print( "\r" );
+ log_writer.close();
+ System.out.println( "Analyzed " + counter + " gene trees" );
+ System.out.println();
+ System.out.println( "Wrote log to: " + log_file.getCanonicalPath() );
+ System.out.println();
+ }
+
+ private final static int executeOneTreeInDir( final ALGORITHM base_algorithm,
+ final boolean most_parsimonous_duplication_model,
+ final boolean allow_stripping_of_gene_tree,
+ final boolean transfer_taxonomy,
+ final File gene_tree_file,
+ final File species_tree_file,
+ final File out_file,
+ final EasyWriter log_writer )
+ throws IOException {
+ if ( ForesterUtil.isReadableFile( gene_tree_file ) != null ) {
+ ForesterUtil.fatalError( gsdi.PRG_NAME, ForesterUtil.isReadableFile( gene_tree_file ) );
+ }
+ if ( ForesterUtil.isReadableFile( species_tree_file ) != null ) {
+ ForesterUtil.fatalError( gsdi.PRG_NAME, ForesterUtil.isReadableFile( species_tree_file ) );
+ }
+ if ( ForesterUtil.isWritableFile( out_file ) != null ) {
+ ForesterUtil.fatalError( gsdi.PRG_NAME, ForesterUtil.isWritableFile( out_file ) );
+ }
+ Phylogeny gene_trees[] = null;
+ try {
+ final PhylogenyFactory factory = ParserBasedPhylogenyFactory.getInstance();
+ gene_trees = factory.create( gene_tree_file, PhyloXmlParser.createPhyloXmlParserXsdValidating() );
+ }
+ catch ( final IOException e ) {
+ fatalError( "error",
+ "failed to read gene tree from [" + gene_tree_file + "]: " + e.getMessage(),
+ log_writer );
+ }
+ int counter = 0;
+ final List<Phylogeny> out_trees = new ArrayList<Phylogeny>();
+ for( final Phylogeny gene_tree : gene_trees ) {
+ if ( !gene_tree.isEmpty() && gene_tree.getNumberOfExternalNodes() > 1 ) {
+ Phylogeny species_tree = null;
+ try {
+ species_tree = SDIutil.parseSpeciesTree( gene_tree,
+ species_tree_file,
+ REPLACE_UNDERSCORES_IN_NH_SPECIES_TREE,
+ true,
+ TAXONOMY_EXTRACTION.NO );
+ }
+ catch ( final PhyloXmlDataFormatException e ) {
+ fatalError( "user error",
+ "failed to transfer general node name, in [" + species_tree_file + "]: "
+ + e.getMessage(),
+ log_writer );
+ }
+ catch ( final SDIException e ) {
+ fatalError( "user error", e.getMessage(), log_writer );
+ }
+ catch ( final IOException e ) {
+ fatalError( "error",
+ "Failed to read species tree from [" + species_tree_file + "]: " + e.getMessage(),
+ log_writer );
+ }
+ gene_tree.setRooted( true );
+ species_tree.setRooted( true );
+ if ( !gene_tree.isCompletelyBinary() ) {
+ fatalError( "user error",
+ "gene tree [" + gene_tree_file + "] is not completely binary",
+ log_writer );
+ }
+ if ( base_algorithm == ALGORITHM.SDI ) {
+ if ( !species_tree.isCompletelyBinary() ) {
+ fatalError( "user error",
+ "species tree is not completely binary, use GSDI or GSDIR instead",
+ log_writer );
+ }
+ }
+ log_writer.print( gene_tree_file.getName() );
+ log_writer.print( "\t" );
+ log_writer.print( ( ForesterUtil.isEmpty( gene_tree.getName() ) ? "" : gene_tree.getName() ) );
+ if ( gene_trees.length > 1 ) {
+ log_writer.print( ( ForesterUtil.isEmpty( gene_tree.getName() ) ? Integer.toString( counter )
+ : ( ":" + Integer.toString( counter ) ) ) );
+ }
+ log_writer.print( "\t" );
+ GSDII gsdii = null;
+ try {
+ if ( base_algorithm == ALGORITHM.GSDI ) {
+ gsdii = new GSDI( gene_tree,
+ species_tree,
+ most_parsimonous_duplication_model,
+ allow_stripping_of_gene_tree,
+ true,
+ transfer_taxonomy );
+ }
+ else if ( base_algorithm == ALGORITHM.GSDIR ) {
+ gsdii = new GSDIR( gene_tree,
+ species_tree,
+ allow_stripping_of_gene_tree,
+ true,
+ transfer_taxonomy );
+ }
+ }
+ catch ( final SDIException e ) {
+ fatalError( "user error", e.getLocalizedMessage(), log_writer );
+ }
+ catch ( final OutOfMemoryError e ) {
+ ForesterUtil.outOfMemoryError( e );
+ }
+ catch ( final Exception e ) {
+ e.printStackTrace();
+ fatalError( "unexpected error", e.toString(), log_writer );
+ }
+ if ( base_algorithm == ALGORITHM.GSDIR ) {
+ final Phylogeny gt = ( ( GSDIR ) gsdii ).getMinDuplicationsSumGeneTree();
+ gt.setRerootable( false );
+ out_trees.add( gt );
+ }
+ else {
+ gene_tree.setRerootable( false );
+ out_trees.add( gene_tree );
+ }
+ log_writer.print( gene_tree.getNumberOfExternalNodes() + "\t" );
+ log_writer.print( gsdii.getSpeciationsSum() + "\t" );
+ if ( ( base_algorithm == ALGORITHM.GSDIR ) ) {
+ final GSDIR gsdir = ( GSDIR ) gsdii;
+ log_writer.print( gsdir.getMinDuplicationsSum() + "\t" );
+ }
+ else if ( ( base_algorithm == ALGORITHM.GSDI ) ) {
+ final GSDI gsdi = ( GSDI ) gsdii;
+ log_writer.print( gsdi.getDuplicationsSum() + "\t" );
+ if ( !most_parsimonous_duplication_model ) {
+ log_writer.print( gsdi.getSpeciationOrDuplicationEventsSum() + "\t" );
+ }
+ }
+ if ( allow_stripping_of_gene_tree ) {
+ log_writer.print( gsdii.getStrippedExternalGeneTreeNodes().size() + "\t" );
+ }
+ log_writer.print( gsdii.getTaxCompBase().toString() );
+ log_writer.println();
+ ++counter;
+ }
+ }
+ if ( counter > 0 ) {
+ try {
+ final PhylogenyWriter writer = new PhylogenyWriter();
+ writer.toPhyloXML( out_file, out_trees, 0, ForesterUtil.LINE_SEPARATOR );
+ }
+ catch ( final IOException e ) {
+ ForesterUtil
+ .fatalError( PRG_NAME,
+ "Failed to write to [" + out_file.getCanonicalPath() + "]: " + e.getMessage() );
+ }
+ }
+ return counter;
+ }
+
+ private final static void execute( final ALGORITHM base_algorithm,
+ final boolean most_parsimonous_duplication_model,
+ final boolean allow_stripping_of_gene_tree,
+ final boolean transfer_taxonomy,
+ final File gene_tree_file,
+ final File species_tree_file,
+ final File out_file,
+ final File log_file )
+ throws IOException {