Esempio n. 1
0
def collapse_conflicting(subtree_root, split, split_bitmask):
    """
    Takes a node that is the root of a subtree.  Collapses every edge in the
    subtree that conflicts with split.  This can include the edge subtending
    subtree_root.
    """
    # we flip splits so that both the split and each edges split  have the
    # lowest bit of the clade mask set to one
    lb = treesplit.lowest_bit_only(split_bitmask)

    if lb & split:
        cropped_split = split & split_bitmask
    else:
        cropped_split = (~split) & split_bitmask

    to_collapse_head_nodes = []
    for nd in subtree_root.postorder_iter():
        if not nd.is_leaf():
            ncm = nd.edge.split_bitmask
            if lb & ncm:
                nd_split = ncm & split_bitmask
            else:
                nd_split = (~ncm) & split_bitmask

            cm_union = nd_split | cropped_split
            if (cm_union != nd_split) and (cm_union != cropped_split):
                to_collapse_head_nodes.append(nd)

    for nd in to_collapse_head_nodes:
        e = nd.edge
        e.collapse()
def collapse_conflicting(subtree_root, split, split_bitmask):
    """
    Takes a node that is the root of a subtree.  Collapses every edge in the
    subtree that conflicts with split.  This can include the edge subtending
    subtree_root.
    """
    # we flip splits so that both the split and each edges split  have the
    # lowest bit of the clade mask set to one
    lb = treesplit.lowest_bit_only(split_bitmask)

    if lb & split:
        cropped_split = split & split_bitmask
    else:
        cropped_split = (~split) & split_bitmask

    to_collapse_head_nodes = []
    for nd in subtree_root.postorder_iter():
        if not nd.is_leaf():
            ncm = nd.edge.split_bitmask
            if lb & ncm:
                nd_split = ncm & split_bitmask
            else:
                nd_split = (~ncm) & split_bitmask

            cm_union = nd_split | cropped_split
            if (cm_union != nd_split) and (cm_union != cropped_split):
                to_collapse_head_nodes.append(nd)

    for nd in to_collapse_head_nodes:
        e = nd.edge
        e.collapse()
Esempio n. 3
0
def reroot_on_lowest_common_index_path(t, common_mask):
    """This operation is only for unrooted trees that are being merged using
    SCM. The path the separates the lowest index taxon in the leaf set
    intersection is placed as the first descendant path of the "seed_node" for
    the tree.
    This assures that all split representations are oriented in the same way
    for subsequent operations.
    The mask most contain more that 2 bits (there must be an internal node in
    the tree that is has degree > 2  wrt the common leafset).
    """
    l = lowest_bit_only(common_mask)
    assert (l > 0)
    assert (count_bits(common_mask) > 2)
    # start at the lowest leaf in common.
    curr_n = t.split_edges[l].head_node
    # walk back toward the root until we find a node that has another bit
    p = curr_n.parent_node
    while p:
        if (p.edge.split_bitmask & common_mask) != l:
            break
        curr_n = p
        p = curr_n.parent_node

    without_lowest = common_mask ^ l

    taxa_mask = t.seed_node.edge.split_bitmask
    if (curr_n.edge.split_bitmask & common_mask) == l:
        # we did not make it to the root.  Make curr_n, the first_child of the root
        t.to_outgroup_position(curr_n,
                               update_splits=True,
                               delete_outdegree_one=True)
        avoid = curr_n
        nd_source = iter(t.seed_node.child_nodes())

        try:
            while True:
                curr_n = nd_source.next()
                if curr_n is not avoid:
                    cm = (curr_n.edge.split_bitmask & without_lowest)
                    if cm:
                        if cm == without_lowest:
                            r = t.seed_node
                            assert curr_n.parent_node is r
                            t.reseed_at(curr_n,
                                        update_splits=True,
                                        delete_outdegree_one=True)
                            t.to_outgroup_position(r,
                                                   update_splits=True,
                                                   delete_outdegree_one=True)
                            nd_source = iter(curr_n.child_nodes())
                            avoid = r
                        else:
                            return
        except StopIteration:
            assert False
            return
    # we hit the root, now we walk up the tree, to find the a relevant internal
    lowest_on_path_to_l = curr_n
    comp_mask = (~common_mask) & taxa_mask
    children = curr_n.child_nodes()
    assert (len(children) > 1)
    nd_source = iter(children)
    try:
        while True:
            c = nd_source.next()
            cm = c.edge.split_bitmask
            masked_cm = cm & common_mask
            if masked_cm:
                if masked_cm == without_lowest:
                    curr_n = c
                    children = curr_n.child_nodes()
                    assert (len(children) > 1)
                    nd_source = iter(children)
                else:
                    break
    except StopIteration:
        raise AssertionError("Reaching supposedly unreachable code")

    if curr_n is not t.seed_node:
        # We have found the first relevant internal node, we want to make it
        #   the root.  We can do this by putting one of its children into the
        #   "outgroup position" and then putting the path to lowest commond
        #   leaf in the outgroup position (this last operation is just a
        #   rearrangement of the order of children in the root.
        children = curr_n.child_nodes()
        assert (len(children) > 1)
        p = curr_n.parent
        t.to_outgroup_position(children[0],
                               update_splits=True,
                               delete_outdegree_one=True)
        t.to_outgroup_position(p,
                               update_splits=True,
                               delete_outdegree_one=True)
    else:
        # if the root first relevant, node then we just make the path leading
        #   to the lowest index node the first child of the root
        t.to_outgroup_position(lowest_on_path_to_l,
                               update_splits=True,
                               delete_outdegree_one=True)
