taxonomy code more stringent now
[jalview.git] / forester / java / src / org / forester / phylogeny / Phylogeny.java
index a3277ba..b1677b1 100644 (file)
@@ -7,7 +7,7 @@
 // Copyright (C) 2000-2001 Washington University School of Medicine
 // and Howard Hughes Medical Institute
 // All rights reserved
-// 
+//
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
@@ -17,7 +17,7 @@
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 // Lesser General Public License for more details.
-// 
+//
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
@@ -39,9 +39,11 @@ import java.util.NoSuchElementException;
 import java.util.Vector;
 
 import org.forester.io.writers.PhylogenyWriter;
+import org.forester.phylogeny.PhylogenyNodeI.NH_CONVERSION_SUPPORT_VALUE_STYLE;
 import org.forester.phylogeny.data.BranchData;
 import org.forester.phylogeny.data.Confidence;
 import org.forester.phylogeny.data.Identifier;
+import org.forester.phylogeny.data.PhylogenyDataUtil;
 import org.forester.phylogeny.data.Sequence;
 import org.forester.phylogeny.data.SequenceRelation;
 import org.forester.phylogeny.data.SequenceRelation.SEQUENCE_RELATION_TYPE;
@@ -111,7 +113,7 @@ public class Phylogeny {
         new_node.setParent( sibling_parent );
         sibling.setParent( new_node );
         sibling_parent.setChildNode( sibling_index, new_node );
-        final double new_dist = sibling.getDistanceToParent() == PhylogenyNode.DISTANCE_DEFAULT ? PhylogenyNode.DISTANCE_DEFAULT
+        final double new_dist = sibling.getDistanceToParent() == PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT ? PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT
                 : sibling.getDistanceToParent() / 2;
         new_node.setDistanceToParent( new_dist );
         sibling.setDistanceToParent( new_dist );
@@ -219,14 +221,13 @@ public class Phylogeny {
      * @param remove_us the parent node of the subtree to be deleted
      */
     public void deleteSubtree( final PhylogenyNode remove_us, final boolean collapse_resulting_node_with_one_desc ) {
-        if ( isEmpty() ) {
+        if ( isEmpty() || ( remove_us.isRoot() && ( getNumberOfExternalNodes() != 1 ) ) ) {
             return;
         }
-        if ( remove_us.isRoot() ) {
+        if ( remove_us.isRoot() && ( getNumberOfExternalNodes() == 1 ) ) {
             init();
-            return;
         }
-        if ( !collapse_resulting_node_with_one_desc ) {
+        else if ( !collapse_resulting_node_with_one_desc ) {
             remove_us.getParent().removeChildNode( remove_us );
         }
         else {
@@ -267,7 +268,7 @@ public class Phylogeny {
                 }
             }
         }
-        remove_us.setParent( null );
+        remove_us.removeConnections();
         setIdHash( null );
         externalNodesHaveChanged();
     }
@@ -563,6 +564,21 @@ public class Phylogeny {
         return nodes.get( 0 );
     }
 
+    /**
+     * This is time-inefficient since it runs a iterator each time it is called.
+     * 
+     */
+    public int getNodeCount() {
+        if ( isEmpty() ) {
+            return 0;
+        }
+        int c = 0;
+        for( final PhylogenyNodeIterator it = iteratorPreorder(); it.hasNext(); it.next() ) {
+            ++c;
+        }
+        return c;
+    }
+
     public int getNumberOfBranches() {
         if ( isEmpty() ) {
             return 0;
@@ -850,46 +866,6 @@ public class Phylogeny {
         PhylogenyNode.setNodeCount( max + 1 );
     }
 
-    /**
-     * Arranges the order of childern for each node of this Phylogeny in such a
-     * way that either the branch with more children is on top (right) or on
-     * bottom (left), dependent on the value of boolean order.
-     * 
-     * @param order
-     *            decides in which direction to order
-     */
-    public void orderAppearance( final boolean order ) throws RuntimeException {
-        if ( !isTree() ) {
-            throw new FailedConditionCheckException( "Attempt to order appearance on phylogeny which is not tree-like." );
-        }
-        if ( isEmpty() ) {
-            return;
-        }
-        orderAppearanceHelper( getRoot(), order );
-    }
-
-    // Helper method for "orderAppearance(boolean)".
-    // Traverses this Phylogeny recusively.
-    private void orderAppearanceHelper( final PhylogenyNode n, final boolean order ) {
-        if ( n.isExternal() ) {
-            return;
-        }
-        else {
-            PhylogenyNode temp = null;
-            // FIXME
-            if ( ( n.getNumberOfDescendants() == 2 )
-                    && ( n.getChildNode1().getNumberOfExternalNodes() != n.getChildNode2().getNumberOfExternalNodes() )
-                    && ( ( n.getChildNode1().getNumberOfExternalNodes() < n.getChildNode2().getNumberOfExternalNodes() ) == order ) ) {
-                temp = n.getChildNode1();
-                n.setChild1( n.getChildNode2() );
-                n.setChild2( temp );
-            }
-            for( int i = 0; i < n.getNumberOfDescendants(); ++i ) {
-                orderAppearanceHelper( n.getChildNode( i ), order );
-            }
-        }
-    }
-
     public void preOrderReId() {
         if ( isEmpty() ) {
             return;
@@ -1093,8 +1069,8 @@ public class Phylogeny {
                 b.setBranchData( ( BranchData ) a.getBranchDataDirectly().copy() );
             }
             // New root is always placed in the middle of the branch:
-            if ( a.getDistanceToParent() == PhylogenyNode.DISTANCE_DEFAULT ) {
-                b.setDistanceToParent( PhylogenyNode.DISTANCE_DEFAULT );
+            if ( a.getDistanceToParent() == PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT ) {
+                b.setDistanceToParent( PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT );
             }
             else {
                 if ( distance_n_to_parent >= 0.0 ) {
@@ -1127,9 +1103,9 @@ public class Phylogeny {
             if ( c.getNumberOfDescendants() == 2 ) {
                 final PhylogenyNode node = c.getChildNode( 1 - b.getChildNodeIndex( c ) );
                 node.setParent( b );
-                if ( ( c.getDistanceToParent() == PhylogenyNode.DISTANCE_DEFAULT )
-                        && ( node.getDistanceToParent() == PhylogenyNode.DISTANCE_DEFAULT ) ) {
-                    node.setDistanceToParent( PhylogenyNode.DISTANCE_DEFAULT );
+                if ( ( c.getDistanceToParent() == PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT )
+                        && ( node.getDistanceToParent() == PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT ) ) {
+                    node.setDistanceToParent( PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT );
                 }
                 else {
                     node.setDistanceToParent( ( c.getDistanceToParent() >= 0.0 ? c.getDistanceToParent() : 0.0 )
@@ -1239,35 +1215,15 @@ public class Phylogeny {
         _type = type;
     }
 
-    /**
-     * Swaps the the two childern of a PhylogenyNode node of this Phylogeny.
-     * <p>
-     * (Last modified: 06/13/01)
-     * 
-     * @param node
-     *            a PhylogenyNode of this Phylogeny
-     */
-    public void swapChildren( final PhylogenyNode node ) throws RuntimeException {
-        if ( !isTree() ) {
-            throw new FailedConditionCheckException( "Attempt to swap children on phylogeny which is not tree-like." );
-        }
-        if ( isEmpty() || node.isExternal() || ( node.getNumberOfDescendants() < 2 ) ) {
-            return;
-        }
-        final PhylogenyNode first = node.getFirstChildNode();
-        for( int i = 1; i < node.getNumberOfDescendants(); ++i ) {
-            node.setChildNode( i - 1, node.getChildNode( i ) );
-        }
-        node.setChildNode( node.getNumberOfDescendants() - 1, first );
-    } // swapChildren( PhylogenyNode )
-
     public String toNewHampshire() {
-        return toNewHampshire( false );
+        return toNewHampshire( false, NH_CONVERSION_SUPPORT_VALUE_STYLE.NONE );
     }
 
-    public String toNewHampshire( final boolean simple_nh ) {
+    public String toNewHampshire( final boolean simple_nh,
+                                  final NH_CONVERSION_SUPPORT_VALUE_STYLE nh_conversion_support_style ) {
         try {
-            return new PhylogenyWriter().toNewHampshire( this, simple_nh, true ).toString();
+            return new PhylogenyWriter().toNewHampshire( this, simple_nh, true, nh_conversion_support_style )
+                    .toString();
         }
         catch ( final IOException e ) {
             throw new Error( "this should not have happend: " + e.getMessage() );
@@ -1283,15 +1239,19 @@ public class Phylogeny {
         }
     }
 
-    public String toNexus() {
+    public String toNexus( final NH_CONVERSION_SUPPORT_VALUE_STYLE svs ) {
         try {
-            return new PhylogenyWriter().toNexus( this ).toString();
+            return new PhylogenyWriter().toNexus( this, svs ).toString();
         }
         catch ( final IOException e ) {
             throw new Error( "this should not have happend: " + e.getMessage() );
         }
     }
 
+    public String toNexus() {
+        return toNexus( NH_CONVERSION_SUPPORT_VALUE_STYLE.NONE );
+    }
+
     public String toPhyloXML( final int phyloxml_level ) {
         try {
             return new PhylogenyWriter().toPhyloXML( this, phyloxml_level ).toString();