def testTreeSampleSortedCounts(self): """ The treeSample method returns a list of tuples, the second element of which is a count. The counts must be sorted from highest to lowest. """ distance = [ [0, 1, 1, 1, 1], [1, 0, 1, 1, 1], [1, 1, 0, 1, 1], [1, 1, 1, 0, 1], [1, 1, 1, 1, 0], ] labels = ['a', 'b', 'c', 'd', 'e'] njtree = NJTree.fromDistanceMatrix(labels, distance) # This test is not 100% reliable because there is a tiny chance the # treeSample method will repeatedly generate the same tree, even # though we make 50 trees and pass a high (0.3) standard deviation. # It is also possible that the counts come back sorted just by # chance even if the treeSample method does not sort them (in which # case the test will pass even though the treeSample code is wrong). # # To make these errors even more unlikely, I have put in an assert # on the number of trees that come back and I do the test multiple # times. If the assert fails it doesn't mean that treeSample is # broken, but it's highly likely that it is! It's also extremely # unlikely that the counts could be sorted correctly by chance on # every run. So if the test passes it doesn't mean that treeSample # isn't broken, but it's highly unlikely that it is! Phew. for _ in range(10): counts = [count for (tree, count) in njtree.treeSample(50, 0.3)] self.assertTrue(len(counts) > 2) self.assertEqual(sorted(counts, reverse=True), counts)
def testWithNoSupportAllNodesHaveSupportOfZero(self): """ If three sequences with no features are used to create an NJTree the child nodes in the resulting tree must all have support of 0.0. """ distance = [[0, 1, 1], [1, 0, 1], [1, 1, 0]] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) self.assertEqual( [0.0, 0.0, 0.0], [njtree.supportForNode(child) for child in njtree.tree.children])
def testTreeSampleZero(self): """ When treeSample is called with a zero argument, it should return an empty list. """ distance = [ [0, 1, 1], [1, 0, 1], [1, 1, 0] ] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) self.assertEqual([], njtree.treeSample(0))
def testGenerateTreesZero(self): """ When generateTrees is called with a zero argument, it should return an empty list. """ distance = [ [0, 1, 1], [1, 0, 1], [1, 1, 0] ] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) self.assertEqual([], list(njtree.generateTrees(0)))
def testOnlyOneConsensusTreeWithZeroIterations(self): """ When consensusTrees is passed an iteration count of zero, only one consensus tree must be returned. """ distance = [ [0, 1, 1], [1, 0, 1], [1, 1, 0] ] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) consensusTrees = njtree.consensusTrees(0) self.assertEqual(1, len(consensusTrees))
def testAddSupportIncrementsSupportIterations(self): """ When support has been added to a tree, its supportIterations attribute must be incremented correctly. """ distance = [ [0, 1, 1], [1, 0, 1], [1, 1, 0] ] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) njtree.addSupport(2) self.assertEqual(2, njtree.supportIterations)
def testSupportForNodeIsOneAtRoot(self): """ When support has been added to a tree, the root node must have support of 1.0. This is because all trees will have all tips under their root, regardless of their topologies. """ distance = [ [0.0, 0.5, 0.4], [0.5, 0.0, 0.1], [0.4, 0.1, 0.0], ] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) njtree.addSupport(10) self.assertEqual(1.0, njtree.supportForNode(njtree.tree))
def testTreeSampleReturnType(self): """ The treeSample method must return a list of tuples, each containing an NJTree and a count. """ distance = [ [0, 1, 1], [1, 0, 1], [1, 1, 0] ] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) result = njtree.treeSample(10) for tree, count in result: self.assertTrue(isinstance(tree, NJTree)) self.assertTrue(isinstance(count, int))
def testGenerateTreesMultiple(self): """ When generateTrees is called with a non-zero argument, it should return a list with the expected number of items, which must all be instances of NJTree. """ distance = [ [0, 1, 1], [1, 0, 1], [1, 1, 0] ] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) result = list(njtree.generateTrees(5)) self.assertEqual(5, len(result)) self. assertTrue(all(isinstance(t, NJTree) for t in result))
def testConsensusTreeWithZeroIterationsHasSupportOneForAllChildren(self): """ When consensusTrees is passed an iteration count of zero, all children in the consensus tree must have support of zero. """ distance = [ [0, 1, 1], [1, 0, 1], [1, 1, 0] ] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) consensusTrees = njtree.consensusTrees(0) self.assertEqual([0, 0, 0], [njtree.supportForNode(child) for child in consensusTrees[0].tree.children])
def testNewickWithNoSuppportAdded(self): """ If no support has been added to a tree, newick must return the expected string (with no support values). """ distance = [ [0, 1, 1], [1, 0, 1], [1, 1, 0] ] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) # The order in the Newick string seems deterministic, and according # to the skbio docs this is the case. self.assertEqual('(y:0.500000,x:0.500000,z:0.500000);\n', njtree.newick())
def testSupportForNodeWhenNoSuppportAdded(self): """ If no support has been added to a tree, supportForNode must return zero for all nodes. """ distance = [ [0, 1, 1], [1, 0, 1], [1, 1, 0] ] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) self.assertEqual(0, njtree.supportForNode(njtree.tree)) self.assertEqual([0, 0, 0], [njtree.supportForNode(child) for child in njtree.tree.children])
def testFromDistanceMatrixThreeByThree(self): """ If an NJTree instance is built from a 3x3 distance matrix, the instance must 1) save the distance matrix, 2) save the labels, and 3) produce a simple tree with three children, and 4) have no sequences. """ distance = [[0, 1, 1], [1, 0, 1], [1, 1, 0]] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) self.assertIs(distance, njtree.distance) self.assertIs(labels, njtree.labels) self.assertEqual(['x:0.5;\n', 'y:0.5;\n', 'z:0.5;\n'], sorted(str(child) for child in njtree.tree.children)) self.assertIs(None, njtree.sequences)
def testNewickWithNoSupportIncludedWhenSupportHasBeenAdded(self): """ If support has been added to a tree, but includeSupport is passed to newick() as False, the Newick string must not contain any square brackets (Newick comment fields in which support is shown). """ distance = [ [0, 1, 1], [1, 0, 1], [1, 1, 0] ] labels = ['x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) njtree.addSupport(2) newick = njtree.newick(includeSupport=False) self.assertEqual(-1, newick.find('[')) self.assertEqual(-1, newick.find(']'))
def testNewickWithSupportAdded(self): """ If support has been added to a tree, the Newick string must contain square brackets (Newick comment fields in which support is shown). """ distance = [ [0, 5, 5, 5], [5, 0, 5, 1], [5, 5, 0, 5], [5, 1, 5, 0], ] labels = ['w', 'x', 'y', 'z'] njtree = NJTree.fromDistanceMatrix(labels, distance) njtree.addSupport(2) newick = njtree.newick(includeSupport=True) self.assertNotEqual(-1, newick.find('[')) self.assertNotEqual(-1, newick.find(']'))