def _setup_linked_list(self, kwargs_list): last_node = None for idx, kwargs in enumerate(kwargs_list): new_node = TreeNode(**kwargs) if last_node is not None: new_node.append(last_node) last_node = new_node return last_node
def test_missing_tip_name(self): """DndParser should produce the correct tree when missing a name""" obs = TreeNode.from_newick(missing_tip_name) exp = TreeNode() exp.append(TreeNode()) exp.append(TreeNode()) exp.children[0].append(TreeNode(name='a')) exp.children[0].append(TreeNode(name='b')) exp.children[1].append(TreeNode(name='c')) exp.children[1].append(TreeNode()) self.assertEqual(str(obs), str(exp))
def test_nonames(self): """DndParser should produce the correct tree when there are no names""" obs = TreeNode.from_newick(no_names) exp = TreeNode() exp.append(TreeNode()) exp.append(TreeNode()) exp.children[0].append(TreeNode()) exp.children[0].append(TreeNode()) exp.children[1].append(TreeNode()) exp.children[1].append(TreeNode()) self.assertEqual(str(obs), str(exp))
def test_gops(self): """Basic TreeNode operations should work as expected""" p = TreeNode() self.assertEqual(str(p), ';') p.name = 'abc' self.assertEqual(str(p), 'abc;') p.length = 3 self.assertEqual(str(p), 'abc:3;') # don't suppress branch from root q = TreeNode() p.append(q) self.assertEqual(str(p), '()abc:3;') r = TreeNode() q.append(r) self.assertEqual(str(p), '(())abc:3;') r.name = 'xyz' self.assertEqual(str(p), '((xyz))abc:3;') q.length = 2 self.assertEqual(str(p), '((xyz):2)abc:3;')
def test_gops(self): """Basic TreeNode operations should work as expected""" p = TreeNode() self.assertEqual(str(p), ';\n') p.name = 'abc' self.assertEqual(str(p), 'abc;\n') p.length = 3 self.assertEqual(str(p), 'abc:3;\n') # don't suppress branch from root q = TreeNode() p.append(q) self.assertEqual(str(p), '()abc:3;\n') r = TreeNode() q.append(r) self.assertEqual(str(p), '(())abc:3;\n') r.name = 'xyz' self.assertEqual(str(p), '((xyz))abc:3;\n') q.length = 2 self.assertEqual(str(p), '((xyz):2)abc:3;\n')
def test_minimal(self): """DndParser should produce the correct minimal tree""" obs = TreeNode.from_newick(minimal) exp = TreeNode() exp.append(TreeNode()) self.assertEqual(str(obs), str(exp))
def walk_copy(node, src): """Directionally and recursively copy a tree node and its neighbors. Parameters ---------- node : skbio.TreeNode node and its neighbors to be copied src : skbio.TreeNode an upstream node determining the direction of walking (src -> node) Returns ------- skbio.TreeNode copied node and its neighbors Notes ----- After manipulation, `src` will become the parent of `node`, and all other neighbors of `node` will become children of it. Unlike scikit-bio's `unrooted_copy` function, this function has special treatment at root: For an unrooted tree, its "root" will be retained as a regular node; for a rooted tree, its root will be deleted, and all basal nodes will become immediate children of the basal node where the source is located. The function determines whether a tree is rooted or unrooted in such way: rooted: root has two children; unrooted: root has one or more than two children. Logic (pseudocode): if node is root: if tree is rooted: raise error else: if src in node.children: append node.other_child else: raise error elif node is basal (i.e., child of root): if tree is rooted: if src in node.siblings: append node.children elif src in node.children: append node.sibling and node.other_children else: raise error else: if src is node.parent (i.e., root): append node.children elif src in node.children: append node.parent and node.other_children else: raise error else: (i.e., node is derived) if src is node.parent: append node.children elif src in node.children: append node.parent and node.other_children else: raise error See Also -------- root_above Raises ------ ValueError if the input node is already a root or if the input node and input source node are not neighbors """ parent = node.parent children = node.children # position of node pos = ('root' if node.is_root() else 'basal' if parent.is_root() else 'derived') # whether tree is rooted root = node if pos == 'root' else node.parent if pos == 'basal' else None rooted = None if pos == 'derived' else ( True if len(root.children) == 2 else False) if rooted: if pos == 'root': raise ValueError('Cannot walk from root of a rooted tree.') elif pos == 'basal': sibling = [x for x in node.siblings()][0] # direction of walking move = (( 'bottom' if src is sibling else 'top' if src in children else 'n/a') if rooted and pos == 'basal' else ('down' if src is parent else 'up' if src in children else 'n/a')) if move == 'n/a': raise ValueError('Source and node are not neighbors.') # create a new node res = TreeNode(node.name) # determine length of the new node res.length = (node.length if move == 'down' else src.length + node.length if move == 'bottom' else src.length) # up or top # determine support of the new node res.support = (node.support if move in ('down', 'bottom') else src.support) # append children except for src (if applies) res.extend([walk_copy(c, node) for c in children if c is not src]) # append parent if walking up (except at root) if move == 'up' and pos != 'root': res.append(walk_copy(parent, node)) # append sibling if walking from one basal node to another if move == 'top': res.append(walk_copy(sibling, node)) return res