class TestNodeDescendantsFunctionality(unittest.TestCase): def setUp(self): self.test_obj = Node("A", "1.0") self.test_descendant = Node("D", "2.0") self.lengths = ["2.0", "3.0", "4.0"] @data(["D1.1", "D1.2", "D1.3"], ["D", "", ""], ["", "", ""]) def test_node_representation_with_deeper_descendants(self, test_data): """ :param test_data: names of descendants Procedure: 1. Make simple tree with one descendant having two another descendants inside 2. Verify if it's newick representation is correct in comparision to parsed "proper_result" :return: """ single_nodes_reprs = [ "{0}:{1}".format(name, length) for name, length in zip(test_data, self.lengths) ] proper_result = "(({1},{2}){0})A:1.0".format(*single_nodes_reprs) d1, d2, d3 = [ Node(name, length) for name, length in zip(test_data, self.lengths) ] d1.add_descendant(d2) d1.add_descendant(d3) self.test_obj.add_descendant(d1) self.assertEqual(proper_result, self.test_obj.newick) def test_node_as_descendants_list(self): self.test_obj.add_descendant(self.test_descendant) self.assertListEqual([self.test_descendant], self.test_obj.descendants)
class TestNodeDescendantsFunctionality(unittest.TestCase): def setUp(self): self.test_obj = Node("A", "1.0") self.test_descendant = Node("D", "2.0") self.lengths = ["2.0", "3.0", "4.0"] @data(["D1.1", "D1.2", "D1.3"], ["D", "", ""], ["", "", ""]) def test_node_representation_with_deeper_descendants(self, test_data): """ :param test_data: names of descendants Procedure: 1. Make simple tree with one descendant having two another descendants inside 2. Verify if it's newick representation is correct in comparision to parsed "proper_result" :return: """ single_nodes_reprs = [ "{0}:{1}".format(name, length) for name, length in zip(test_data, self.lengths)] proper_result = "(({1},{2}){0})A:1.0".format(*single_nodes_reprs) d1, d2, d3 = [Node(name, length) for name, length in zip(test_data, self.lengths)] d1.add_descendant(d2) d1.add_descendant(d3) self.test_obj.add_descendant(d1) self.assertEqual(proper_result, self.test_obj.newick) def test_node_as_descendants_list(self): self.test_obj.add_descendant(self.test_descendant) self.assertListEqual([self.test_descendant], self.test_obj.descendants)
def newick_node(self, nodes=None, template=None): template = template or self._newick_default_template n = Node(name=template.format(l=self), length='1') # noqa: E741 children = self.children if nodes is None else self.children_from_nodemap( nodes) for nn in sorted(children, key=lambda nn: nn.name): n.add_descendant(nn.newick_node(nodes=nodes, template=template)) return n
def newick_node(self, nodes=None): label = '{0} [{1}]'.format( self.name.replace(',', '/').replace('(', '{').replace(')', '}'), self.id) if self.iso: label += '[%s]' % self.iso if self.level == Level.language: label += '-l-' n = Node(name="'{0}'".format(label), length='1') children = self.children if nodes is None else self.children_from_nodemap( nodes) for nn in sorted(children, key=lambda nn: nn.name): n.add_descendant(nn.newick_node(nodes=nodes)) return n
def newick_node(self, nodes=None, template=None, maxlevel=None, level=0) -> Node: """ Return a `newick.Node` representing the subtree of the Glottolog classification starting at the languoid. :param template: Python format string accepting the `Languoid` instance as single \ variable named `l`, used to format node labels. """ template = template or self._newick_default_template n = Node(name=template.format(l=self), length='1') # noqa: E741 children = self.children if nodes is None else self.children_from_nodemap(nodes) for nn in sorted(children, key=lambda nn: nn.name): if maxlevel: if (isinstance(maxlevel, config.LanguoidLevel) and nn.level > maxlevel) or \ (not isinstance(maxlevel, config.LanguoidLevel) and level > maxlevel): continue n.add_descendant( nn.newick_node(nodes=nodes, template=template, maxlevel=maxlevel, level=level + 1)) return n
def _add_leaf(node: Node, target: str, leaf: str): if PhyTree._is_group(node.name): if node.name == target: node.add_descendant(Node(f"{{{leaf}}}")) else: if PhyTree._is_group(target): expected_leaves = set(PhyTree._get_group_leaves(target)) else: expected_leaves = {target} for child in node.descendants: if PhyTree._is_group(child.name): child_leaves = set( PhyTree._get_group_leaves(child.name)) if expected_leaves <= child_leaves: PhyTree._add_leaf(child, target, leaf) break elif PhyTree._is_leaf(child.name): if child.name in expected_leaves: PhyTree._add_leaf(child, target, leaf) else: raise ValueError(f"Couldn't find {target}") elif PhyTree._is_leaf(node.name): if node.name == target: if node.name != '{}': node.add_descendant(Node(node.name)) node.add_descendant(Node(f"{{{leaf}}}")) else: node.name = f"{{{leaf}}}" return else: raise ValueError(f"Unexpected leaf: {node.name}") else: raise ValueError(f"Couldn't recognize {leaf} as a leaf or a group") node.name = node.name.replace("}", f" {leaf}}}")
def clone_node(n): c = Node(name=n.name) for nn in n.descendants: c.add_descendant(clone_node(nn)) return c