Esempio n. 1
0
    def __init__(self, newickstr, periods=None, root_age=None):
        """
        newickstr: newick tree with branch lengths
        periods: list of durations ordered from present to past
        root_age: age of root node for branch length scaling
        """
        self.root = newick.parse(newickstr)
        phylo.polarize(self.root)
        self.periods = periods

        # initialize nodes (label interiors, etc)
        # and collect leaves and postorder sequence
        self.postorder_nodes = []
        self.leaves = []
        for i, node in enumerate(self.root.descendants(phylo.POSTORDER)):
            node.tree = self
            node.number = i
            node.segments = []
            if (not node.istip) and (not node.label):
                node.label = str(node.number)
            node.age = None
            if node.istip:
                #node.age = 0.0
                self.leaves.append(node)
            self.postorder_nodes.append(node)

        self.root_age = root_age
        if root_age:
            self.calibrate(root_age)

        self.label2node = dict([(n.label, n) for n in self.postorder_nodes ])

        self.assign_node_ages()
##         for node in self.postorder_nodes:
##             if node.parent and (node.parent.age is None):
##                 node.parent.age = node.age + node.length

        # initialize branch segments
        for node in self.postorder_nodes:
            if node.parent:
                periods = self.periods
                anc = node.parent.age
                des = node.age
                assert anc > des, "%s = %g, %s = %g\n%s" \
                       % (node.parent.label, anc, node.label, des,
                          self.root.render_ascii(scaled=1, minwidth=80))
                t = des
                for i, p in enumerate(periods):
                    s = sum(periods[:i+1])
                    if t < s:
                        duration = min((s - t, anc - t))
                        if duration > 0:
                            seg = BranchSegment(duration, i)
                            node.segments.append(seg)
                        t += p
                    if t > anc:
                        break
Esempio n. 2
0
def tree2ascii(tree, unitlen=3, minwidth=None, maxwidth=None, scaled=False, show_internal_labels=True, data=None):
    phylo.polarize(tree)
    depth_length_preorder_traversal(tree)

    leaves = tree.leaves()
    nleaves = len(leaves)
    node2label = dict([(n, n.label) for n in tree.descendants()])
    if data:
        for k, v in node2label.items():
            if v in data:
                if k.istip:
                    node2label[k] = "[%s] %s" % (data[v], v)
                else:
                    node2label[k] = "%s [%s]" % (data[v], v)

    maxdepth = max([lf.depth for lf in leaves])

    max_labelwidth = max([len(node2label[lf]) for lf in leaves]) + 1

    root_offset = 0
    if tree.label and show_internal_labels:
        root_offset = len(node2label[tree])

    width = maxdepth * unitlen + max_labelwidth + 2 + root_offset
    # print width

    height = 2 * nleaves - 1

    if minwidth and (width < minwidth):
        unitlen = (minwidth - max_labelwidth - 2 - root_offset) / maxdepth
        width = maxdepth * unitlen + max_labelwidth + 2 + root_offset

    buf = AsciiBuffer(width, height)

    for i, lf in enumerate(leaves):
        lf.c = width - max_labelwidth - 2
        lf.r = i * 2

    for node in tree.descendants(phylo.POSTORDER):
        if not node.istip:
            children = node.children()
            rmin = children[0].r
            rmax = children[-1].r
            node.r = int(rmin + (rmax - rmin) / 2.0)
            node.c = min([ch.c for ch in children]) - unitlen

    if not scaled:
        for i in range(maxdepth):
            smooth_cpos(tree)
    else:
        maxlen = max([lf.length_to_root for lf in leaves])
        scalef = (leaves[0].c + 1 - root_offset) / maxlen
        scale_cpos(tree, scalef, root_offset)

    for node in tree.descendants(phylo.POSTORDER):

        if node.parent:
            for r in range(min([node.r, node.parent.r]), max([node.r, node.parent.r])):
                buf.putstr(r, node.parent.c, ":")

            sym = getattr(node, "hchar", "-")
            vbar = sym * (node.c - node.parent.c)
            buf.putstr(node.r, node.parent.c, vbar)

        if node.istip:
            buf.putstr(node.r, node.c + 1, " " + node2label[node])
        else:
            if node.label and show_internal_labels:
                label = node2label[node]
                buf.putstr(node.r, node.c - len(label), label)

        buf.putstr(node.r, node.c, "+")

    return str(buf)