// clone this node, make its supertree a child, and clone all children // other than oldNode, leaving this node as a child of nodeToAddTo static void tree_cloneFlippedTree(stTree *node, stTree *oldNode, stTree *nodeToAddTo, double branchLength) { if(stTree_getParent(node) != NULL) { // This node isn't the root stTree *clonedNode = stTree_cloneNode(node); stTree_setParent(clonedNode, nodeToAddTo); stTree_setBranchLength(clonedNode, branchLength); // Clone its children (other than oldNode) and their subtrees for(int64_t i = 0; i < stTree_getChildNumber(node); i++) { stTree *child = stTree_getChild(node, i); if(child != oldNode) { stTree *clonedChild = stTree_clone(child); stTree_setParent(clonedChild, clonedNode); } } // Recurse on the parent of this node. tree_cloneFlippedTree(stTree_getParent(node), node, clonedNode, stTree_getBranchLength(node)); } else { // We have to treat the root specially, because we're going to // eliminate it. Just add all the other children of the root // as children of nodeToAddTo. for(int64_t i = 0; i < stTree_getChildNumber(node); i++) { stTree *child = stTree_getChild(node, i); if(child != oldNode) { stTree *clonedChild = stTree_clone(child); stTree_setParent(clonedChild, nodeToAddTo); stTree_setBranchLength(clonedChild, stTree_getBranchLength(child) + branchLength); } } } }
void stTree_setParent(stTree *tree, stTree *parent) { if(stTree_getParent(tree) != NULL) { stList_removeItem(stTree_getParent(tree)->nodes, tree); } tree->parent = parent; if(parent != NULL) { stList_append(parent->nodes, tree); } }
/* Join at the specified components, returning new root */ static stTree *joinAtNodes(stTree *root1, stTree *node1, stTree *root2, stTree *node2, struct malnCompCompMap *srcDestCompMap) { if ((stTree_getParent(node1) == NULL) && (stTree_getParent(node2) == NULL)) { assert((root1 == node1) && (root2 == node2)); return joinTrees(root1, node1, node2, srcDestCompMap); } else if (stTree_getParent(node1) == NULL) { assert(root1 == node1); return joinTrees(root2, node2, node1, srcDestCompMap); } else if (stTree_getParent(node2) == NULL) { assert(root2 == node2); return joinTrees(root1, node1, node2, srcDestCompMap); } else { errAbort("join nodes don't obey rules: node1: %s node2: %s", stTree_getLabel(node1), stTree_getLabel(node2)); return NULL; } }
/* get location type in tree */ enum mafTreeLoc mafTreeNodeCompLink_getLoc(struct mafTreeNodeCompLink *ncLink) { if (stTree_getParent(ncLink->node) == NULL) { return mafTreeLocRoot; } else if (stTree_getChildNumber(ncLink->node) == 0) { return mafTreeLocLeaf; } else { return mafTreeLocInternal; } }
/* Clone tree1 and then attach the children of tree2 at the copy of the * specified attachment point. */ static stTree *joinTrees(stTree *srcRoot1, stTree *srcAttach1, stTree *srcRoot2, struct malnCompCompMap *srcDestCompMap) { assertJoinCompatible(srcAttach1, srcRoot2); assert(stTree_getParent(srcRoot2) == NULL); stTree *joinedRoot = cloneTree(srcRoot1, NULL, srcDestCompMap); struct mafTreeNodeCompLink *srcAttach1NcLink = getNodeCompLink(srcAttach1); stTree *joinLeaf = searchByComp(joinedRoot, malnCompCompMap_get(srcDestCompMap, srcAttach1NcLink->comp)); cloneChildren(srcRoot2, joinLeaf, srcDestCompMap); return joinedRoot; }
stTree *stTree_getMRCA(stTree *node1, stTree *node2) { // Find all of node 1's parents (inclusive of node 1) stSet *parents = stSet_construct(); stTree *curNode = node1; do { stSet_insert(parents, curNode); } while ((curNode = stTree_getParent(curNode)) != NULL); // Find the first parent of node 2 that is a parent of node 1 stTree *ret = NULL; curNode = node2; do { if (stSet_search(parents, curNode) != NULL) { ret = curNode; break; } } while ((curNode = stTree_getParent(curNode)) != NULL); stSet_destruct(parents); return ret; }
// Return a new tree rooted a given distance above the given node. stTree *stTree_reRoot(stTree *node, double distanceAbove) { if(stTree_getParent(node) == NULL) { // This node is already the root. stTree *newRoot = stTree_clone(node); stTree_clearClientData(newRoot, true); return newRoot; } assert(stTree_getBranchLength(node) >= distanceAbove); stTree *newRoot = stTree_construct(); // This node and its children (if any) are fine already. stTree *clonedNode = stTree_clone(node); stTree_setParent(clonedNode, newRoot); stTree_setBranchLength(clonedNode, distanceAbove); tree_cloneFlippedTree(stTree_getParent(node), node, newRoot, stTree_getBranchLength(node) - distanceAbove); // Having the same client data can be a problem stTree_clearClientData(newRoot, true); return newRoot; }
/* Remove a node from the tree and free. Can't delete the root node. */ void mafTree_deleteNode(mafTree *mTree, struct mafTreeNodeCompLink *ncLink) { stTree *node = ncLink->node; stTree *parent = stTree_getParent(node); if (parent == NULL) { errAbort("BUG: can't remove tree root node"); } stTree_setParent(node, NULL); // setParent changes node children while (stTree_getChildNumber(node) > 0) { stTree_setParent(stTree_getChild(node, 0), parent); } freeMafTreeNodeCompLinks(node); stTree_destruct(node); setCheckTreeOrder(mTree, false); }