def recon_root(self, gtree, newCopy=True, returnCost=False): """ Reroots the tree by minimizing the cost function. Rerooted tree must keep same node names as the original tree. Adapted from phylo.recon_root. """ # try all rerootings mincost = util.INF for gtree, edge in self._reroot_helper(gtree, newCopy=newCopy, returnEdge=True): cost = self.compute_cost(gtree) if cost < mincost: mincost = cost minroot = edge # root tree by minroot if edge != minroot: node1, node2 = minroot if node1.parent != node2: node1, node2 = node2, node1 assert node1.parent == node2 treelib.reroot(gtree, node1.name, newCopy=False, keepName=True) if returnCost: return gtree, mincost else: return gtree
def unroot(gtree, newCopy=True): """returns unrooted gtree (with internal root always at the same place)""" if newCopy: gtree = gtree.copy() treelib.unroot(gtree, newCopy=False) treelib.reroot(gtree, gtree.nodes[sorted(gtree.leaf_names())[0]].parent.name, onBranch=False, newCopy=False) return gtree
def _reroot_helper(self, gtree, newCopy=True, returnEdge=False): """ Yields rerooted trees. Adapted from phylo.recon_root. """ # make a consistent unrooted copy of gene tree if newCopy: gtree = gtree.copy() if len(gtree.leaves()) == 2: raise StopIteration oldroot = gtree.root.name treelib.unroot(gtree, newCopy=False) treelib.reroot(gtree, gtree.nodes[sorted(gtree.leaf_names())[0]].parent.name, onBranch=False, newCopy=False) # make rerooting order consistent using hash ordering phylo.hash_order_tree(gtree, self.gene2species) # get list of edges to root on edges = [] def walk(node): edges.append((node, node.parent)) if not node.is_leaf(): node.recurse(walk) edges.append((node, node.parent)) for child in gtree.root.children: walk(child) # try initial root treelib.reroot(gtree, edges[0][0].name, newCopy=False) gtree.rename(gtree.root.name, oldroot) if returnEdge: yield gtree, edges[0] else: yield gtree rootedge = sorted(edges[0]) # try rerooting on everything for edge in edges[1:]: if sorted(edge) == rootedge: continue rootedge = sorted(edge) node1, node2 = edge if node1.parent != node2: node1, node2 = node2, node1 assert node1.parent == node2, "%s %s" % (node1.name, node2.name) # new root and cost treelib.reroot(gtree, node1.name, newCopy=False, keepName=True) if returnEdge: yield gtree, edge else: yield gtree