Ejemplo n.º 1
0
    def test_collapse(self):
        names = np.array([
            'r', '2', '3', None, '4', None, '5', '6', None, None, None, '7',
            None, '8', '9', '10', None, '11', None, None, None, None
        ])
        lengths = np.array([
            0, 1, 2, 0, 3, 0, 4, 5, 0, 0, 0, 6, 0, 7, 8, 9, 0, 10, 0, 0, 0, 0
        ],
                           dtype=np.double)
        self.BP.set_names(names)
        self.BP.set_lengths(lengths)

        exp = np.array([1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0],
                       dtype=np.uint8)
        exp_n = [
            'r', '2', '3', None, '4', None, '6', None, None, '7', None, '9',
            '10', None, '11', None, None, None
        ]
        exp_l = [0, 1, 2, 0, 3, 0, 9, 0, 0, 6, 0, 15, 9, 0, 10, 0, 0, 0]

        obs = self.BP.collapse()

        npt.assert_equal(obs.B, exp)
        for i in range(len(obs.B)):
            self.assertEqual(obs.name(i), exp_n[i])
            self.assertEqual(obs.length(i), exp_l[i])

        bp = BP(np.array([1, 1, 1, 0, 0, 1, 0, 0], dtype=np.uint8))
        exp = np.array([1, 1, 0, 1, 0, 0])
        obs = bp.collapse().B

        npt.assert_equal(obs, exp)
Ejemplo n.º 2
0
    def test_collapse(self):
        names = np.array(['r', '2', '3', None, '4', None, '5', '6', None, None, None, '7', None, '8', '9', '10', None,
                          '11', None, None, None, None])
        lengths = np.array([0, 1, 2, 0, 3, 0, 4, 5, 0, 0, 0, 6, 0, 7, 8, 9, 0, 10, 0, 0, 0, 0], dtype=np.double)
        self.BP.set_names(names)
        self.BP.set_lengths(lengths)

        exp = np.array([1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0],
                       dtype=np.uint8)
        exp_n = ['r', '2', '3', None, '4', None, '6', None, None, '7', None, '9', '10', None, '11', None, None, None]
        exp_l = [0, 1, 2, 0, 3, 0, 9, 0, 0, 6, 0, 15, 9, 0, 10, 0, 0, 0]

        obs = self.BP.collapse()

        npt.assert_equal(obs.B, exp)
        for i in range(len(obs.B)):
            self.assertEqual(obs.name(i), exp_n[i])
            self.assertEqual(obs.length(i), exp_l[i])

        bp = BP(np.array([1, 1, 1, 0, 0, 1, 0, 0], dtype=np.uint8))
        exp = np.array([1, 1, 0, 1, 0, 0])
        obs = bp.collapse().B

        npt.assert_equal(obs, exp)
