Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
// NodeUtils.java
//
// (c) 1999-2001 PAL Development Core Team
//
// This package may be distributed under the
// terms of the Lesser GNU General Public License (LGPL)
package net.maizegenetics.taxa.tree;
import java.io.IOException;
import net.maizegenetics.taxa.Taxon;
import net.maizegenetics.util.FormattedOutput;
import java.io.PrintWriter;
import java.util.Vector;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Helper routines for dealing with nodes.
*
* @version $Id: NodeUtils.java,v 1.1 2007/01/12 03:26:17 tcasstevens Exp $
*
* @author Alexei Drummond
* @author Korbinian Strimmer
* @author Matthew Goode
*/
public class NodeUtils {
private static final Logger myLogger = LogManager.getLogger(NodeUtils.class);
/**
* Appends all external nodes from tree defined by root to Vector store
* @param root The root node defining tree
* @param store Where leaf nodes are stored (original contents is not touched)
*/
public static void getExternalNodes(Node root, Vector store) {
if(root.isLeaf()) {
store.addElement(root);
} else {
for(int i = 0 ; i < root.getChildCount() ; i++) {
getExternalNodes(root.getChild(i),store);
}
}
}
/**
* Obtains all external nodes from tree defined by root and returns as an array
* @param root The root node defining tree
* @return an array of nodes where each node is a leaf node, and is a member
* of the tree defined by root
*/
public static Node[] getExternalNodes(Node root) {
Vector v = new Vector();
getExternalNodes(root,v);
Node[] result = new Node[v.size()];
v.copyInto(result);
return result;
}
/**
* Appends all internal nodes from tree defined by root to Vector store
* @param root The root node defining tree
* @param store Where internal nodes are stored (original contents is not touched)
* @note Root will be the first node added
*/
public static void getInternalNodes(Node root, Vector store) {
if(!root.isLeaf()) {
store.addElement(root);
for(int i = 0 ; i < root.getChildCount() ; i++) {
getInternalNodes(root.getChild(i),store);
}
}
}
/**
* Obtains all internal nodes from tree defined by root and returns as an array
* @param root The root node defining tree
* @return an array of nodes where each node is a internal node, and is a member
* of the tree defined by root
* @note Root will be the first node added (if included)
*/
public static Node[] getInternalNodes(Node root, boolean includeRoot) {
Vector v = new Vector();
getInternalNodes(root,v);
Node[] result = new Node[v.size()];
v.copyInto(result);
if(includeRoot) {
return result;
}
Node[] adjustedResult = new Node[result.length-1];
System.arraycopy(result, 1,adjustedResult,0,adjustedResult.length);
return adjustedResult;
}
/**
* @return the maxium distance in nodes from root to a leaf
* @note this is a CompSci depth measure and has nothing to do with branch lengths/node heights :)
*/
public static int getMaxNodeDepth(Node root) {
int max = 0;
for(int i = 0 ; i < root.getChildCount() ; i++) {
int depth = getMaxNodeDepth(root.getChild(i));
if(depth>max) {
max = depth;
}
}
return max+1;
}
/**
* Calculates max/min lengths of paths from root to leaf, taking into account branch lengths
*
* @return a double array where
*
*
The first element is the minimum length path from root to leaf.
*
The second element is the second most minimum length path from root to leaf.
*
The third element is the second most maximum length path from root to leaf.
*
The forth element is the maximum length path from root to leaf.
*
* @see getMaxNodeDepth()
*/
public static final double[] getPathLengthInfo(Node root) {
double[] lengthInfo = new double[] { Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY };
getLengthInfo(root,0,lengthInfo);
return lengthInfo;
}
/**
* @return the maximum length of a path from root to a leaf
*/
public static final double getMaximumPathLengthLengthToLeaf(Node root) {
if(root.isLeaf()) { return 0; }
double maxLength = Double.NEGATIVE_INFINITY;
for(int i = 0 ; i < root.getChildCount() ; i++) {
Node c = root.getChild(i);
double length = c.getBranchLength()+getMaximumPathLengthLengthToLeaf(c);
maxLength=Math.max(length,maxLength);
}
return maxLength;
}
/**
* @return the minimum length of a path from root to a leaf
*/
public static final double getMinimumPathLengthLengthToLeaf(Node root) {
if(root.isLeaf()) { return 0; }
double minLength = Double.POSITIVE_INFINITY;
for(int i = 0 ; i < root.getChildCount() ; i++) {
Node c = root.getChild(i);
double length = c.getBranchLength()+getMinimumPathLengthLengthToLeaf(c);
minLength=Math.min(length,minLength);
}
return minLength;
}
/**
* Traverses tree (recursively) updating lengthInfo each time a leaf node is met.
* @note: first value is assumed to be minimum length, second value is assumed to be maximum length
*/
private static final void getLengthInfo(Node root, double lengthFromRoot, double[] lengthInfo) {
if(root.isLeaf()) {
if(lengthFromRootlengthInfo[2]) {
if(lengthFromRoot>lengthInfo[3]) {
lengthInfo[2] = lengthInfo[3];
lengthInfo[3] = lengthFromRoot;
} else {
lengthInfo[2] = lengthFromRoot;
}
}
} else {
for(int i = 0 ; i < root.getChildCount() ; i++) {
Node c = root.getChild(i);
getLengthInfo(c, lengthFromRoot+c.getBranchLength(),lengthInfo);
}
}
}
/**
* Converts lengths to heights, *without* assuming contemporaneous
* tips.
*/
public static void lengths2Heights(Node root) {
lengths2Heights(root, getMaximumPathLengthLengthToLeaf(root));
}
/**
* @return the number of internal nodes from a root node
*/
public static int getInternalNodeCount(Node root) {
if(root.isLeaf()) {
return 0;
}
int count = 0;
for(int i = 0 ; i < root.getChildCount() ; i++) {
count+=getInternalNodeCount(root.getChild(i));
}
return count+1;
}
/**
* Converts lengths to heights, but maintains tip heights.
*/
public static void lengths2HeightsKeepTips(Node node, boolean useMax) {
if (!node.isLeaf()) {
for (int i = 0; i < node.getChildCount(); i++) {
lengths2HeightsKeepTips(node.getChild(i), useMax);
}
double totalHL = 0.0;
double maxHL = 0.0;
double hl = 0.0;
double maxH = 0.0;
double h = 0.0;
for (int i = 0; i < node.getChildCount(); i++) {
h = node.getChild(i).getNodeHeight();
hl = node.getChild(i).getBranchLength() + h;
if (hl > maxHL) maxHL = hl;
if (h > maxH) maxH = h;
totalHL += hl;
}
if (useMax) {
hl = maxHL; // set parent height to maximum parent height implied by children
} else {
hl = totalHL / node.getChildCount(); // get mean parent height
if (hl < maxH) hl = maxHL; // if mean parent height is not greater than all children height, fall back on max parent height.
}
node.setNodeHeight(hl); // set new parent height
// change lengths in children to reflect changes.
for (int i = 0; i < node.getChildCount(); i++) {
h = node.getChild(i).getNodeHeight();
node.getChild(i).setBranchLength(hl - h);
}
}
}
/**
* sets this nodes height value to newHeight and all children's
* height values based on length of branches.
*/
private static void lengths2Heights(Node node, double newHeight) {
if (!node.isRoot()) {
newHeight -= node.getBranchLength();
node.setNodeHeight(newHeight);
} else {
node.setNodeHeight(newHeight);
}
for (int i = 0; i < node.getChildCount(); i++) {
lengths2Heights(node.getChild(i), newHeight);
}
}
/**
* Exchange field info between two nodes. Specifically
* identifiers, branch lengths, node heights and branch length
* SEs.
*/
public static void exchangeInfo(Node node1, Node node2) {
Taxon swaps;
double swapd;
swaps = node1.getIdentifier();
node1.setIdentifier(node2.getIdentifier());
node2.setIdentifier(swaps);
swapd = node1.getBranchLength();
node1.setBranchLength(node2.getBranchLength());
node2.setBranchLength(swapd);
swapd = node1.getNodeHeight();
node1.setNodeHeight(node2.getNodeHeight());
node2.setNodeHeight(swapd);
swapd = node1.getBranchLengthSE();
node1.setBranchLengthSE(node2.getBranchLengthSE());
node2.setBranchLengthSE(swapd);
}
/**
* determines branch lengths of this and all descendent nodes
* from heights
*/
public static void heights2Lengths(Node node) {
heights2Lengths(node, true); //respect minimum
}
/**
* determines branch lengths of this and all descendent nodes
* from heights
*/
public static void heights2Lengths(Node node, boolean respectMinimum) {
for (int i = 0; i < node.getChildCount(); i++) {
heights2Lengths(node.getChild(i));
}
if (node.isRoot()) {
node.setBranchLength(0.0);
}
else {
node.setBranchLength(node.getParent().getNodeHeight() - node.getNodeHeight());
if (respectMinimum && (node.getBranchLength() < BranchLimits.MINARC))
{
node.setBranchLength(BranchLimits.MINARC);
}
}
}
/**
* determines branch lengths of this node and its immediate descendent nodes
* from heights.
*/
public static void localHeights2Lengths(Node node, boolean respectMinimum) {
for (int i = 0; i < node.getChildCount(); i++) {
Node child = node.getChild(i);
child.setBranchLength(node.getNodeHeight() - child.getNodeHeight());
}
if (node.isRoot()) {
node.setBranchLength(0.0);
}
else {
node.setBranchLength(node.getParent().getNodeHeight() - node.getNodeHeight());
if (respectMinimum && (node.getBranchLength() < BranchLimits.MINARC))
{
node.setBranchLength(BranchLimits.MINARC);
}
}
}
/**
* Finds the largest child (in terms of node height).
*/
public static double findLargestChild(Node node) {
// find child with largest height
double max = node.getChild(0).getNodeHeight();
for (int j = 1; j < node.getChildCount(); j++){
double h = node.getChild(j).getNodeHeight();
if (h > max)
{
max = h;
}
}
return max;
}
/**
* remove child
*
* @param node child node to be removed
*/
public static void removeChild(Node parent, Node child)
{
int rm = -1;
for (int i = 0; i < parent.getChildCount(); i++)
{
if (child == parent.getChild(i))
{
rm = i;
break;
}
}
parent.removeChild(rm);
}
/**
* remove internal branch (collapse node with its parent)
*
* @param node node associated with internal branch
*/
public static void removeBranch(Node node)
{
if (node.isRoot() || node.isLeaf())
{
throw new IllegalArgumentException("INTERNAL NODE REQUIRED (NOT ROOT)");
}
Node parent = node.getParent();
// add childs of node to parent
// (node still contains the link to childs
// to allow later restoration)
int numChilds = node.getChildCount();
for (int i = 0; i < numChilds; i++)
{
parent.addChild(node.getChild(i));
}
// remove node from parent
// (link to parent is restored and the
// position is stored)
int rm = -1;
for (int i = 0; i < parent.getChildCount(); i++)
{
if (node == parent.getChild(i))
{
rm = i;
break;
}
}
parent.removeChild(rm);
node.setParent(parent);
node.setNumber(rm);
}
/**
* restore internal branch
*
* @param node node associated with internal branch
*/
public static void restoreBranch(Node node)
{
if (node.isRoot() || node.isLeaf())
{
throw new IllegalArgumentException("INTERNAL NODE REQUIRED (NOT ROOT)");
}
Node parent = node.getParent();
// remove childs of node from parent and make node their parent
int numChilds = node.getChildCount();
for (int i = 0; i < numChilds; i++)
{
Node c = node.getChild(i);
removeChild(parent, c);
c.setParent(node);
}
// insert node into parent
parent.insertChild(node, node.getNumber());
}
/**
* join two childs, introducing a new node/branch in the tree
* that replaces the first child
*
* @param n1 number of first child
* @param n2 number of second child
*/
public static void joinChilds(Node node, int n1, int n2) {
if (n1 == n2) {
throw new IllegalArgumentException("CHILDREN MUST BE DIFFERENT");
}
int c1, c2;
if (n2 < n1)
{
c1 = n2;
c2 = n1;
}
else
{
c1 = n1;
c2 = n2;
}
Node newNode = NodeFactory.createNode();
Node child1 = node.getChild(c1);
Node child2 = node.getChild(c2);
node.setChild(c1, newNode);
newNode.setParent(node);
node.removeChild(c2); // now parent of child2 = null
newNode.addChild(child1);
newNode.addChild(child2);
}
/**
* determine preorder successor of this node
*
* @return next node
*/
public static Node preorderSuccessor(Node node) {
Node next = null;
if (node.isLeaf()) {
Node cn = node, ln = null; // Current and last node
// Go up
do
{
if (cn.isRoot())
{
next = cn;
break;
}
ln = cn;
cn = cn.getParent();
}
while (cn.getChild(cn.getChildCount()-1) == ln);
// Determine next node
if (next == null)
{
// Go down one node
for (int i = 0; i < cn.getChildCount()-1; i++)
{
if (cn.getChild(i) == ln)
{
next = cn.getChild(i+1);
break;
}
}
}
}
else
{
next = node.getChild(0);
}
return next;
}
/**
* determine postorder successor of a node
*
* @return next node
*/
public static Node postorderSuccessor(Node node) {
Node cn = null;
Node parent = node.getParent();
if (node.isRoot()){
cn = node;
} else{
// Go up one node
if (parent.getChild(parent.getChildCount()-1) == node) {
return parent;
}
// Go down one node
for (int i = 0; i < parent.getChildCount()-1; i++) {
if (parent.getChild(i) == node) {
cn = parent.getChild(i+1);
break;
}
}
}
// Go down until leaf
while (cn.getChildCount() > 0)
{
cn = cn.getChild(0);
}
return cn;
}
/**
* prints node in New Hamshire format.
*/
public static void printNH(PrintWriter out, Node node,
boolean printLengths, boolean printInternalLabels) throws IOException{
printNH(out, node, printLengths, printInternalLabels, 0, true);
}
public static int printNH(PrintWriter out, Node node,
boolean printLengths, boolean printInternalLabels, int column, boolean breakLines) throws IOException{
if (breakLines) column = breakLine(out, column);
if (!node.isLeaf())
{
out.print("(");
column++;
for (int i = 0; i < node.getChildCount(); i++)
{
if (i != 0)
{
out.print(",");
column++;
}
column = printNH(out, node.getChild(i), printLengths, printInternalLabels, column, breakLines);
}
out.print(")");
column++;
}
if (!node.isRoot())
{
if (node.isLeaf() || printInternalLabels)
{
if (breakLines) column = breakLine(out, column);
String id = node.getIdentifier().toString();
out.print(id);
column += id.length();
}
if (printLengths)
{
out.print(":");
column++;
if (breakLines) column = breakLine(out, column);
column += FormattedOutput.getInstance().displayDecimal(out, node.getBranchLength(), 7);
}
}
return column;
}
private static int breakLine(PrintWriter out, int column)
{
if (column > 70)
{
out.println();
column = 0;
}
return column;
}
/**
* Returns the first nodes in this tree that has the
* required identifiers.
* @return null if none of the identifiers names match nodes in tree, else return array which may have
* null "blanks" for corresponding identifiers that do not match any node in the tree
*/
public static final Node[] findByIdentifier(Node node, String[] identifierNames) {
Node[] nodes = new Node[identifierNames.length];
boolean foundSomething = false;
for(int i = 0 ; i < nodes.length ; i++) {
nodes[i] = findByIdentifier(node,identifierNames[i]);
foundSomething = foundSomething||(nodes[i]!=null);
}
if(!foundSomething) {
return null;
}
return nodes;
}
/**
* Returns the first nodes in this tree that has the
* required identifiers.
*/
public static final Node[] findByIdentifier(Node node, Taxon[] identifiers) {
Node[] nodes = new Node[identifiers.length];
for(int i = 0 ; i < nodes.length ; i++) {
nodes[i] = findByIdentifier(node,identifiers[i]);
}
return nodes;
}
/**
* Returns the first node in this tree that has the
* required identifier.
*/
public static final Node findByIdentifier(Node node, Taxon identifier) {
return findByIdentifier(node,identifier.getName());
}
/**
* Returns the first node in this tree that has the
* required identifier.
*/
public static final Node findByIdentifier(Node node, String identifierName) {
myLogger.debug("node identifier = " + node.getIdentifier());
myLogger.debug("target identifier name = " + identifierName);
if (node.getIdentifier().getName().equals(identifierName)) {
return node;
} else {
Node pos = null;
for (int i = 0; i < node.getChildCount(); i++) {
pos = findByIdentifier(node.getChild(i), identifierName);
if (pos != null) return pos;
}
//if (pos == null && !node.isRoot()) {
// pos = findByIdentifier(node.getParent(), identifier);
//}
if (pos != null) return pos;
return null;
}
}
/**
* determine distance to root
*
* @return distance to root
*/
public static double getDistanceToRoot(Node node)
{
if (node.isRoot())
{
return 0.0;
}
else
{
return node.getBranchLength() + getDistanceToRoot(node.getParent());
}
}
/**
* Return the number of terminal leaves below this node or 1 if this is
* a terminal leaf.
*/
public static int getLeafCount(Node node) {
int count = 0;
if (!node.isLeaf()) {
for (int i = 0; i < node.getChildCount(); i++) {
count += getLeafCount(node.getChild(i));
}
} else {
count = 1;
}
return count;
}
/**
* For two nodes in the tree true if the first node is the ancestor of the second
*
* @param possibleAncestor the node that may be the ancestor of the other node
* @param node the node that may have the other node as it's ancestor
*/
public static boolean isAncestor(Node possibleAncestor, Node node) {
if(node==possibleAncestor) {
return true;
}
while(!node.isRoot()){
node = node.getParent();
if(node==possibleAncestor) {
return true;
}
}
return false;
}
/**
* For a set of nodes in the tree returns the common ancestor closest to all nodes (most recent common ancestor)
*
* @param nodes the nodes to check, is okay if array elements are null!
* @returns null if a at least one node is disjoint from the others nodes disjoint
*/
public static Node getFirstCommonAncestor(Node[] nodes) {
Node currentCA = nodes[0];
for(int i = 1; i < nodes.length ;i++) {
if(currentCA!=null&&nodes[i]!=null) {
currentCA = getFirstCommonAncestor(currentCA,nodes[i]);
if(currentCA==null) {
return null;
}
}
}
return currentCA;
}
/**
* For two nodes in the tree returns the common ancestor closest to both nodes (most recent common ancestor)
*
* @param nodeOne
* @param nodeTwo
* @returns null if two nodes disjoint (from different trees). May also return either nodeOne or nodeTwo if one node is an ancestor of the other
*/
public static Node getFirstCommonAncestor(Node nodeOne, Node nodeTwo) {
if(isAncestor(nodeTwo, nodeOne)) {
return nodeTwo;
}
if(isAncestor(nodeOne, nodeTwo)) {
return nodeOne;
}
while(!nodeTwo.isRoot()) {
nodeTwo = nodeTwo.getParent();
if(isAncestor(nodeTwo, nodeOne)) {
return nodeTwo;
}
}
return null;
}
/** returns number of branches centered around an internal node in an unrooted tree */
public static final int getUnrootedBranchCount(Node center) {
if (center.isRoot()) {
return center.getChildCount();
}
else {
return center.getChildCount()+1;
}
}
/**
* If the given node or the sub tree defined by that node have negative branch lengths, they'll have
* zeron branch lengths after a call to this function!
*/
public static final void convertNegativeBranchLengthsToZeroLength(Node node) {
convertNegativeBranchLengthsToZeroLengthImpl(node);
lengths2Heights(node);
}
private static final void convertNegativeBranchLengthsToZeroLengthImpl(Node node) {
if(node.getBranchLength()<0) {
node.setBranchLength(0);
}
for(int i = 0 ; i < node.getChildCount() ; i++) {
convertNegativeBranchLengthsToZeroLengthImpl(node.getChild(i));
}
}
}