def testRobinsonFoulds(self): """ The correct Robinson Foulds distance must be calculated. """ njtree1 = NJTree() njtree2 = NJTree() njtree1.tree = TreeNode.read(StringIO('((a,b),(c,d));')) njtree2.tree = TreeNode.read(StringIO('(((a,b),c),d);')) distance = njtree1.robinsonFoulds(njtree2) self.assertEqual(2.0, distance)
def testSetCanonicalizes(self): """ When putting NJTrees into sets, the hash function must canonicalize the trees. So, adding the same tree (modulo canonicalization) twice to a set must result in a set of size one. """ njtree1 = NJTree() njtree1.tree = TreeNode.read(StringIO('((a:1,b:2)c);')) njtree2 = NJTree() njtree2.tree = TreeNode.read(StringIO('((b:2,a:1)c);')) self.assertEqual(1, len({njtree1, njtree2}))
def testRobinsonFouldsProportionTrueReversed(self): """ The correct Robinson Foulds distance must be calculated with proportion=True, if the trees are passed in reverse order. """ njtree1 = NJTree() njtree2 = NJTree() njtree1.tree = TreeNode.read(StringIO('((a,b),(c,d));')) njtree2.tree = TreeNode.read(StringIO('(((a,b),c),d);')) distance = njtree2.robinsonFoulds(njtree1, proportion=True) self.assertEqual(0.5, distance)
def testDictCanonicalizes(self): """ When hashing NJTrees, the hash function must canonicalize the trees. So, adding the same tree (modulo canonicalization) twice to a dict must result in a dict of size one. """ njtree1 = NJTree() njtree1.tree = TreeNode.read(StringIO('((b:0.4,a:0.9):0.7);')) njtree2 = NJTree() njtree2.tree = TreeNode.read(StringIO('((a:0.9,b:0.4):0.7);')) self.assertEqual(1, len(dict.fromkeys([njtree1, njtree2])))
def testRobinsonFouldsCompareAgainstItself(self): """ If a tree is compared against itself, the Robinson Foulds distance must be 0.0. """ njtree1 = NJTree() njtree2 = NJTree() njtree1.tree = TreeNode.read(StringIO('((a,b),(c,d));')) njtree2.tree = TreeNode.read(StringIO('((a,b),(c,d));')) distance = njtree1.robinsonFoulds(njtree2) self.assertEqual(0.0, distance)
def testCountCladesEmptyTree(self): """ In a tree with no children, there are no clades. """ njtree = NJTree() njtree.tree = TreeNode() self.assertEqual(Counter(), njtree.countClades())
def testCanonicalizeByNumberOfTips(self): """ In forming a canonical tree, child nodes must be sorted by number of tips (assuming child lengths are all equal). """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode(children=[ TreeNode(), TreeNode(), TreeNode(), ]), TreeNode(children=[ TreeNode(), TreeNode(), TreeNode(), TreeNode(), TreeNode(), ]), TreeNode(children=[ TreeNode(), TreeNode(), ]), ]) self.assertEqual( [3, 5, 2], [len(child.children) for child in njtree.tree.children]) self.assertEqual( [2, 3, 5], [len(child.children) for child in njtree.canonicalize().tree.children])
def testCanonicalizeByNameAheadOfNamesOfDescendants(self): """ In forming a canonical tree, child nodes must be sorted by name in preference to the sorted names of all their descendants. """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode(name='b', children=[ TreeNode(name='e'), TreeNode(name='f'), TreeNode(name='g'), ]), TreeNode(name='c', children=[ TreeNode(name='h'), TreeNode(name='i'), TreeNode(name='j'), ]), TreeNode(name='a', children=[ TreeNode(name='k'), TreeNode(name='l'), TreeNode(name='m'), ]), ]) self.assertEqual( ['b', 'c', 'a'], [child.name for child in njtree.tree.children]) self.assertEqual( ['a', 'b', 'c'], [child.name for child in njtree.canonicalize().tree.children])
def testCanonicalizeByNumberOfTipsAheadOfName(self): """ In forming a canonical tree, child nodes must be sorted by number of tips in preference to name. """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode(name='a', children=[ TreeNode(), TreeNode(), TreeNode(), ]), TreeNode(name='b', children=[ TreeNode(), ]), TreeNode(name='c', children=[ TreeNode(), TreeNode(), ]), ]) self.assertEqual( ['a', 'b', 'c'], [child.name for child in njtree.tree.children]) self.assertEqual( ['b', 'c', 'a'], [child.name for child in njtree.canonicalize().tree.children])
def testCanonicalizeByTipSubset(self): """ In forming a canonical tree, child nodes must be sorted by the names of the set of tips they lead to, if all else is equal. """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode(children=[ TreeNode(name='d'), TreeNode(name='e'), TreeNode(name='f'), ]), TreeNode(children=[ TreeNode(name='g'), TreeNode(name='h'), TreeNode(name='i'), ]), TreeNode(children=[ TreeNode(name='a'), TreeNode(name='b'), TreeNode(name='c'), ]), ]) self.assertEqual( ['d', 'e', 'f', 'g', 'h', 'i', 'a', 'b', 'c'], [grandchild.name for child in njtree.tree.children for grandchild in child.children]) self.assertEqual( ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], [grandchild.name for child in njtree.canonicalize().tree.children for grandchild in child.children])
def testCountCladesOneChild(self): """ In a tree with one child, there is one clade. """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode(name='a'), ]) self.assertEqual( { frozenset(['a']): 1, }, njtree.countClades() )
def testRootByOneNodeName(self): """ Rooting by one node name must work. """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode(name='c'), TreeNode(name='d'), TreeNode(name='b'), TreeNode(name='a')]) self.assertEqual( ['c', 'd', 'b', 'a'], [child.name for child in njtree.root(['a']).tree.children])
def testRootByInexistentNodeNameMustRaiseError(self): """ Rooting by an inexistent node name must raise an exception. """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode(name='c'), TreeNode(name='d'), TreeNode(name='b'), TreeNode(name='a')]) error = 'Node f is not in self' six.assertRaisesRegex(self, MissingNodeError, error, njtree.root, ['f'])
def testCanonicalizeByNodeLength(self): """ In forming a canonical tree, child nodes must be sorted by length. """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode(length=13), TreeNode(length=11), TreeNode(length=18), TreeNode(length=14)]) self.assertEqual( [13, 11, 18, 14], [child.length for child in njtree.tree.children]) self.assertEqual( [11, 13, 14, 18], [child.length for child in njtree.canonicalize().tree.children])
def testRootByTwoTreeNodes(self): """ Rooting by two TreeNodes must work. """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode(name='c'), TreeNode(name='d'), TreeNode(name='b'), TreeNode(name='a')]) node1 = njtree.tree.find('a') node2 = njtree.tree.find('b') self.assertEqual( ['c', 'd', 'b', 'a'], [child.name for child in njtree.root([node1, node2]).tree.children])
def testCanonicalizeByNodeName(self): """ In forming a canonical tree, child nodes must be sorted by name if node lengths and number of tips are equal. """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode(name='c'), TreeNode(name='d'), TreeNode(name='b'), TreeNode(name='a')]) self.assertEqual( ['c', 'd', 'b', 'a'], [child.name for child in njtree.tree.children]) self.assertEqual( ['a', 'b', 'c', 'd'], [child.name for child in njtree.canonicalize().tree.children])
def testCountCladesTwoChildren(self): """ In a tree with two children, one of which has two children, there are two clades. """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode(children=[ TreeNode(name='a'), TreeNode(name='b'), ]), TreeNode(name='c'), ]) self.assertEqual( { frozenset(['a', 'b']): 1, frozenset(['a', 'b', 'c']): 1, }, njtree.countClades() )
def testCanonicalizeByLengthAheadOfNumberOfTips(self): """ In forming a canonical tree, child nodes must be sorted by length in preference to number of tips. """ njtree = NJTree() njtree.tree = TreeNode(children=[ TreeNode( length=13, children=[ TreeNode(), TreeNode(), TreeNode(), ], ), TreeNode( length=11, children=[ TreeNode(), TreeNode(), TreeNode(), TreeNode(), ], ), TreeNode( length=12, children=[ TreeNode(), TreeNode(), ], ), ]) self.assertEqual( [13, 11, 12], [child.length for child in njtree.tree.children]) self.assertEqual( [11, 12, 13], [child.length for child in njtree.canonicalize().tree.children])