X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=forester%2Fjava%2Fsrc%2Forg%2Fforester%2Fphylogeny%2FPhylogeny.java;h=a4102d20377f63f79e92bc4233374664724d4273;hb=7ad84913635263ddc191fcbebd8a9bd46a9ac7e3;hp=9560dfac2ac9366174e8875bae5e4eb5c5a99877;hpb=b568d2173eb55795647a68afc370aba0cb1170f2;p=jalview.git diff --git a/forester/java/src/org/forester/phylogeny/Phylogeny.java b/forester/java/src/org/forester/phylogeny/Phylogeny.java index 9560dfa..a4102d2 100644 --- a/forester/java/src/org/forester/phylogeny/Phylogeny.java +++ b/forester/java/src/org/forester/phylogeny/Phylogeny.java @@ -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; @@ -66,7 +68,7 @@ public class Phylogeny { private Confidence _confidence; private Identifier _identifier; private boolean _rerootable; - private HashMap _idhash; + private HashMap _id_to_node_map; private List _external_nodes_set; private Collection _sequenceRelationQueries; private Collection _relevant_sequence_relation_types; @@ -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 ); @@ -211,7 +213,7 @@ public class Phylogeny { } /** - * Need the delete and/or rehash _idhash (not done automatically + * Need to call clearHashIdToNodeMap() afterwards (not done automatically * to allow client multiple deletions in linear time). * Need to call 'recalculateNumberOfExternalDescendants(boolean)' after this * if tree is to be displayed. @@ -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,8 +268,7 @@ public class Phylogeny { } } } - remove_us.setParent( null ); - setIdHash( null ); + remove_us.removeConnections(); externalNodesHaveChanged(); } @@ -375,11 +375,8 @@ public class Phylogeny { return _identifier; } - // --------------------------------------------------------- - // Modification of Phylogeny topology and Phylogeny appearance - // --------------------------------------------------------- - private HashMap getIdHash() { - return _idhash; + private HashMap getIdToNodeMap() { + return _id_to_node_map; } /** @@ -391,29 +388,16 @@ public class Phylogeny { /** * Finds the PhylogenyNode of this Phylogeny which has a matching ID number. - * Takes O(n) time. After method hashIDs() has been called it runs in - * constant time. - * - * @param id - * ID number (int) of the PhylogenyNode to find * @return PhylogenyNode with matching ID, null if not found */ public PhylogenyNode getNode( final int id ) throws NoSuchElementException { if ( isEmpty() ) { throw new NoSuchElementException( "attempt to get node in an empty phylogeny" ); } - if ( _idhash != null ) { - return _idhash.get( id ); + if ( ( getIdToNodeMap() == null ) || getIdToNodeMap().isEmpty() ) { + reHashIdToNodeMap(); } - else { - for( final PhylogenyNodeIterator iter = iteratorPreorder(); iter.hasNext(); ) { - final PhylogenyNode node = iter.next(); - if ( node.getId() == id ) { - return node; - } - } - } - return null; + return getIdToNodeMap().get( id ); } /** @@ -723,17 +707,21 @@ public class Phylogeny { * constant time. Important: The user is responsible for calling this method * (again) after this Phylogeny has been changed/created/renumbered. */ - public void hashIDs() { + private void reHashIdToNodeMap() { if ( isEmpty() ) { return; } - setIdHash( new HashMap() ); + setIdToNodeMap( new HashMap() ); for( final PhylogenyNodeIterator iter = iteratorPreorder(); iter.hasNext(); ) { final PhylogenyNode node = iter.next(); - getIdHash().put( node.getId(), node ); + getIdToNodeMap().put( node.getId(), node ); } } + public void clearHashIdToNodeMap() { + setIdToNodeMap( null ); + } + /** * Deletes this Phylogeny. */ @@ -744,7 +732,7 @@ public class Phylogeny { _description = ""; _type = ""; _distance_unit = ""; - _idhash = null; + _id_to_node_map = null; _confidence = null; _identifier = null; _rerootable = true; @@ -848,7 +836,7 @@ public class Phylogeny { if ( isEmpty() ) { return; } - _idhash = null; + _id_to_node_map = null; int max = 0; for( final PhylogenyNodeIterator it = iteratorPreorder(); it.hasNext(); ) { final PhylogenyNode node = it.next(); @@ -865,51 +853,11 @@ 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; } - setIdHash( null ); + setIdToNodeMap( null ); int i = PhylogenyNode.getNodeCount(); for( final PhylogenyNodeIterator it = iteratorPreorder(); it.hasNext(); ) { it.next().setId( i++ ); @@ -1108,8 +1056,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 ) { @@ -1142,9 +1090,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 ) @@ -1204,8 +1152,8 @@ public class Phylogeny { _identifier = identifier; } - void setIdHash( final HashMap idhash ) { - _idhash = idhash; + private void setIdToNodeMap( final HashMap idhash ) { + _id_to_node_map = idhash; } /** @@ -1254,35 +1202,15 @@ public class Phylogeny { _type = type; } - /** - * Swaps the the two childern of a PhylogenyNode node of this Phylogeny. - *

- * (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() ); @@ -1298,15 +1226,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();