Phylo BioPython 构建树结构

6 投票
1 回答
2868 浏览
提问于 2025-04-16 06:17

我正在用BioPython的Phylo模块构建一棵树。
到目前为止,我做出的效果是这个图: alt text

每个名字后面都有一个四位数的编号,后面跟着一个短横线和一个数字:这个数字表示这个序列出现的次数。比如1578 - 22,这个节点应该代表22个序列。

这是对齐后的序列文件: 文件
这是用来构建树的距离文件: 文件

现在我知道怎么改变每个节点的大小。每个节点的大小都不同,这可以通过创建一个包含不同值的数组来轻松实现:

    fh = open(MEDIA_ROOT + "groupsnp.txt")    
    list_size = {}
    for line in fh:
        if '>' in line:
            labels = line.split('>')
            label = labels[-1]
            label = label.split()
            num = line.split('-')
            size = num[-1]
            size = size.split()
            for lab in label:
                for number in size:
                    list_size[lab] = int(number)

    a = array(list_size.values())

但是这个数组是随意的,我想把正确的节点大小放到对应的节点里。我试过这样做:

         for elem in list_size.keys():
             if labels == elem:
                 Phylo.draw_graphviz(tree_xml, prog="neato", node_size=a)

但是当我使用if语句时,什么也没有显示出来。

有没有办法做到这一点呢?

我会非常感激!

谢谢大家

1 个回答

8

我终于把这个搞定了。基本的思路是,你要用 labels/nodelist 来构建你的 node_sizes。这样它们就能正确对应起来。我相信我还缺少一些重要的选项,可能让树的样子看起来更完美,但目前节点的大小显示得还不错。

#basically a stripped down rewrite of Phylo.draw_graphviz
import networkx, pylab
from Bio import Phylo


#taken from draw_graphviz
def get_label_mapping(G, selection): 
    for node in G.nodes(): 
        if (selection is None) or (node in selection): 
            try: 
                label = str(node) 
                if label not in (None, node.__class__.__name__): 
                    yield (node, label) 
            except (LookupError, AttributeError, ValueError): 
                pass


kwargs={}
tree = Phylo.read('tree.dnd', 'newick')
G = Phylo.to_networkx(tree)
Gi = networkx.convert_node_labels_to_integers(G, discard_old_labels=False)

node_sizes = []
labels = dict(get_label_mapping(G, None))
kwargs['nodelist'] = labels.keys()

#create our node sizes based on our labels because the labels are used for the node_list
#this way they should be correct
for label in labels.keys():
    if str(label) != "Clade":
        num = label.name.split('-')
        #the times 50 is just a guess on what would look best
        size = int(num[-1]) * 50
        node_sizes.append(size)

kwargs['node_size'] = node_sizes
posi = networkx.pygraphviz_layout(Gi, 'neato', args='') 
posn = dict((n, posi[Gi.node_labels[n]]) for n in G) 

networkx.draw(G, posn, labels=labels, node_color='#c0deff', **kwargs)

pylab.show()

生成的树 alt text

撰写回答