work on data buffer for aLeaves MAFFT suite + clean up
[jalview.git] / forester / java / src / org / forester / sdi / GSDI.java
index a323ef7..bfdd14f 100644 (file)
@@ -31,8 +31,11 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
 import org.forester.phylogeny.Phylogeny;
+import org.forester.phylogeny.PhylogenyMethods;
 import org.forester.phylogeny.PhylogenyNode;
 import org.forester.phylogeny.data.Event;
 import org.forester.phylogeny.data.Taxonomy;
@@ -61,17 +64,18 @@ import org.forester.util.ForesterUtil;
  * 
  * @author Christian M. Zmasek
  */
-public final class GSDI extends SDI {
+public class GSDI extends SDI {
 
     private final boolean             _most_parsimonious_duplication_model;
     private final boolean             _strip_gene_tree;
     private final boolean             _strip_species_tree;
-    private int                       _speciation_or_duplication_events_sum;
-    private int                       _speciations_sum;
+    protected int                     _speciation_or_duplication_events_sum;
+    protected int                     _speciations_sum;
     private final List<PhylogenyNode> _stripped_gene_tree_nodes;
     private final List<PhylogenyNode> _stripped_species_tree_nodes;
     private final Set<PhylogenyNode>  _mapped_species_tree_nodes;
     private TaxonomyComparisonBase    _tax_comp_base;
+    private final SortedSet<String>   _scientific_names_mapped_to_reduced_specificity;
 
     public GSDI( final Phylogeny gene_tree,
                  final Phylogeny species_tree,
@@ -88,8 +92,9 @@ public final class GSDI extends SDI {
         _stripped_gene_tree_nodes = new ArrayList<PhylogenyNode>();
         _stripped_species_tree_nodes = new ArrayList<PhylogenyNode>();
         _mapped_species_tree_nodes = new HashSet<PhylogenyNode>();
+        _scientific_names_mapped_to_reduced_specificity = new TreeSet<String>();
         linkNodesOfG();
-        getSpeciesTree().preOrderReId();
+        PhylogenyMethods.preOrderReId( getSpeciesTree() );
         geneTreePostOrderTraversal();
     }
 
@@ -98,6 +103,25 @@ public final class GSDI extends SDI {
         this( gene_tree, species_tree, most_parsimonious_duplication_model, false, false );
     }
 
+    public GSDI( final Phylogeny gene_tree,
+                 final Phylogeny species_tree,
+                 final boolean most_parsimonious_duplication_model,
+                 final boolean strip_gene_tree,
+                 final boolean strip_species_tree,
+                 final int x ) throws SDIException {
+        super( gene_tree, species_tree );
+        _speciation_or_duplication_events_sum = 0;
+        _speciations_sum = 0;
+        _most_parsimonious_duplication_model = most_parsimonious_duplication_model;
+        _duplications_sum = 0;
+        _strip_gene_tree = strip_gene_tree;
+        _strip_species_tree = strip_species_tree;
+        _stripped_gene_tree_nodes = new ArrayList<PhylogenyNode>();
+        _stripped_species_tree_nodes = new ArrayList<PhylogenyNode>();
+        _mapped_species_tree_nodes = new HashSet<PhylogenyNode>();
+        _scientific_names_mapped_to_reduced_specificity = new TreeSet<String>();
+    }
+
     // s is the node on the species tree g maps to.
     private final void determineEvent( final PhylogenyNode s, final PhylogenyNode g ) {
         boolean oyako = false;
@@ -228,12 +252,14 @@ public final class GSDI extends SDI {
         for( final PhylogenyNodeIterator iter = _species_tree.iteratorExternalForward(); iter.hasNext(); ) {
             final PhylogenyNode s = iter.next();
             species_tree_ext_nodes.add( s );
-            final String tax_str = taxonomyToString( s, _tax_comp_base );
-            if ( !ForesterUtil.isEmpty( tax_str ) ) {
-                if ( species_to_node_map.containsKey( tax_str ) ) {
-                    throw new SDIException( "taxonomy \"" + s + "\" is not unique in species tree" );
+            if ( s.getNodeData().isHasTaxonomy() ) {
+                final String tax_str = taxonomyToString( s, _tax_comp_base );
+                if ( !ForesterUtil.isEmpty( tax_str ) ) {
+                    if ( species_to_node_map.containsKey( tax_str ) ) {
+                        throw new SDIException( "taxonomy \"" + s + "\" is not unique in species tree" );
+                    }
+                    species_to_node_map.put( tax_str, s );
                 }
-                species_to_node_map.put( tax_str, s );
             }
         }
         // Retrieve the reference to the node with a matching stringyfied taxonomy.
@@ -261,7 +287,7 @@ public final class GSDI extends SDI {
                     PhylogenyNode s = species_to_node_map.get( tax_str );
                     if ( ( _tax_comp_base == TaxonomyComparisonBase.SCIENTIFIC_NAME ) && ( s == null )
                             && ( ForesterUtil.countChars( tax_str, ' ' ) > 1 ) ) {
-                        s = tryMapByRemovingOverlySpecificData( species_to_node_map, tax_str, s );
+                        s = tryMapByRemovingOverlySpecificData( species_to_node_map, tax_str );
                     }
                     if ( s == null ) {
                         if ( _strip_gene_tree ) {
@@ -281,19 +307,25 @@ public final class GSDI extends SDI {
         } // for loop
         if ( _strip_gene_tree ) {
             stripGeneTree();
+            if ( getGeneTree().isEmpty() || ( getGeneTree().getNumberOfExternalNodes() < 2 ) ) {
+                throw new SDIException( "species could not be mapped between gene tree and species tree" );
+            }
         }
         if ( _strip_species_tree ) {
             stripSpeciesTree( species_tree_ext_nodes );
         }
     }
 
-    private final static PhylogenyNode tryMapByRemovingOverlySpecificData( final Map<String, PhylogenyNode> species_to_node_map,
-                                                                           final String tax_str,
-                                                                           PhylogenyNode s ) {
-        s = tryMapByRemovingOverlySpecificData( species_to_node_map, tax_str, " (" );
+    private final PhylogenyNode tryMapByRemovingOverlySpecificData( final Map<String, PhylogenyNode> species_to_node_map,
+                                                                    final String tax_str ) {
+        PhylogenyNode s = tryMapByRemovingOverlySpecificData( species_to_node_map, tax_str, " (" );
         if ( s == null ) {
             if ( ForesterUtil.countChars( tax_str, ' ' ) == 2 ) {
-                s = species_to_node_map.get( tax_str.substring( 0, tax_str.lastIndexOf( ' ' ) ).trim() );
+                final String new_tax_str = tax_str.substring( 0, tax_str.lastIndexOf( ' ' ) ).trim();
+                s = species_to_node_map.get( new_tax_str );
+                if ( s != null ) {
+                    addScientificNamesMappedToReducedSpecificity( tax_str, new_tax_str );
+                }
             }
         }
         if ( s == null ) {
@@ -308,16 +340,29 @@ public final class GSDI extends SDI {
         return s;
     }
 
-    private final static PhylogenyNode tryMapByRemovingOverlySpecificData( final Map<String, PhylogenyNode> species_to_node_map,
-                                                                           final String tax_str,
-                                                                           final String term ) {
+    private final PhylogenyNode tryMapByRemovingOverlySpecificData( final Map<String, PhylogenyNode> species_to_node_map,
+                                                                    final String tax_str,
+                                                                    final String term ) {
         final int i = tax_str.indexOf( term );
         if ( i > 4 ) {
-            return species_to_node_map.get( tax_str.substring( 0, i ).trim() );
+            final String new_tax_str = tax_str.substring( 0, i ).trim();
+            final PhylogenyNode s = species_to_node_map.get( new_tax_str );
+            if ( s != null ) {
+                addScientificNamesMappedToReducedSpecificity( tax_str, new_tax_str );
+            }
+            return s;
         }
         return null;
     }
 
+    private final void addScientificNamesMappedToReducedSpecificity( final String s1, final String s2 ) {
+        _scientific_names_mapped_to_reduced_specificity.add( s1 + " -> " + s2 );
+    }
+
+    public final SortedSet<String> getReMappedScientificNamesFromGeneTree() {
+        return _scientific_names_mapped_to_reduced_specificity;
+    }
+
     public TaxonomyComparisonBase getTaxCompBase() {
         return _tax_comp_base;
     }
@@ -329,6 +374,8 @@ public final class GSDI extends SDI {
                 _stripped_species_tree_nodes.add( s );
             }
         }
+        _species_tree.clearHashIdToNodeMap();
+        _species_tree.externalNodesHaveChanged();
     }
 
     public List<PhylogenyNode> getStrippedSpeciesTreeNodes() {
@@ -339,6 +386,8 @@ public final class GSDI extends SDI {
         for( final PhylogenyNode g : _stripped_gene_tree_nodes ) {
             _gene_tree.deleteSubtree( g, true );
         }
+        _gene_tree.clearHashIdToNodeMap();
+        _gene_tree.externalNodesHaveChanged();
     }
 
     public Set<PhylogenyNode> getMappedExternalSpeciesTreeNodes() {
@@ -377,12 +426,12 @@ public final class GSDI extends SDI {
         else if ( max == 1 ) {
             throw new IllegalArgumentException( "gene tree has only one node with taxonomic data" );
         }
-        else if ( max == with_sn_count ) {
-            return SDI.TaxonomyComparisonBase.SCIENTIFIC_NAME;
-        }
         else if ( max == with_id_count ) {
             return SDI.TaxonomyComparisonBase.ID;
         }
+        else if ( max == with_sn_count ) {
+            return SDI.TaxonomyComparisonBase.SCIENTIFIC_NAME;
+        }
         else {
             return SDI.TaxonomyComparisonBase.CODE;
         }