import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.forester.io.parsers.nhx.NHXParser;
import org.forester.io.writers.PhylogenyWriter;
/**
* Adds this Phylogeny to the list of child nodes of PhylogenyNode parent
* and sets the parent of this to parent.
- *
+ *
* @param n
* the PhylogenyNode to add
*/
new_node.setParent( sibling_parent );
sibling.setParent( new_node );
sibling_parent.setChildNode( sibling_index, new_node );
- final double new_dist = sibling.getDistanceToParent() == PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT ? PhylogenyDataUtil.BRANCH_LENGTH_DEFAULT
- : sibling.getDistanceToParent() / 2;
+ 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 );
externalNodesHaveChanged();
/**
* This calculates the height of the subtree emanating at n for rooted,
* tree-shaped phylogenies
- *
+ *
* @param n
* the root-node of a subtree
* @return the height of the subtree emanating at n
*/
- public double calculateSubtreeHeight( final PhylogenyNode n ) {
- if ( n.isExternal() || n.isCollapse() ) {
- return ForesterUtil.isLargerOrEqualToZero( n.getDistanceToParent() );
+ public double calculateSubtreeHeight( final PhylogenyNode n, final boolean take_collapse_into_account ) {
+ if ( n.isExternal() || ( take_collapse_into_account && n.isCollapse() ) ) {
+ return n.getDistanceToParent() > 0 ? n.getDistanceToParent() : 0;
}
else {
double max = -Double.MAX_VALUE;
for( int i = 0; i < n.getNumberOfDescendants(); ++i ) {
- final double l = calculateSubtreeHeight( n.getChildNode( i ) );
+ final double l = calculateSubtreeHeight( n.getChildNode( i ), take_collapse_into_account );
if ( l > max ) {
max = l;
}
}
- return max + ForesterUtil.isLargerOrEqualToZero( n.getDistanceToParent() );
+ return max + ( n.getDistanceToParent() > 0 ? n.getDistanceToParent() : 0 );
}
}
/**
* Need to call clearHashIdToNodeMap() afterwards (not done automatically
* to allow client multiple deletions in linear time).
- * Need to call 'recalculateNumberOfExternalDescendants(boolean)' after this
+ * 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 ( p.getNumberOfDescendants() == 2 ) {
final int pi = p.getChildNodeIndex();
if ( removed_node.isFirstChildNode() ) {
- p.getChildNode( 1 ).setDistanceToParent( PhylogenyMethods.addPhylogenyDistances( p
- .getDistanceToParent(), p.getChildNode( 1 ).getDistanceToParent() ) );
+ p.getChildNode( 1 )
+ .setDistanceToParent( PhylogenyMethods.addPhylogenyDistances( p.getDistanceToParent(),
+ p.getChildNode( 1 )
+ .getDistanceToParent() ) );
pp.setChildNode( pi, p.getChildNode( 1 ) );
}
else {
- p.getChildNode( 0 ).setDistanceToParent( PhylogenyMethods.addPhylogenyDistances( p
- .getDistanceToParent(), p.getChildNode( 0 ).getDistanceToParent() ) );
+ p.getChildNode( 0 )
+ .setDistanceToParent( PhylogenyMethods.addPhylogenyDistances( p.getDistanceToParent(),
+ p.getChildNode( 0 )
+ .getDistanceToParent() ) );
pp.setChildNode( pi, p.getChildNode( 0 ) );
}
}
}
/**
- *
+ *
* Warning. The order of the returned nodes is random
* -- and hence cannot be relied on.
- *
+ *
* @return Unordered set of PhylogenyNode
*/
public List<PhylogenyNode> getExternalNodes() {
}
/**
- * Returns the number of duplications of this Phylogeny (int). A return
- * value of -1 indicates that the number of duplications is unknown.
- */
- // public int getNumberOfDuplications() {
- // return _number_of_duplications;
- // } // getNumberOfDuplications()
- /**
- * Sets the number of duplications of this Phylogeny (int). A value of -1
- * indicates that the number of duplications is unknown.
- *
- * @param clean_nh
- * set to true for clean NH format
- */
- // public void setNumberOfDuplications( int i ) {
- // if ( i < 0 ) {
- // _number_of_duplications = -1;
- // }
- // else {
- // _number_of_duplications = i;
- // }
- // } // setNumberOfDuplications( int )
- /**
* Returns the first external PhylogenyNode.
*/
public PhylogenyNode getFirstExternalNode() {
/**
* This calculates the height for rooted, tree-shaped phylogenies. The
- * height is the longest distance from the root to an external node. Please
- * note. Child nodes of collapsed nodes are ignored -- which is useful for
- * display purposes but might be misleading for other applications.
- *
+ * height is the longest distance from the root to an external node.
+ *
* @return the height for rooted, tree-shaped phylogenies
*/
- public double getHeight() {
+ public double calculateHeight( final boolean take_collapse_into_account ) {
if ( isEmpty() ) {
return 0.0;
}
- return calculateSubtreeHeight( getRoot() );
+ return calculateSubtreeHeight( getRoot(), take_collapse_into_account );
}
public Identifier getIdentifier() {
/**
* Returns a PhylogenyNode of this Phylogeny which has a matching name.
* Throws an Exception if seqname is not present in this or not unique.
- *
+ *
* @param name
* name (String) of PhylogenyNode to find
* @return PhylogenyNode with matchin name
/**
* This is time-inefficient since it runs a iterator each time it is called.
- *
+ *
*/
public int getNodeCount() {
if ( isEmpty() ) {
/**
* Returns a List with references to all Nodes of this Phylogeny which have
* a matching name.
- *
+ *
* @param name
* name (String) of Nodes to find
* @return Vector of references to Nodes of this Phylogeny with matching
return nodes;
}
+ public List<PhylogenyNode> getNodes( final Pattern p ) {
+ 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.getName() != null ) {
+ final Matcher m = p.matcher( n.getName() );
+ if ( m.find() ) {
+ nodes.add( n );
+ }
+ }
+ }
+ return nodes;
+ }
+
public List<PhylogenyNode> getNodesViaSequenceName( final String seq_name ) {
if ( isEmpty() ) {
return null;
/**
* Returns a Vector with references to all Nodes of this Phylogeny which
* have a matching species name.
- *
+ *
* @param specname
* species name (String) of Nodes to find
* @return Vector of references to Nodes of this Phylogeny with matching
* <p>
* (Last modified: 11/22/00) Olivier CHABROL :
* olivier.chabrol@univ-provence.fr
- *
+ *
* @param n
* external PhylogenyNode whose orthologs are to be returned
* @return Vector of references to all orthologous Nodes of PhylogenyNode n
taxIdList = map.get( node );
if ( node.isDuplication() && isContains( taxIdList, taxonomyCodeRangeList ) ) {
if ( node.getChildNode1() == prev ) {
- v.addAll( getNodeByTaxonomyID( searchNodeSpeciesId, node.getChildNode2()
- .getAllExternalDescendants() ) );
+ v.addAll( getNodeByTaxonomyID( searchNodeSpeciesId,
+ node.getChildNode2().getAllExternalDescendants() ) );
}
else {
- v.addAll( getNodeByTaxonomyID( searchNodeSpeciesId, node.getChildNode1()
- .getAllExternalDescendants() ) );
+ v.addAll( getNodeByTaxonomyID( searchNodeSpeciesId,
+ node.getChildNode1().getAllExternalDescendants() ) );
}
}
}
public Collection<SequenceRelation.SEQUENCE_RELATION_TYPE> getRelevantSequenceRelationTypes() {
if ( _relevant_sequence_relation_types == null ) {
- _relevant_sequence_relation_types = new Vector<SEQUENCE_RELATION_TYPE>();
+ _relevant_sequence_relation_types = new Vector<SequenceRelation.SEQUENCE_RELATION_TYPE>();
}
return _relevant_sequence_relation_types;
}
/**
* Returns whether this is a completely binary tree (i.e. all internal nodes
* are bifurcations).
- *
+ *
*/
public boolean isCompletelyBinary() {
if ( isEmpty() ) {
return true;
}
+ public boolean isCompletelyBinaryAllow3ChildrenAtRoot() {
+ if ( isEmpty() ) {
+ return false;
+ }
+ for( final PhylogenyNodeIterator iter = iteratorPreorder(); iter.hasNext(); ) {
+ final PhylogenyNode node = iter.next();
+ if ( node.isRoot() ) {
+ if ( node.isInternal()
+ && ( ( node.getNumberOfDescendants() != 2 ) && ( node.getNumberOfDescendants() != 3 ) ) ) {
+ return false;
+ }
+ }
+ else {
+ if ( node.isInternal() && ( node.getNumberOfDescendants() != 2 ) ) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
/**
* Checks whether a Phylogeny object is deleted (or empty).
- *
+ *
* @return true if the tree is deleted (or empty), false otherwise
*/
public boolean isEmpty() {
* Resets the ID numbers of the nodes of this Phylogeny in level order,
* starting with start_label (for the root). <br>
* WARNING. After this method has been called, node IDs are no longer
- * unique.
+ * unique.
*/
public void levelOrderReID() {
if ( isEmpty() ) {
* (Re)counts the number of children for each PhylogenyNode of this
* Phylogeny. As an example, this method needs to be called after a
* Phylogeny has been reRooted and it is to be displayed.
- *
+ *
* @param consider_collapsed_nodes
* set to true to take into account collapsed nodes (collapsed
* nodes have 1 child).
* <p>
* <li>recalculateNumberOfExternalDescendants(boolean)
* <li>recalculateAndReset()
- *
+ *
* @param id
* ID (int) of PhylogenyNode of this Phylogeny
*/
* </ul>
* <p>
* (Last modified: 10/01/01)
- *
+ *
* @param n
* PhylogenyNode of this Phylogeny\
*/
*/
public void setRooted( final boolean b ) {
_rooted = b;
- } // setRooted( boolean )
+ }
public void setSequenceRelationQueries( final Collection<Sequence> sequencesByName ) {
_sequenceRelationQueries = sequencesByName;
// ---------------------------------------------------------
/**
* Converts this Phylogeny to a New Hampshire X (String) representation.
- *
+ *
* @return New Hampshire X (String) representation of this
* @see #toNewHampshireX()
*/
/**
* Return Node by TaxonomyId Olivier CHABROL :
* olivier.chabrol@univ-provence.fr
- *
+ *
* @param taxonomyID
* search taxonomy identifier
* @param nodes
/**
* 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
* 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
/**
* 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