Esempio n. 4
0
def reroot_on_lowest_common_index_path(t, common_mask):
    """This operation is only for unrooted trees that are being merged using
    SCM. The path the separates the lowest index taxon in the leaf set
    intersection is placed as the first descendant path of the "seed_node" for
    the tree.
    This assures that all split representations are oriented in the same way
    for subsequent operations.
    The mask most contain more that 2 bits (there must be an internal node in
    the tree that is has degree > 2  wrt the common leafset).
    """
    l = lowest_bit_only(common_mask)
    assert(l > 0)
    assert(count_bits(common_mask) > 2)
    # start at the lowest leaf in common.
    curr_n = t.split_edges[l].head_node
    # walk back toward the root until we find a node that has another bit
    p = curr_n.parent_node
    while p:
        if (p.edge.split_bitmask & common_mask) != l:
            break
        curr_n = p
        p = curr_n.parent_node

    without_lowest = common_mask^l

    taxa_mask = t.seed_node.edge.split_bitmask
    if (curr_n.edge.split_bitmask & common_mask) == l:
        # we did not make it to the root.  Make curr_n, the first_child of the root
        t.to_outgroup_position(curr_n, update_splits=True, delete_outdegree_one=True)
        avoid = curr_n
        nd_source = iter(t.seed_node.child_nodes())

        try:
            while True:
                curr_n = nd_source.next()
                if curr_n is not avoid:
                    cm = (curr_n.edge.split_bitmask & without_lowest)
                    if cm:
                        if cm == without_lowest:
                            r = t.seed_node
                            assert curr_n.parent_node is r
                            t.reseed_at(curr_n, update_splits=True, delete_outdegree_one=True)
                            t.to_outgroup_position(r, update_splits=True, delete_outdegree_one=True)
                            nd_source = iter(curr_n.child_nodes())
                            avoid = r
                        else:
                            return
        except StopIteration:
            assert False
            return
    # we hit the root, now we walk up the tree, to find the a relevant internal
    lowest_on_path_to_l = curr_n
    comp_mask = (~common_mask) & taxa_mask
    children = curr_n.child_nodes()
    assert(len(children) > 1)
    nd_source = iter(children)
    try:
        while True:
            c = nd_source.next()
            cm = c.edge.split_bitmask
            masked_cm = cm & common_mask
            if masked_cm:
                if masked_cm == without_lowest:
                    curr_n = c
                    children = curr_n.child_nodes()
                    assert(len(children) > 1)
                    nd_source = iter(children)
                else:
                    break
    except StopIteration:
        raise AssertionError("Reaching supposedly unreachable code")

    if curr_n is not t.seed_node:
        # We have found the first relevant internal node, we want to make it
        #   the root.  We can do this by putting one of its children into the
        #   "outgroup position" and then putting the path to lowest commond
        #   leaf in the outgroup position (this last operation is just a
        #   rearrangement of the order of children in the root.
        children = curr_n.child_nodes()
        assert(len(children) > 1)
        p = curr_n.parent
        t.to_outgroup_position(children[0], update_splits=True, delete_outdegree_one=True)
        t.to_outgroup_position(p, update_splits=True, delete_outdegree_one=True)
    else:
        # if the root first relevant, node then we just make the path leading
        #   to the lowest index node the first child of the root
        t.to_outgroup_position(lowest_on_path_to_l, update_splits=True, delete_outdegree_one=True)
Esempio n. 5
0
 def runTest(self):
     for n, expected in enumerate(
         [0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, 16]):
         self.assertEqual(treesplit.lowest_bit_only(n), expected)
 def runTest(self):
     for n, expected in enumerate([0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, 16]):
         self.assertEqual(treesplit.lowest_bit_only(n), expected)