示例#1
0
    def AddLeafToTree(self, id, diameter):
        """
        Add a single leaf to the tree. The position is guided 
        by the diameter parameter which indicates the precentage
        of the maximum possible tree diameter to use.
        """

        # Handle the cases where the tree is empty (or a single node)
        if len(self.__tree.vertices) == 0:
            Leaf(label=id, tree=self.__tree)
        elif len(self.__tree.vertices) == 1:
            Edge(nodes=[
                self.__tree.vertices[0],
                Leaf(label=id, tree=self.__tree)
            ],
                 tree=self.__tree)
        else:
            # Find the edges which will (and will not) increase the diameter
            (will, willnot) = self.__PartitionEdges()

            # if no unmarked edges exist or we want to increase diameter
            # randomly select an edge to split

            if not len(willnot) or random.random() > (1.0 - diameter):
                esplit = random.choice(will)
            else:
                esplit = random.choice(willnot)

            # Add new taxa splitting the edge
            self.__SplitEdge(esplit, id)
示例#2
0
    def __TreeFromBipartition(self, bp):
        """Generate an initial non-binary tree from a bipartition"""

        e = Edge(tree=self.__tree)
        left = Inner(edges=[e], tree=self.__tree)
        right = Inner(edges=[e], tree=self.__tree)

        [
            Edge(nodes=[Leaf(label=str(leaf), tree=self.__tree), left],
                 tree=self.__tree) for leaf in bp.left
        ]
        [
            Edge(nodes=[Leaf(label=str(leaf), tree=self.__tree), right],
                 tree=self.__tree) for leaf in bp.right
        ]
示例#3
0
    def __FindAncestors(self, leaves):
        """
        Finds all inner nodes in the path between the leaves.
        Leaves not found will be added.
        """

        leafIdSet = set(str(l) for l in leaves)

        # Find any new leafs

        newLeafIds = leafIdSet.difference(self.__tree.leafSet)
        assert len(newLeafIds) != len(leafIdSet)

        oldLeafIds = leafIdSet - newLeafIds
        oldLeafObjs = [l for l in self.__tree.leaves if str(l) in oldLeafIds]

        # Only one id, add any nodes to it's parent

        if len(oldLeafObjs) == 1:
            parent = oldLeafObjs[0].edges[0].Other(oldLeafObjs[0])
            newLeafObjs = []
            for l in newLeafIds:
                leaf = Leaf(edge=Edge(nodes=[parent], tree=self.__tree),
                            label=l,
                            tree=self.__tree)
                newLeafObjs.append(leaf)

            inodes = self.__FindInnerNodes(oldLeafObjs + newLeafObjs)

        # Multiple old id's, find the overall path and add to the common node

        else:

            # Get the paths for the existing (old) leafs
            inodes = self.__FindInnerNodes(oldLeafObjs)

            assert not len(newLeafIds) or len(inodes) == 1

            # Add new nodes to the tree at the inode point
            [
                Leaf(edge=Edge(nodes=[inodes[0]], tree=self.__tree),
                     label=l,
                     tree=self.__tree) for l in newLeafIds
            ]

        return inodes
示例#4
0
    def __SplitEdge(self, edge, id):
        """
        Add a new taxa by splitting an existing edge
        """

        # Disconnect the edge

        nright = edge.nodes[0]
        nleft = edge.nodes[1]
        nright.RemoveEdge(edge)
        nleft.RemoveEdge(edge)

        # Connect it all up

        Leaf(label=id, edge=edge, tree=self.__tree)
        Inner(edges=[
            Edge(nodes=[nleft], tree=self.__tree),
            Edge(nodes=[nright], tree=self.__tree), edge
        ],
              tree=self.__tree)