Ejemplo n.º 3
0
class BPTests(TestCase):
    def setUp(self):
        #                       0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21
        self.fig1_B = np.array(
            [1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0],
            dtype=np.uint8)
        self.BP = BP(self.fig1_B)

    def test_rmq(self):
        #       (  (  (  )  (  )  (  (  )  )   )   (   )   (   (   (   )   (   )   )   )   )
        #excess 1  2  3  2  3  2  3  4  3  2   1   2   1   2   3   4   3   4   3   2   1   0
        #i      0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21

        exp = [[
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21
        ],
               [
                   1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 10, 10, 10, 10, 10, 10,
                   10, 10, 10, 21
               ],
               [
                   2, 3, 3, 3, 3, 3, 3, 3, 10, 10, 10, 10, 10, 10, 10, 10, 10,
                   10, 10, 21
               ],
               [
                   3, 3, 3, 3, 3, 3, 3, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
                   10, 21
               ],
               [
                   4, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
                   10, 21
               ],
               [5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
               [6, 6, 6, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
               [7, 8, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
               [8, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
               [9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
               [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
               [11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21],
               [12, 12, 12, 12, 12, 12, 12, 12, 12, 21],
               [13, 13, 13, 13, 13, 13, 13, 20, 21],
               [14, 14, 14, 14, 14, 19, 20, 21], [15, 16, 16, 16, 19, 20, 21],
               [16, 16, 16, 19, 20, 21], [17, 18, 19, 20, 21],
               [18, 19, 20, 21], [19, 20, 21], [20, 21], [21]]
        for i in range(len(self.fig1_B)):
            for j in range(i + 1, len(self.fig1_B)):
                self.assertEqual(self.BP.rmq(i, j), exp[i][j - i])

    def test_rMq(self):
        #       (  (  (  )  (  )  (  (  )  )   )   (   )   (   (   (   )   (   )   )   )   )
        #excess 1  2  3  2  3  2  3  4  3  2   1   2   1   2   3   4   3   4   3   2   1   0
        #i      0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21

        exp = [[
            0, 1, 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
        ], [1, 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
               [2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
               [3, 4, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
               [4, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
               [5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
               [6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
               [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
               [8, 8, 8, 8, 8, 8, 8, 15, 15, 15, 15, 15, 15, 15],
               [9, 9, 9, 9, 9, 14, 15, 15, 15, 15, 15, 15, 15],
               [10, 11, 11, 11, 14, 15, 15, 15, 15, 15, 15, 15],
               [11, 11, 11, 14, 15, 15, 15, 15, 15, 15, 15],
               [12, 13, 14, 15, 15, 15, 15, 15, 15, 15],
               [13, 14, 15, 15, 15, 15, 15, 15, 15],
               [14, 15, 15, 15, 15, 15, 15, 15], [15, 15, 15, 15, 15, 15, 15],
               [16, 17, 17, 17, 17, 17], [17, 17, 17, 17, 17],
               [18, 18, 18, 18], [19, 19, 19], [20, 20], [21]]
        for i in range(len(self.fig1_B)):
            for j in range(i + 1, len(self.fig1_B)):
                self.assertEqual(self.BP.rMq(i, j), exp[i][j - i])

    def test_mincount(self):
        #       (  (  (  )  (  )  (  (  )  )   )   (   )   (   (   (   )   (   )   )   )   )
        #i      0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21
        #excess 1  2  3  2  3  2  3  4  3  2   1   2   1   2   3   4   3   4   3   2   1   0

        exp = [[
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1
        ], [1, 1, 2, 2, 3, 3, 3, 3, 4, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1],
               [1, 1, 1, 2, 2, 2, 2, 3, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1],
               [1, 1, 2, 2, 2, 2, 3, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1],
               [1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1],
               [1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1],
               [1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1],
               [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1],
               [1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1],
               [1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1],
               [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1],
               [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1],
               [1, 1, 1, 1, 1, 1, 1, 1, 2, 1], [1, 1, 1, 1, 1, 1, 2, 1, 1],
               [1, 1, 2, 2, 3, 1, 1, 1], [1, 1, 1, 2, 1, 1, 1],
               [1, 1, 2, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1],
               [1, 1], [1]]

        for i in range(len(self.fig1_B)):
            for j in range(i + 1, len(self.fig1_B)):
                self.assertEqual(self.BP.mincount(i, j), exp[i][j - i])

    def test_minselect(self):
        """position of the qth minimum in excess(i), excess(i + 1), . . . , excess(j)."""
        exp = {
            (0, 20, 1): 0,
            (0, 21, 1): 21,
            (0, 20, 2): 10,
            (0, 21, 2): None,
            (0, 20, 3): 12,
            (0, 20, 4): 20,
            (8, 15, 1): 10,
            (8, 15, 2): 12,
            (6, 9, 1): 9
        }

        for (i, j, q), e in exp.items():
            self.assertEqual(self.BP.minselect(i, j, q), e)

    def test_preorder(self):
        exp = [
            1, 2, 3, 3, 4, 4, 5, 6, 6, 5, 2, 7, 7, 8, 9, 10, 10, 11, 11, 9, 8,
            1
        ]
        for i, e in enumerate(exp):
            self.assertEqual(self.BP.preorder(i), e)

    def test_preorderselect(self):
        exp = [0, 1, 2, 4, 6, 7, 11, 13, 14, 15, 17]
        for k, e in enumerate(exp):
            self.assertEqual(self.BP.preorderselect(k), e)

    def test_postorder(self):
        exp = [
            11, 5, 1, 1, 2, 2, 4, 3, 3, 4, 5, 6, 6, 10, 9, 7, 7, 8, 8, 9, 10,
            11
        ]
        for i, e in enumerate(exp):
            self.assertEqual(self.BP.postorder(i), e)

    def test_postorderselect(self):
        exp = [2, 4, 7, 6, 1, 11, 15, 17, 14, 13, 0]
        for k, e in enumerate(exp):
            self.assertEqual(self.BP.postorderselect(k + 1), e)

    def test_isancestor(self):
        exp = {
            (0, 0): False,  # identity test
            (2, 1): False,  # tip test
            (1, 2): True,  # open test
            (1, 3): True,  # close test
            (0, 7): True,  # nested test
            (1, 7): True
        }  # nested test

        for (i, j), e in exp.items():
            self.assertEqual(self.BP.isancestor(i, j), e)

    def test_subtree(self):
        exp = [
            11, 5, 1, 1, 1, 1, 2, 1, 1, 2, 5, 1, 1, 4, 3, 1, 1, 1, 1, 3, 4, 11
        ]
        for i, e in enumerate(exp):
            self.assertEqual(self.BP.subtree(i), e)

    def test_levelancestor(self):
        exp = {
            (2, 1): 1,  # first tip to its parent
            (2, 2): 0,  # first tip to root
            (4, 1): 1,  # second tip to its parent
            (5, 1): 1,  # second tip, closing, to its parent
            (7, 1): 6,  # deep tip to its parent
            (7, 2): 1,  # deep tip to its grandparent
            (7, 3): 0,  # deep tip to its great grand parent
            (7, 9999): 0,  # max out at the root
            (10, 0): -1
        }  # can't be an ancestor of yourself

        for (i, d), e in exp.items():
            self.assertEqual(self.BP.levelancestor(i, d), e)

    def _testinator(self, exp, f, verbose=False):
        self.assertEqual(len(exp), len(self.fig1_B))
        for i, e in enumerate(exp):
            if verbose:
                print(i, e)
            self.assertEqual(f(i), e)

    def test_levelnext(self):
        #       (   (  (  )  (  )   (   (   )   )   )  (    )   (   (   (   )   (   )   )   )   )
        exp = [
            -1, 11, 4, 4, 6, 6, 14, 15, 15, 14, 11, 13, 13, -1, -1, 17, 17, -1,
            -1, -1, -1, -1
        ]
        self.assertEqual(len(exp), len(self.fig1_B))

        for i, e in enumerate(exp):
            self.assertEqual(self.BP.levelnext(i), e)

    def test_close(self):
        exp = [21, 10, 3, 5, 9, 8, 12, 20, 19, 16, 18]
        for i, e in zip(np.argwhere(self.BP.B == 1).squeeze(), exp):
            npt.assert_equal(self.BP.close(i), e)

    def test_lca(self):
        # lca(i, j) = parent(rmq(i, j) + 1)
        # unless isancestor(i, j)
        # (so lca(i, j) = i) or isancestor(j, i) (so lca(i, j) = j),
        nodes = [self.BP.preorderselect(k) for k in range(self.fig1_B.sum())]
        exp = {
            (nodes[2], nodes[3]): nodes[1],
            (nodes[2], nodes[5]): nodes[1],
            (nodes[2], nodes[9]): nodes[0],
            (nodes[9], nodes[10]): nodes[8],
            (nodes[1], nodes[8]): nodes[0]
        }
        for (i, j), e in exp.items():
            self.assertEqual(self.BP.lca(i, j), e)

    def test_deepestnode(self):
        # deepestnode(i) = rMq(i, close(i)),
        exp = [
            7, 7, 2, 2, 4, 4, 7, 7, 7, 7, 7, 11, 11, 15, 15, 15, 15, 17, 17,
            15, 15, 7
        ]
        self._testinator(exp, self.BP.deepestnode)

    def test_height(self):
        # height(i) = excess(deepestnode(i)) − excess(i).
        exp = [
            3, 2, 0, 0, 0, 0, 1, 0, 0, 1, 2, 0, 0, 2, 1, 0, 0, 0, 0, 1, 2, 3
        ]
        self._testinator(exp, self.BP.height)

    def test_ntips(self):
        exp = 6
        obs = self.BP.ntips()
        self.assertEqual(obs, exp)

    def test_shear(self):
        #       r  2  3     4     5  6             7       8   9  10      11
        #       (  (  (  )  (  )  (  (  )  )   )   (   )   (   (   (   )   (   )   )   )   )
        #i      0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21
        names = np.array([
            'r', '2', '3', None, '4', None, '5', '6', None, None, None, '7',
            None, '8', '9', '10', None, '11', None, None, None, None
        ])
        lengths = np.array([
            0, 1, 2, 0, 3, 0, 4, 5, 0, 0, 0, 6, 0, 7, 8, 9, 0, 10, 0, 0, 0, 0
        ],
                           dtype=np.double)
        self.BP.set_names(names)
        self.BP.set_lengths(lengths)

        in_ = {'4', '6', '7', '10', '11'}
        exp = np.array(
            [1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0],
            dtype=np.uint32)
        exp_n = np.array([
            'r', '2', '4', None, '5', '6', None, None, None, '7', None, '8',
            '9', '10', None, '11', None, None, None, None
        ])
        exp_l = np.array(
            [0, 1, 3, 0, 4, 5, 0, 0, 0, 6, 0, 7, 8, 9, 0, 10, 0, 0, 0, 0],
            dtype=np.double)
        obs = self.BP.shear(in_)
        npt.assert_equal(exp, obs.B)

        for i in range(len(obs.B)):
            self.assertEqual(obs.name(i), exp_n[i])
            self.assertEqual(obs.length(i), exp_l[i])

        in_ = {'10', '11'}
        exp = np.array([1, 1, 1, 1, 0, 1, 0, 0, 0, 0], dtype=np.uint32)
        obs = self.BP.shear(in_).B
        npt.assert_equal(obs, exp)

    def test_shear_raise_tree_is_empty(self):
        names = np.array([
            'r', '2', '3', None, '4', None, '5', '6', None, None, None, '7',
            None, '8', '9', '10', None, '11', None, None, None, None
        ])
        lengths = np.array([
            0, 1, 2, 0, 3, 0, 4, 5, 0, 0, 0, 6, 0, 7, 8, 9, 0, 10, 0, 0, 0, 0
        ],
                           dtype=np.double)
        self.BP.set_names(names)
        with self.assertRaises(ValueError):
            self.BP.shear({'not', 'in', 'tree'})

    def test_collapse(self):
        names = np.array([
            'r', '2', '3', None, '4', None, '5', '6', None, None, None, '7',
            None, '8', '9', '10', None, '11', None, None, None, None
        ])
        lengths = np.array([
            0, 1, 2, 0, 3, 0, 4, 5, 0, 0, 0, 6, 0, 7, 8, 9, 0, 10, 0, 0, 0, 0
        ],
                           dtype=np.double)
        self.BP.set_names(names)
        self.BP.set_lengths(lengths)

        exp = np.array([1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0],
                       dtype=np.uint8)
        exp_n = [
            'r', '2', '3', None, '4', None, '6', None, None, '7', None, '9',
            '10', None, '11', None, None, None
        ]
        exp_l = [0, 1, 2, 0, 3, 0, 9, 0, 0, 6, 0, 15, 9, 0, 10, 0, 0, 0]

        obs = self.BP.collapse()

        npt.assert_equal(obs.B, exp)
        for i in range(len(obs.B)):
            self.assertEqual(obs.name(i), exp_n[i])
            self.assertEqual(obs.length(i), exp_l[i])

        bp = BP(np.array([1, 1, 1, 0, 0, 1, 0, 0], dtype=np.uint8))
        exp = np.array([1, 1, 0, 1, 0, 0])
        obs = bp.collapse().B

        npt.assert_equal(obs, exp)

    def test_name_unset(self):
        for i in range(self.BP.B.size):
            self.assertEqual(self.BP.name(i), None)

    def test_length_unset(self):
        for i in range(self.BP.B.size):
            self.assertEqual(self.BP.length(i), 0.0)

    def test_name_length_set(self):
        names = np.full(self.BP.B.size, None, dtype=object)
        lengths = np.zeros(self.BP.B.size, dtype=np.double)

        names[0] = 'root'
        names[self.BP.preorderselect(7)] = 'other'

        lengths[1] = 1.23
        lengths[self.BP.preorderselect(5)] = 5.43

        self.BP.set_names(names)
        self.BP.set_lengths(lengths)

        self.assertEqual(self.BP.name(0), 'root')
        self.assertEqual(self.BP.name(1), None)
        self.assertEqual(self.BP.name(13), 'other')
        self.assertEqual(self.BP.length(1), 1.23)
        self.assertEqual(self.BP.length(5), 0.0)
        self.assertEqual(self.BP.length(7), 5.43)
Ejemplo n.º 4
0
class BPTests(TestCase):
    def setUp(self):
        #                       0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21
        self.fig1_B = np.array([1, 1, 1, 0, 1, 0, 1, 1 ,0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0], dtype=np.uint8)
        self.BP = BP(self.fig1_B)

    def test_rmq(self):
        #       (  (  (  )  (  )  (  (  )  )   )   (   )   (   (   (   )   (   )   )   )   )
        #excess 1  2  3  2  3  2  3  4  3  2   1   2   1   2   3   4   3   4   3   2   1   0
        #i      0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21

        exp = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 21],
                  [1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
                     [2, 3, 3, 3, 3, 3, 3, 3, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
                        [3, 3, 3, 3, 3, 3, 3, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
                           [4, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
                              [5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
                                 [6, 6, 6, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
                                    [7, 8, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
                                       [8, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
                                          [9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
                                             [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21],
                                                 [11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21],
                                                     [12, 12, 12, 12, 12, 12, 12, 12, 12, 21],
                                                         [13, 13, 13, 13, 13, 13, 13, 20, 21],
                                                             [14, 14, 14, 14, 14, 19, 20, 21],
                                                                 [15, 16, 16, 16, 19, 20, 21],
                                                                     [16, 16, 16, 19, 20, 21],
                                                                         [17, 18, 19, 20, 21],
                                                                             [18, 19, 20, 21],
                                                                                 [19, 20, 21],
                                                                                     [20, 21],
                                                                                         [21]]
        for i in range(len(self.fig1_B)):
            for j in range(i+1, len(self.fig1_B)):
                self.assertEqual(self.BP.rmq(i, j), exp[i][j - i])

    def test_rMq(self):
        #       (  (  (  )  (  )  (  (  )  )   )   (   )   (   (   (   )   (   )   )   )   )
        #excess 1  2  3  2  3  2  3  4  3  2   1   2   1   2   3   4   3   4   3   2   1   0
        #i      0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21

        exp = [[0, 1, 2, 2, 2, 2, 2, 7, 7, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 7],
                  [1, 2, 2, 2, 2, 2, 7, 7, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 7],
                     [2, 2, 2, 2, 2, 7, 7, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 7],
                        [3, 4, 4, 4, 7, 7, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 7],
                           [4, 4, 4, 7, 7, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 7],
                              [5, 6, 7, 7, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 7],
                                 [6, 7, 7, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 7],
                                    [7, 7, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 7],
                                       [8, 8,  8,  8,  8,  8,  8, 15, 15, 15, 15, 15, 15, 15],
                                          [9,  9,  9,  9,  9, 14, 15, 15, 15, 15, 15, 15, 15],
                                             [10, 11, 11, 11, 14, 15, 15, 15, 15, 15, 15, 15],
                                                 [11, 11, 11, 14, 15, 15, 15, 15, 15, 15, 15],
                                                     [12, 13, 14, 15, 15, 15, 15, 15, 15, 15],
                                                         [13, 14, 15, 15, 15, 15, 15, 15, 15],
                                                             [14, 15, 15, 15, 15, 15, 15, 15],
                                                                 [15, 15, 15, 15, 15, 15, 15],
                                                                     [16, 17, 17, 17, 17, 17],
                                                                         [17, 17, 17, 17, 17],
                                                                             [18, 18, 18, 18],
                                                                                 [19, 19, 19],
                                                                                     [20, 20],
                                                                                         [21]]
        for i in range(len(self.fig1_B)):
            for j in range(i+1, len(self.fig1_B)):
                self.assertEqual(self.BP.rMq(i, j), exp[i][j - i])

    def test_mincount(self):
        #       (  (  (  )  (  )  (  (  )  )   )   (   )   (   (   (   )   (   )   )   )   )
        #i      0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21
        #excess 1  2  3  2  3  2  3  4  3  2   1   2   1   2   3   4   3   4   3   2   1   0

        exp = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,  4, 1],
                  [1, 1, 2, 2, 3, 3, 3, 3, 4,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3, 1],
                     [1, 1, 1, 2, 2, 2, 2, 3,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3, 1],
                        [1, 1, 2, 2, 2, 2, 3,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3, 1],
                           [1, 1, 1, 1, 1, 2,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3, 1],
                              [1, 1, 1, 1, 2,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3, 1],
                                 [1, 1, 2, 1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3, 1],
                                    [1, 1, 1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3, 1],
                                       [1, 1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3, 1],
                                          [1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3, 1],
                                              [1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3, 1],
                                                  [1,  1,  1,  1,  1,  1,  1,  1,  1,  2, 1],
                                                      [1,  1,  1,  1,  1,  1,  1,  1,  2, 1],
                                                          [1,  1,  1,  1,  1,  1,  2,  1, 1],
                                                              [1,  1,  2,  2,  3,  1,  1, 1],
                                                                  [1,  1,  1,  2,  1,  1, 1],
                                                                      [1,  1,  2,  1,  1, 1],
                                                                          [1,  1,  1,  1, 1],
                                                                              [1,  1,  1, 1],
                                                                                  [1,  1, 1],
                                                                                      [1, 1],
                                                                                         [1]]

        for i in range(len(self.fig1_B)):
            for j in range(i+1, len(self.fig1_B)):
                self.assertEqual(self.BP.mincount(i, j), exp[i][j - i])

    def test_minselect(self):
        """position of the qth minimum in excess(i), excess(i + 1), . . . , excess(j)."""
        exp = {(0, 20, 1): 0,
               (0, 21, 1): 21,
               (0, 20, 2): 10,
               (0, 21, 2): None,
               (0, 20, 3): 12,
               (0, 20, 4): 20,
               (8, 15, 1): 10,
               (8, 15, 2): 12,
               (6, 9, 1): 9}

        for (i, j, q), e in exp.items():
            self.assertEqual(self.BP.minselect(i, j, q), e)

    def test_preorder(self):
        exp = [1, 2, 3, 3, 4, 4, 5, 6, 6, 5, 2, 7, 7, 8, 9, 10, 10, 11, 11, 9, 8, 1]
        for i, e in enumerate(exp):
            self.assertEqual(self.BP.preorder(i), e)

    def test_preorderselect(self):
        exp = [0, 1, 2, 4, 6, 7, 11, 13, 14, 15, 17]
        for k, e in enumerate(exp):
            self.assertEqual(self.BP.preorderselect(k), e)

    def test_postorder(self):
        exp = [11, 5, 1, 1, 2, 2, 4, 3, 3, 4, 5, 6, 6, 10, 9, 7, 7, 8, 8, 9, 10, 11]
        for i, e in enumerate(exp):
            self.assertEqual(self.BP.postorder(i), e)

    def test_postorderselect(self):
        exp = [2, 4, 7, 6, 1, 11, 15, 17, 14, 13, 0]
        for k, e in enumerate(exp):
            self.assertEqual(self.BP.postorderselect(k + 1), e)

    def test_isancestor(self):
        exp = {(0, 0): False,  # identity test
               (2, 1): False,  # tip test
               (1, 2): True,   # open test
               (1, 3): True,   # close test
               (0, 7): True,   # nested test
               (1, 7): True}   # nested test

        for (i, j), e in exp.items():
            self.assertEqual(self.BP.isancestor(i, j), e)

    def test_subtree(self):
        exp = [11, 5, 1, 1, 1, 1, 2, 1, 1, 2, 5, 1, 1, 4, 3, 1, 1, 1, 1, 3, 4, 11]
        for i, e in enumerate(exp):
            self.assertEqual(self.BP.subtree(i), e)

    def test_levelancestor(self):
        exp = {(2, 1): 1,  # first tip to its parent
               (2, 2): 0,  # first tip to root
               (4, 1): 1,  # second tip to its parent
               (5, 1): 1,  # second tip, closing, to its parent
               (7, 1): 6,  # deep tip to its parent
               (7, 2): 1,  # deep tip to its grandparent
               (7, 3): 0,  # deep tip to its great grand parent
               (7, 9999): 0,  # max out at the root
               (10, 0): -1}  # can't be an ancestor of yourself

        for (i, d), e in exp.items():
            self.assertEqual(self.BP.levelancestor(i, d), e)

    def _testinator(self, exp, f, verbose=False):
        self.assertEqual(len(exp), len(self.fig1_B))
        for i, e in enumerate(exp):
            if verbose:
                print(i, e)
            self.assertEqual(f(i), e)

    def test_levelnext(self):
        #       (   (  (  )  (  )   (   (   )   )   )  (    )   (   (   (   )   (   )   )   )   )
        exp = [-1, 11, 4, 4, 6, 6, 14, 15, 15, 14, 11, 13, 13, -1, -1, 17, 17, -1, -1, -1, -1, -1]
        self.assertEqual(len(exp), len(self.fig1_B))

        for i, e in enumerate(exp):
            self.assertEqual(self.BP.levelnext(i), e)

    def test_lca(self):
        # lca(i, j) = parent(rmq(i, j) + 1)
        # unless isancestor(i, j)
        # (so lca(i, j) = i) or isancestor(j, i) (so lca(i, j) = j),
        nodes = [self.BP.preorderselect(k) for k in range(self.fig1_B.sum())]
        exp = {(nodes[2], nodes[3]): nodes[1],
               (nodes[2], nodes[5]): nodes[1],
               (nodes[2], nodes[9]): nodes[0],
               (nodes[9], nodes[10]): nodes[8],
               (nodes[1], nodes[8]): nodes[0]}
        for (i, j), e in exp.items():
            self.assertEqual(self.BP.lca(i, j), e)

    def test_deepestnode(self):
        # deepestnode(i) = rMq(i, close(i)),
        exp = [7, 7, 2, 2, 4, 4, 7, 7, 7, 7, 7, 11, 11, 15, 15, 15, 15, 17, 17, 15, 15, 7]
        self._testinator(exp, self.BP.deepestnode)

    def test_height(self):
        # height(i) = excess(deepestnode(i)) − excess(i).
        exp = [3, 2, 0, 0, 0, 0, 1, 0, 0, 1, 2, 0, 0, 2, 1, 0, 0, 0, 0, 1, 2, 3]
        self._testinator(exp, self.BP.height)

    def test_ntips(self):
        exp = 6
        obs = self.BP.ntips()
        self.assertEqual(obs, exp)

    def test_shear(self):
        #       r  2  3     4     5  6             7       8   9  10      11
        #       (  (  (  )  (  )  (  (  )  )   )   (   )   (   (   (   )   (   )   )   )   )
        #i      0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21
        names = np.array(['r', '2', '3', None, '4', None, '5', '6', None, None, None, '7', None, '8', '9', '10', None,
                          '11', None, None, None, None])
        lengths = np.array([0, 1, 2, 0, 3, 0, 4, 5, 0, 0, 0, 6, 0, 7, 8, 9, 0, 10, 0, 0, 0, 0], dtype=np.double)
        self.BP.set_names(names)
        self.BP.set_lengths(lengths)

        in_ = {'4', '6', '7', '10', '11'}
        exp = np.array([1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0,
                        0, 0], dtype=np.uint32)
        exp_n = np.array(['r', '2', '4', None, '5', '6', None, None, None, '7', None, '8', '9', '10', None, '11', None,
                          None, None, None])
        exp_l = np.array([0, 1, 3, 0, 4, 5, 0, 0, 0, 6, 0, 7, 8, 9, 0, 10, 0, 0, 0, 0], dtype=np.double)
        obs = self.BP.shear(in_)
        npt.assert_equal(exp, obs.B)

        for i in range(len(obs.B)):
            self.assertEqual(obs.name(i), exp_n[i])
            self.assertEqual(obs.length(i), exp_l[i])

        in_ = {'10', '11'}
        exp = np.array([1, 1, 1, 1, 0, 1, 0, 0, 0, 0], dtype=np.uint32)
        obs = self.BP.shear(in_).B
        npt.assert_equal(obs, exp)

    def test_collapse(self):
        names = np.array(['r', '2', '3', None, '4', None, '5', '6', None, None, None, '7', None, '8', '9', '10', None,
                          '11', None, None, None, None])
        lengths = np.array([0, 1, 2, 0, 3, 0, 4, 5, 0, 0, 0, 6, 0, 7, 8, 9, 0, 10, 0, 0, 0, 0], dtype=np.double)
        self.BP.set_names(names)
        self.BP.set_lengths(lengths)

        exp = np.array([1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0],
                       dtype=np.uint8)
        exp_n = ['r', '2', '3', None, '4', None, '6', None, None, '7', None, '9', '10', None, '11', None, None, None]
        exp_l = [0, 1, 2, 0, 3, 0, 9, 0, 0, 6, 0, 15, 9, 0, 10, 0, 0, 0]

        obs = self.BP.collapse()

        npt.assert_equal(obs.B, exp)
        for i in range(len(obs.B)):
            self.assertEqual(obs.name(i), exp_n[i])
            self.assertEqual(obs.length(i), exp_l[i])

        bp = BP(np.array([1, 1, 1, 0, 0, 1, 0, 0], dtype=np.uint8))
        exp = np.array([1, 1, 0, 1, 0, 0])
        obs = bp.collapse().B

        npt.assert_equal(obs, exp)

    def test_name_unset(self):
        for i in range(self.BP.B.size):
            self.assertEqual(self.BP.name(i), None)

    def test_length_unset(self):
        for i in range(self.BP.B.size):
            self.assertEqual(self.BP.length(i), 0.0)

    def test_name_length_set(self):
        names = np.full(self.BP.B.size, None, dtype=object)
        lengths = np.zeros(self.BP.B.size, dtype=np.double)

        names[0] = 'root'
        names[self.BP.preorderselect(7)] = 'other'

        lengths[1] = 1.23
        lengths[self.BP.preorderselect(5)] = 5.43

        self.BP.set_names(names)
        self.BP.set_lengths(lengths)

        self.assertEqual(self.BP.name(0), 'root')
        self.assertEqual(self.BP.name(1), None)
        self.assertEqual(self.BP.name(13), 'other')
        self.assertEqual(self.BP.length(1), 1.23)
        self.assertEqual(self.BP.length(5), 0.0)
        self.assertEqual(self.BP.length(7), 5.43)