// 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;
import java.util.NoSuchElementException;
import java.util.Vector;
+import org.forester.io.parsers.nhx.NHXParser;
import org.forester.io.writers.PhylogenyWriter;
+import org.forester.phylogeny.PhylogenyNode.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.Sequence;
import org.forester.phylogeny.data.SequenceRelation;
import org.forester.phylogeny.data.SequenceRelation.SEQUENCE_RELATION_TYPE;
+import org.forester.phylogeny.factories.ParserBasedPhylogenyFactory;
+import org.forester.phylogeny.factories.PhylogenyFactory;
import org.forester.phylogeny.iterators.ExternalForwardIterator;
import org.forester.phylogeny.iterators.LevelOrderTreeIterator;
import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
private Confidence _confidence;
private Identifier _identifier;
private boolean _rerootable;
- private HashMap<Integer, PhylogenyNode> _idhash;
+ private HashMap<Long, PhylogenyNode> _id_to_node_map;
private List<PhylogenyNode> _external_nodes_set;
private Collection<Sequence> _sequenceRelationQueries;
private Collection<SequenceRelation.SEQUENCE_RELATION_TYPE> _relevant_sequence_relation_types;
}
}
+ public void clearHashIdToNodeMap() {
+ setIdToNodeMap( null );
+ }
+
/**
* Returns a deep copy of this Phylogeny.
* <p>
}
/**
- * Returns a shallow copy of this Phylogeny.
+ * Returns a deep copy of this Phylogeny.
* <p>
* (The resulting Phylogeny has its references in the external nodes
* corrected, if they are lacking/obsolete in this.)
*/
- public Phylogeny copyShallow() {
- return copyShallow( _root );
- }
-
- public Phylogeny copyShallow( final PhylogenyNode source ) {
+ public Phylogeny copy( final PhylogenyNode source ) {
final Phylogeny tree = new Phylogeny();
if ( isEmpty() ) {
tree.init();
return tree;
}
tree._rooted = _rooted;
- tree._name = _name;
- tree._description = _description;
- tree._type = _type;
+ tree._name = new String( _name );
+ tree._description = new String( _description );
+ tree._type = new String( _type );
tree._rerootable = _rerootable;
- tree._distance_unit = _distance_unit;
- tree._confidence = _confidence;
- tree._identifier = _identifier;
+ tree._distance_unit = new String( _distance_unit );
+ if ( _confidence != null ) {
+ tree._confidence = ( Confidence ) _confidence.copy();
+ }
+ if ( _identifier != null ) {
+ tree._identifier = ( Identifier ) _identifier.copy();
+ }
tree.setAllowMultipleParents( isAllowMultipleParents() );
- tree._root = PhylogenyMethods.copySubTreeShallow( source );
+ tree._root = PhylogenyMethods.copySubTree( source );
return tree;
}
/**
- * Returns a deep copy of this Phylogeny.
+ * Returns a shallow copy of this Phylogeny.
* <p>
* (The resulting Phylogeny has its references in the external nodes
* corrected, if they are lacking/obsolete in this.)
*/
- public Phylogeny copy( final PhylogenyNode source ) {
+ public Phylogeny copyShallow() {
+ return copyShallow( _root );
+ }
+
+ public Phylogeny copyShallow( final PhylogenyNode source ) {
final Phylogeny tree = new Phylogeny();
if ( isEmpty() ) {
tree.init();
return tree;
}
tree._rooted = _rooted;
- tree._name = new String( _name );
- tree._description = new String( _description );
- tree._type = new String( _type );
+ tree._name = _name;
+ tree._description = _description;
+ tree._type = _type;
tree._rerootable = _rerootable;
- tree._distance_unit = new String( _distance_unit );
- if ( _confidence != null ) {
- tree._confidence = ( Confidence ) _confidence.copy();
- }
- if ( _identifier != null ) {
- tree._identifier = ( Identifier ) _identifier.copy();
- }
+ tree._distance_unit = _distance_unit;
+ tree._confidence = _confidence;
+ tree._identifier = _identifier;
tree.setAllowMultipleParents( isAllowMultipleParents() );
- tree._root = PhylogenyMethods.copySubTree( source );
+ tree._root = PhylogenyMethods.copySubTreeShallow( source );
return tree;
}
/**
- * 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.
* @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 {
}
}
}
- remove_us.setParent( null );
- setIdHash( null );
+ remove_us.removeConnections();
externalNodesHaveChanged();
}
return _distance_unit;
}
+ public final static Phylogeny createInstanceFromNhxString( final String nhx ) throws IOException {
+ final PhylogenyFactory factory = ParserBasedPhylogenyFactory.getInstance();
+ return factory.create( nhx, new NHXParser() )[ 0 ];
+ }
+
/**
*
* Warning. The order of the returned nodes is random
return _identifier;
}
- // ---------------------------------------------------------
- // Modification of Phylogeny topology and Phylogeny appearance
- // ---------------------------------------------------------
- private HashMap<Integer, PhylogenyNode> getIdHash() {
- return _idhash;
- }
-
/**
* Returns the name of this 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 {
+ public PhylogenyNode getNode( final long id ) throws NoSuchElementException {
if ( isEmpty() ) {
throw new NoSuchElementException( "attempt to get node in an empty phylogeny" );
}
- if ( _idhash != null ) {
- return _idhash.get( id );
- }
- else {
- for( final PhylogenyNodeIterator iter = iteratorPreorder(); iter.hasNext(); ) {
- final PhylogenyNode node = iter.next();
- if ( node.getId() == id ) {
- return node;
- }
- }
+ if ( ( getIdToNodeMap() == null ) || getIdToNodeMap().isEmpty() ) {
+ reHashIdToNodeMap();
}
- return null;
+ return getIdToNodeMap().get( id );
}
/**
}
final List<PhylogenyNode> nodes = getNodes( name );
if ( ( nodes == null ) || ( nodes.size() < 1 ) ) {
- throw new IllegalArgumentException( "node named [" + name + "] not found" );
+ throw new IllegalArgumentException( "node named \"" + name + "\" not found" );
}
if ( nodes.size() > 1 ) {
- throw new IllegalArgumentException( "node named [" + name + "] not unique" );
+ throw new IllegalArgumentException( "node named \"" + name + "\" not unique" );
}
return nodes.get( 0 );
}
/**
- * Return Node by TaxonomyId Olivier CHABROL :
- * olivier.chabrol@univ-provence.fr
+ * This is time-inefficient since it runs a iterator each time it is called.
*
- * @param taxonomyID
- * search taxonomy identifier
- * @param nodes
- * sublist node to search
- * @return List node with the same taxonomy identifier
*/
- private List<PhylogenyNode> getNodeByTaxonomyID( final String taxonomyID, final List<PhylogenyNode> nodes ) {
- final List<PhylogenyNode> retour = new ArrayList<PhylogenyNode>();
- for( final PhylogenyNode node : nodes ) {
- if ( taxonomyID.equals( PhylogenyMethods.getTaxonomyIdentifier( node ) ) ) {
- retour.add( node );
- }
+ public int getNodeCount() {
+ if ( isEmpty() ) {
+ return 0;
}
- return retour;
+ int c = 0;
+ for( final PhylogenyNodeIterator it = iteratorPreorder(); it.hasNext(); it.next() ) {
+ ++c;
+ }
+ return c;
}
/**
return nodes;
}
+ public List<PhylogenyNode> getNodesViaSequenceSymbol( final String seq_name ) {
+ if ( isEmpty() ) {
+ return null;
+ }
+ final List<PhylogenyNode> nodes = new ArrayList<PhylogenyNode>();
+ for( final PhylogenyNodeIterator iter = iteratorPreorder(); iter.hasNext(); ) {
+ final PhylogenyNode n = iter.next();
+ if ( n.getNodeData().isHasSequence() && n.getNodeData().getSequence().getSymbol().equals( seq_name ) ) {
+ nodes.add( n );
+ }
+ }
+ return nodes;
+ }
+
+ public List<PhylogenyNode> getNodesViaGeneName( final String seq_name ) {
+ if ( isEmpty() ) {
+ return null;
+ }
+ final List<PhylogenyNode> nodes = new ArrayList<PhylogenyNode>();
+ for( final PhylogenyNodeIterator iter = iteratorPreorder(); iter.hasNext(); ) {
+ final PhylogenyNode n = iter.next();
+ if ( n.getNodeData().isHasSequence() && n.getNodeData().getSequence().getGeneName().equals( seq_name ) ) {
+ nodes.add( n );
+ }
+ }
+ return nodes;
+ }
+
public List<PhylogenyNode> getNodesViaTaxonomyCode( final String taxonomy_code ) {
if ( isEmpty() ) {
return null;
return nodes.get( 0 );
}
- /**
- * This is time-inefficient since it runs a iterator each time it is called.
- *
- */
- public int getNodeCount() {
+ public int getNumberOfBranches() {
if ( isEmpty() ) {
return 0;
}
int c = 0;
- for( final PhylogenyNodeIterator it = iteratorPreorder(); it.hasNext(); it.next() ) {
+ for( final PhylogenyNodeIterator iter = iteratorPreorder(); iter.hasNext(); iter.next() ) {
++c;
}
+ if ( !isRooted() ) {
+ --c;
+ }
return c;
}
- public int getNumberOfBranches() {
+ public int getNumberOfInternalNodes() {
if ( isEmpty() ) {
return 0;
}
int c = 0;
- for( final PhylogenyNodeIterator iter = iteratorPreorder(); iter.hasNext(); iter.next() ) {
- ++c;
+ for( final PhylogenyNodeIterator iter = iteratorPreorder(); iter.hasNext(); ) {
+ if ( iter.next().isInternal() ) {
+ ++c;
+ }
}
if ( !isRooted() ) {
--c;
return _sequenceRelationQueries;
}
- /**
- * List all species contains in all leaf under a node Olivier CHABROL :
- * olivier.chabrol@univ-provence.fr
- *
- * @param node
- * PhylogenyNode whose sub node species are returned
- * @return species contains in all leaf under the param node
- */
- private List<String> getSubNodeTaxonomy( final PhylogenyNode node ) {
- final List<String> taxonomyList = new ArrayList<String>();
- final List<PhylogenyNode> childs = node.getAllExternalDescendants();
- String speciesId = null;
- for( final PhylogenyNode phylogenyNode : childs ) {
- // taxId = new Long(phylogenyNode.getTaxonomyID());
- speciesId = PhylogenyMethods.getTaxonomyIdentifier( phylogenyNode );
- if ( !taxonomyList.contains( speciesId ) ) {
- taxonomyList.add( speciesId );
- }
- }
- return taxonomyList;
- }
-
- /**
- * Create a map [<PhylogenyNode, List<String>], the list contains the
- * species contains in all leaf under phylogeny node Olivier CHABROL :
- * olivier.chabrol@univ-provence.fr
- *
- * @param node
- * the tree root node
- * @param map
- * map to fill
- */
- private void getTaxonomyMap( final PhylogenyNode node, final Map<PhylogenyNode, List<String>> map ) {
- // node is leaf
- if ( node.isExternal() ) {
- return;
- }
- map.put( node, getSubNodeTaxonomy( node ) );
- getTaxonomyMap( node.getChildNode1(), map );
- getTaxonomyMap( node.getChildNode2(), map );
- }
-
public String getType() {
return _type;
}
/**
- * Hashes the ID number of each PhylogenyNode of this Phylogeny to its
- * corresponding PhylogenyNode, in order to make method getNode( id ) run in
- * constant time. Important: The user is responsible for calling this method
- * (again) after this Phylogeny has been changed/created/renumbered.
- */
- public void hashIDs() {
- if ( isEmpty() ) {
- return;
- }
- setIdHash( new HashMap<Integer, PhylogenyNode>() );
- for( final PhylogenyNodeIterator iter = iteratorPreorder(); iter.hasNext(); ) {
- final PhylogenyNode node = iter.next();
- getIdHash().put( node.getId(), node );
- }
- }
-
- /**
* Deletes this Phylogeny.
*/
public void init() {
_description = "";
_type = "";
_distance_unit = "";
- _idhash = null;
+ _id_to_node_map = null;
_confidence = null;
_identifier = null;
_rerootable = true;
setAllowMultipleParents( Phylogeny.ALLOW_MULTIPLE_PARENTS_DEFAULT );
}
- private boolean isAllowMultipleParents() {
- return _allow_multiple_parents;
- }
-
/**
* Returns whether this is a completely binary tree (i.e. all internal nodes
* are bifurcations).
}
/**
- * Util method to check if all element of a list is contains in the
- * rangeList. Olivier CHABROL : olivier.chabrol@univ-provence.fr
- *
- * @param list
- * list to be check
- * @param rangeList
- * the range list to compare
- * @return <code>true</code> if all param list element are contains in param
- * rangeList, <code>false</code> otherwise.
- */
- private boolean isContains( final List<String> list, final List<String> rangeList ) {
- if ( list.size() > rangeList.size() ) {
- return false;
- }
- String l = null;
- for( final Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
- l = iterator.next();
- if ( !rangeList.contains( l ) ) {
- return false;
- }
- }
- return true;
- }
-
- /**
* Checks whether a Phylogeny object is deleted (or empty).
*
* @return true if the tree is deleted (or empty), false otherwise
if ( isEmpty() ) {
return;
}
- _idhash = null;
- int max = 0;
+ _id_to_node_map = null;
+ long max = 0;
for( final PhylogenyNodeIterator it = iteratorPreorder(); it.hasNext(); ) {
final PhylogenyNode node = it.next();
if ( node.isRoot() ) {
}
/**
- * 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 );
- int i = PhylogenyNode.getNodeCount();
- for( final PhylogenyNodeIterator it = iteratorPreorder(); it.hasNext(); ) {
- it.next().setId( i++ );
- }
- PhylogenyNode.setNodeCount( i );
- }
-
- /**
* Prints descriptions of all external Nodes of this Phylogeny to
* System.out.
*/
* @param id
* ID (int) of PhylogenyNode of this Phylogeny
*/
- public void reRoot( final int id ) {
+ public void reRoot( final long id ) {
reRoot( getNode( id ) );
}
/**
- * Places the root of this Phylogeny on Branch b. The new root is always
- * placed on the middle of the branch b.
- *
- */
- public void reRoot( final PhylogenyBranch b ) {
- final PhylogenyNode n1 = b.getFirstNode();
- final PhylogenyNode n2 = b.getSecondNode();
- if ( n1.isExternal() ) {
- reRoot( n1 );
- }
- else if ( n2.isExternal() ) {
- reRoot( n2 );
- }
- else if ( ( n2 == n1.getChildNode1() ) || ( n2 == n1.getChildNode2() ) ) {
- reRoot( n2 );
- }
- else if ( ( n1 == n2.getChildNode1() ) || ( n1 == n2.getChildNode2() ) ) {
- reRoot( n1 );
- }
- else if ( ( n1.getParent() != null ) && n1.getParent().isRoot()
- && ( ( n1.getParent().getChildNode1() == n2 ) || ( n1.getParent().getChildNode2() == n2 ) ) ) {
- reRoot( n1 );
- }
- else {
- throw new IllegalArgumentException( "reRoot( Branch b ): b is not a branch." );
- }
- }
-
- /**
* Places the root of this Phylogeny on the parent branch PhylogenyNode n.
* The new root is always placed on the middle of the branch.
* <p>
}
}
- private void setAllowMultipleParents( final boolean allow_multiple_parents ) {
- _allow_multiple_parents = allow_multiple_parents;
- }
-
public void setConfidence( final Confidence confidence ) {
_confidence = confidence;
}
_identifier = identifier;
}
- void setIdHash( final HashMap<Integer, PhylogenyNode> idhash ) {
- _idhash = idhash;
+ public void setIdToNodeMap( final HashMap<Long, PhylogenyNode> idhash ) {
+ _id_to_node_map = idhash;
}
/**
public void setRoot( final PhylogenyNode n ) {
_root = n;
- } // setRoot( PhylogenyNode )
+ }
/**
* Sets whether this Phylogeny is rooted or not.
_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, false );
+ return toNewHampshire( false, NH_CONVERSION_SUPPORT_VALUE_STYLE.NONE );
}
- public String toNewHampshire( final boolean simple_nh, final boolean write_conf_values_in_branckets_in_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, write_conf_values_in_branckets_in_nh )
+ return new PhylogenyWriter().toNewHampshire( this, simple_nh, true, nh_conversion_support_style )
.toString();
}
catch ( final IOException e ) {
}
}
- public String toNexus( final boolean write_conf_values_in_branckets_in_nh ) {
+ public String toNexus() {
+ return toNexus( NH_CONVERSION_SUPPORT_VALUE_STYLE.NONE );
+ }
+
+ public String toNexus( final NH_CONVERSION_SUPPORT_VALUE_STYLE svs ) {
try {
- return new PhylogenyWriter().toNexus( this, write_conf_values_in_branckets_in_nh ).toString();
+ return new PhylogenyWriter().toNexus( this, svs ).toString();
}
catch ( final IOException e ) {
throw new Error( "this should not have happend: " + e.getMessage() );
setRooted( false );
return;
} // unRoot()
+
+ private HashMap<Long, PhylogenyNode> getIdToNodeMap() {
+ return _id_to_node_map;
+ }
+
+ /**
+ * Return Node by TaxonomyId Olivier CHABROL :
+ * olivier.chabrol@univ-provence.fr
+ *
+ * @param taxonomyID
+ * search taxonomy identifier
+ * @param nodes
+ * sublist node to search
+ * @return List node with the same taxonomy identifier
+ */
+ private List<PhylogenyNode> getNodeByTaxonomyID( final String taxonomyID, final List<PhylogenyNode> nodes ) {
+ final List<PhylogenyNode> retour = new ArrayList<PhylogenyNode>();
+ for( final PhylogenyNode node : nodes ) {
+ if ( taxonomyID.equals( PhylogenyMethods.getTaxonomyIdentifier( node ) ) ) {
+ retour.add( node );
+ }
+ }
+ return retour;
+ }
+
+ /**
+ * List all species contains in all leaf under a node Olivier CHABROL :
+ * olivier.chabrol@univ-provence.fr
+ *
+ * @param node
+ * PhylogenyNode whose sub node species are returned
+ * @return species contains in all leaf under the param node
+ */
+ private List<String> getSubNodeTaxonomy( final PhylogenyNode node ) {
+ final List<String> taxonomyList = new ArrayList<String>();
+ final List<PhylogenyNode> childs = node.getAllExternalDescendants();
+ String speciesId = null;
+ for( final PhylogenyNode phylogenyNode : childs ) {
+ // taxId = new Long(phylogenyNode.getTaxonomyID());
+ speciesId = PhylogenyMethods.getTaxonomyIdentifier( phylogenyNode );
+ if ( !taxonomyList.contains( speciesId ) ) {
+ taxonomyList.add( speciesId );
+ }
+ }
+ return taxonomyList;
+ }
+
+ /**
+ * Create a map [<PhylogenyNode, List<String>], the list contains the
+ * species contains in all leaf under phylogeny node Olivier CHABROL :
+ * olivier.chabrol@univ-provence.fr
+ *
+ * @param node
+ * the tree root node
+ * @param map
+ * map to fill
+ */
+ private void getTaxonomyMap( final PhylogenyNode node, final Map<PhylogenyNode, List<String>> map ) {
+ // node is leaf
+ if ( node.isExternal() ) {
+ return;
+ }
+ map.put( node, getSubNodeTaxonomy( node ) );
+ getTaxonomyMap( node.getChildNode1(), map );
+ getTaxonomyMap( node.getChildNode2(), map );
+ }
+
+ private boolean isAllowMultipleParents() {
+ return _allow_multiple_parents;
+ }
+
+ /**
+ * Util method to check if all element of a list is contains in the
+ * rangeList. Olivier CHABROL : olivier.chabrol@univ-provence.fr
+ *
+ * @param list
+ * list to be check
+ * @param rangeList
+ * the range list to compare
+ * @return <code>true</code> if all param list element are contains in param
+ * rangeList, <code>false</code> otherwise.
+ */
+ private boolean isContains( final List<String> list, final List<String> rangeList ) {
+ if ( list.size() > rangeList.size() ) {
+ return false;
+ }
+ String l = null;
+ for( final Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
+ l = iterator.next();
+ if ( !rangeList.contains( l ) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Hashes the ID number of each PhylogenyNode of this Phylogeny to its
+ * corresponding PhylogenyNode, in order to make method getNode( id ) run in
+ * constant time. Important: The user is responsible for calling this method
+ * (again) after this Phylogeny has been changed/created/renumbered.
+ */
+ private void reHashIdToNodeMap() {
+ if ( isEmpty() ) {
+ return;
+ }
+ setIdToNodeMap( new HashMap<Long, PhylogenyNode>() );
+ for( final PhylogenyNodeIterator iter = iteratorPreorder(); iter.hasNext(); ) {
+ final PhylogenyNode node = iter.next();
+ getIdToNodeMap().put( node.getId(), node );
+ }
+ }
+
+ private void setAllowMultipleParents( final boolean allow_multiple_parents ) {
+ _allow_multiple_parents = allow_multiple_parents;
+ }
}