inprogress
[jalview.git] / forester / java / src / org / forester / phylogeny / PhylogenyMethods.java
index f2a982d..cc140e4 100644 (file)
@@ -21,7 +21,7 @@
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 //
 // Contact: phylosoft @ gmail . com
-// WWW: www.phylosoft.org/forester
+// WWW: https://sites.google.com/site/cmzmasek/home/software/forester
 
 package org.forester.phylogeny;
 
@@ -62,52 +62,15 @@ import org.forester.util.ForesterUtil;
 
 public class PhylogenyMethods {
 
-    //private static PhylogenyMethods _instance   = null;
-    //private final PhylogenyNode     _farthest_1 = null;
-    //private final PhylogenyNode     _farthest_2 = null;
     private PhylogenyMethods() {
         // Hidden constructor.
     }
 
-    //    public double calculateFurthestDistance( final Phylogeny phylogeny ) {
-    //        if ( phylogeny.getNumberOfExternalNodes() < 2 ) {
-    //            return 0.0;
-    //        }
-    //        _farthest_1 = null;
-    //        _farthest_2 = null;
-    //        PhylogenyNode node_1 = null;
-    //        PhylogenyNode node_2 = null;
-    //        double farthest_d = -Double.MAX_VALUE;
-    //        final PhylogenyMethods methods = PhylogenyMethods.getInstance();
-    //        final List<PhylogenyNode> ext_nodes = phylogeny.getRoot().getAllExternalDescendants();
-    //        for( int i = 1; i < ext_nodes.size(); ++i ) {
-    //            for( int j = 0; j < i; ++j ) {
-    //                final double d = methods.calculateDistance( ext_nodes.get( i ), ext_nodes.get( j ) );
-    //                if ( d < 0.0 ) {
-    //                    throw new RuntimeException( "distance cannot be negative" );
-    //                }
-    //                if ( d > farthest_d ) {
-    //                    farthest_d = d;
-    //                    node_1 = ext_nodes.get( i );
-    //                    node_2 = ext_nodes.get( j );
-    //                }
-    //            }
-    //        }
-    //        _farthest_1 = node_1;
-    //        _farthest_2 = node_2;
-    //        return farthest_d;
-    //    }
     @Override
     public Object clone() throws CloneNotSupportedException {
         throw new CloneNotSupportedException();
     }
 
-    // public PhylogenyNode getFarthestNode1() {
-    //      return _farthest_1;
-    // }
-    //  public PhylogenyNode getFarthestNode2() {
-    //      return _farthest_2;
-    //  }
     public static DescriptiveStatistics calculatBranchLengthStatistics( final Phylogeny phy ) {
         final DescriptiveStatistics stats = new BasicDescriptiveStatistics();
         for( final PhylogenyNodeIterator iter = phy.iteratorPreorder(); iter.hasNext(); ) {
@@ -303,6 +266,18 @@ public class PhylogenyMethods {
         return stats;
     }
 
+    public final static void collapseSubtreeStructure( final PhylogenyNode n ) {
+        final List<PhylogenyNode> eds = n.getAllExternalDescendants();
+        final List<Double> d = new ArrayList<Double>();
+        for( final PhylogenyNode ed : eds ) {
+            d.add( calculateDistanceToAncestor( n, ed ) );
+        }
+        for( int i = 0; i < eds.size(); ++i ) {
+            n.setChildNode( i, eds.get( i ) );
+            eds.get( i ).setDistanceToParent( d.get( i ) );
+        }
+    }
+
     public static int countNumberOfOneDescendantNodes( final Phylogeny phy ) {
         int count = 0;
         for( final PhylogenyNodeIterator iter = phy.iteratorPreorder(); iter.hasNext(); ) {
@@ -327,16 +302,15 @@ public class PhylogenyMethods {
 
     public static final HashMap<String, PhylogenyNode> createNameToExtNodeMap( final Phylogeny phy ) {
         final HashMap<String, PhylogenyNode> nodes = new HashMap<String, PhylogenyNode>();
-        for( final PhylogenyNodeIterator iter = phy.iteratorExternalForward(); iter.hasNext(); ) {
-            final PhylogenyNode n = iter.next();
+        final List<PhylogenyNode> ext = phy.getExternalNodes();
+        for( final PhylogenyNode n : ext ) {
             nodes.put( n.getName(), n );
         }
         return nodes;
     }
 
-    public static void deleteExternalNodesNegativeSelection( final Set<Integer> to_delete, final Phylogeny phy ) {
-        phy.clearHashIdToNodeMap();
-        for( final Integer id : to_delete ) {
+    public static void deleteExternalNodesNegativeSelection( final Set<Long> to_delete, final Phylogeny phy ) {
+        for( final Long id : to_delete ) {
             phy.deleteSubtree( phy.getNode( id ), true );
         }
         phy.clearHashIdToNodeMap();
@@ -364,24 +338,6 @@ public class PhylogenyMethods {
         p.externalNodesHaveChanged();
     }
 
-    public static void deleteExternalNodesPositiveSelection( final Set<Taxonomy> species_to_keep, final Phylogeny phy ) {
-        //   final Set<Integer> to_delete = new HashSet<Integer>();
-        for( final PhylogenyNodeIterator it = phy.iteratorExternalForward(); it.hasNext(); ) {
-            final PhylogenyNode n = it.next();
-            if ( n.getNodeData().isHasTaxonomy() ) {
-                if ( !species_to_keep.contains( n.getNodeData().getTaxonomy() ) ) {
-                    //to_delete.add( n.getNodeId() );
-                    phy.deleteSubtree( n, true );
-                }
-            }
-            else {
-                throw new IllegalArgumentException( "node " + n.getId() + " has no taxonomic data" );
-            }
-        }
-        phy.clearHashIdToNodeMap();
-        phy.externalNodesHaveChanged();
-    }
-
     public static List<String> deleteExternalNodesPositiveSelection( final String[] node_names_to_keep,
                                                                      final Phylogeny p ) {
         final PhylogenyNodeIterator it = p.iteratorExternalForward();
@@ -404,6 +360,22 @@ public class PhylogenyMethods {
         return deleted;
     }
 
+    public static void deleteExternalNodesPositiveSelectionT( final List<Taxonomy> species_to_keep, final Phylogeny phy ) {
+        final Set<Long> to_delete = new HashSet<Long>();
+        for( final PhylogenyNodeIterator it = phy.iteratorExternalForward(); it.hasNext(); ) {
+            final PhylogenyNode n = it.next();
+            if ( n.getNodeData().isHasTaxonomy() ) {
+                if ( !species_to_keep.contains( n.getNodeData().getTaxonomy() ) ) {
+                    to_delete.add( n.getId() );
+                }
+            }
+            else {
+                throw new IllegalArgumentException( "node " + n.getId() + " has no taxonomic data" );
+            }
+        }
+        deleteExternalNodesNegativeSelection( to_delete, phy );
+    }
+
     final public static void deleteInternalNodesWithOnlyOneDescendent( final Phylogeny phy ) {
         final ArrayList<PhylogenyNode> to_delete = new ArrayList<PhylogenyNode>();
         for( final PhylogenyNodeIterator iter = phy.iteratorPostorder(); iter.hasNext(); ) {
@@ -439,7 +411,7 @@ public class PhylogenyMethods {
 
     public static List<PhylogenyNode> getAllDescendants( final PhylogenyNode node ) {
         final List<PhylogenyNode> descs = new ArrayList<PhylogenyNode>();
-        final Set<Integer> encountered = new HashSet<Integer>();
+        final Set<Long> encountered = new HashSet<Long>();
         if ( !node.isExternal() ) {
             final List<PhylogenyNode> exts = node.getAllExternalDescendants();
             for( PhylogenyNode current : exts ) {
@@ -700,39 +672,6 @@ public class PhylogenyMethods {
         phylogeny.recalculateNumberOfExternalDescendants( true );
     }
 
-    public static void midpointRootOLD( final Phylogeny phylogeny ) {
-        //   if ( phylogeny.getNumberOfExternalNodes() < 2 ) {
-        //       return;
-        //   }
-        //    final PhylogenyMethods methods = getInstance();
-        //final double farthest_d = methods.calculateFurthestDistance( phylogeny );
-        // final PhylogenyNode f1 = methods.getFarthestNode1();
-        // final PhylogenyNode f2 = methods.getFarthestNode2();
-        //        if ( farthest_d <= 0.0 ) {
-        //            return;
-        //        }
-        //        double x = farthest_d / 2.0;
-        //        PhylogenyNode n = f1;
-        //        if ( PhylogenyMethods.getDistance( f1, phylogeny.getRoot() ) < PhylogenyMethods.getDistance( f2, phylogeny
-        //                .getRoot() ) ) {
-        //            n = f2;
-        //        }
-        //        while ( ( x > n.getDistanceToParent() ) && !n.isRoot() ) {
-        //            x -= ( n.getDistanceToParent() > 0 ? n.getDistanceToParent() : 0 );
-        //            n = n.getParent();
-        //        }
-        //        phylogeny.reRoot( n, x );
-        //        phylogeny.recalculateNumberOfExternalDescendants( true );
-        //        final PhylogenyNode a = getFurthestDescendant( phylogeny.getRoot().getChildNode1() );
-        //        final PhylogenyNode b = getFurthestDescendant( phylogeny.getRoot().getChildNode2() );
-        //        final double da = getDistance( a, phylogeny.getRoot() );
-        //        final double db = getDistance( b, phylogeny.getRoot() );
-        //        if ( Math.abs( da - db ) > 0.000001 ) {
-        //            throw new FailedConditionCheckException( "this should not have happened: midpoint rooting failed:  da="
-        //                    + da + ",  db=" + db + ",  diff=" + Math.abs( da - db ) );
-        //        }
-    }
-
     public static void normalizeBootstrapValues( final Phylogeny phylogeny,
                                                  final double max_bootstrap_value,
                                                  final double max_normalized_value ) {
@@ -764,25 +703,6 @@ public class PhylogenyMethods {
     }
 
     /**
-     * Returns the set of distinct taxonomies of
-     * all external nodes of node.
-     * If at least one the external nodes has no taxonomy,
-     * null is returned.
-     * 
-     */
-    public static Set<Taxonomy> obtainDistinctTaxonomies( final PhylogenyNode node ) {
-        final List<PhylogenyNode> descs = node.getAllExternalDescendants();
-        final Set<Taxonomy> tax_set = new HashSet<Taxonomy>();
-        for( final PhylogenyNode n : descs ) {
-            if ( !n.getNodeData().isHasTaxonomy() || n.getNodeData().getTaxonomy().isEmpty() ) {
-                return null;
-            }
-            tax_set.add( n.getNodeData().getTaxonomy() );
-        }
-        return tax_set;
-    }
-
-    /**
      * Returns a map of distinct taxonomies of
      * all external nodes of node.
      * If at least one of the external nodes has no taxonomy,
@@ -882,7 +802,7 @@ public class PhylogenyMethods {
             return;
         }
         phy.setIdToNodeMap( null );
-        int i = PhylogenyNode.getNodeCount();
+        long i = PhylogenyNode.getNodeCount();
         for( final PhylogenyNodeIterator it = phy.iteratorPreorder(); it.hasNext(); ) {
             it.next().setId( i++ );
         }
@@ -1570,6 +1490,24 @@ public class PhylogenyMethods {
         return PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT;
     }
 
+    static double calculateDistanceToAncestor( final PhylogenyNode anc, PhylogenyNode desc ) {
+        double d = 0;
+        boolean all_default = true;
+        while ( anc != desc ) {
+            if ( desc.getDistanceToParent() != PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT ) {
+                d += desc.getDistanceToParent();
+                if ( all_default ) {
+                    all_default = false;
+                }
+            }
+            desc = desc.getParent();
+        }
+        if ( all_default ) {
+            return PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT;
+        }
+        return d;
+    }
+
     /**
      * Deep copies the phylogeny originating from this node.
      */