Поскольку вы пытаетесь разобрать дерево филогенетического c, я настоятельно рекомендую, чтобы Bio Python сделал за вас тяжелую работу.
Вы можете легко проанализировать и отобразить филогенетический c с Bio.Phylo . Затем он просто перебирает все элементы дерева и разделяет имена по знаку «at».
Поскольку Phylo ожидает, что ввод находится в файле, мы создаем файл-подобный объект в памяти с помощью io.StringIO
. Получить полное дерево так же просто, как
Phylo.read(io.StringIO(s), 'newick')
Чтобы проверить, выглядит ли проанализированное дерево в здравом уме, я печатаю его один раз с помощью print(tree)
.
Теперь мы хотим изменить все имена узлов, которые содержат '@'
. С tree.find_elements
мы получаем доступ ко всем узлам. Некоторые узлы не имеют имени, а некоторые могут не содержать '@'
. Поэтому, чтобы быть особенно осторожным, мы сначала проверяем if n.name and '@' in n.name
. Только тогда мы разделяем имя каждого узла на '@'
и берем только первую его часть (индекс 0): n.name = n.name.split('@')[0]
Чтобы воссоздать начальное строковое представление, мы используем Phylo.write
:
out = io.StringIO()
Phylo.write(tree, out, "newick")
print(out.getvalue())
Опять же, write
хочет получить аргумент файла - если мы просто хотим получить строку, мы можем снова использовать объект StringIO
.
Full код:
import io
from Bio import Phylo
if __name__ == '__main__':
s = '(Esy@ESY15_g64743_DN3_SP7_c0:0.0726396855636,Aar@AA_maker7399_1:0.137507902808,((Spa@Tp2g18720:0.0318934795022,Cpl@CP2_g48793_DN3_SP8_c:0.0273465005242):9.05326020871e-05,(((Bst@Bostr_13083s0053_1:0.0332592496158,((Aly@AL8G21130_t1:0.0328569260951,Ath@AT5G48370_1:0.0391706378372):0.0205924636564,(Chi@CARHR183840_1:0.0954469923893,Cru@Carubv10026342m:0.0570981548016):0.00998579652059):0.0150356382287):0.0340484449097,(((Hco@scaff1034_g23864_DN3_SP8_c_TE35_CDS100:0.00823215335663,Hlo@DN13684_c0_g1_i1_p1:0.0085462978729):0.0144626717872,Hla@DN22821_c0_g1_i1_p1:0.0225079453622):0.0206478928557,Hse@DN23412_c0_g1_i3_p1:0.048590776459):0.0372829371381):0.00859075940423,(Esa@Thhalv10004228m:0.0378509854703,Aal@Aa_G102140_t1:0.0712272454125):1.00000050003e-06):0.00328120860999):0.0129090235079):0.0129090235079;'
tree = Phylo.read(io.StringIO(s), 'newick')
print(' before '.center(20, '='))
print(tree)
for n in tree.find_elements():
if n.name and '@' in n.name:
n.name = n.name.split('@')[0]
print(' result '.center(20, '='))
out = io.StringIO()
Phylo.write(tree, out, "newick")
print(out.getvalue())
Вывод:
====== before ======
Tree(rooted=False, weight=1.0)
Clade(branch_length=0.0129090235079)
Clade(branch_length=0.0726396855636, name='Esy@ESY15_g64743_DN3_SP7_c0')
Clade(branch_length=0.137507902808, name='Aar@AA_maker7399_1')
Clade(branch_length=0.0129090235079)
Clade(branch_length=9.05326020871e-05)
Clade(branch_length=0.0318934795022, name='Spa@Tp2g18720')
Clade(branch_length=0.0273465005242, name='Cpl@CP2_g48793_DN3_SP8_c')
Clade(branch_length=0.00328120860999)
Clade(branch_length=0.00859075940423)
Clade(branch_length=0.0340484449097)
Clade(branch_length=0.0332592496158, name='Bst@Bostr_13083s0053_1')
Clade(branch_length=0.0150356382287)
Clade(branch_length=0.0205924636564)
Clade(branch_length=0.0328569260951, name='Aly@AL8G21130_t1')
Clade(branch_length=0.0391706378372, name='Ath@AT5G48370_1')
Clade(branch_length=0.00998579652059)
Clade(branch_length=0.0954469923893, name='Chi@CARHR183840_1')
Clade(branch_length=0.0570981548016, name='Cru@Carubv10026342m')
Clade(branch_length=0.0372829371381)
Clade(branch_length=0.0206478928557)
Clade(branch_length=0.0144626717872)
Clade(branch_length=0.00823215335663, name='Hco@scaff1034_g23864_DN3_SP8_c_TE35_CDS100')
Clade(branch_length=0.0085462978729, name='Hlo@DN13684_c0_g1_i1_p1')
Clade(branch_length=0.0225079453622, name='Hla@DN22821_c0_g1_i1_p1')
Clade(branch_length=0.048590776459, name='Hse@DN23412_c0_g1_i3_p1')
Clade(branch_length=1.00000050003e-06)
Clade(branch_length=0.0378509854703, name='Esa@Thhalv10004228m')
Clade(branch_length=0.0712272454125, name='Aal@Aa_G102140_t1')
==== result =====
(Esy:0.07264,Aar:0.13751,((Spa:0.03189,Cpl:0.02735):0.00009,(((Bst:0.03326,((Aly:0.03286,Ath:0.03917):0.02059,(Chi:0.09545,Cru:0.05710):0.00999):0.01504):0.03405,(((Hco:0.00823,Hlo:0.00855):0.01446,Hla:0.02251):0.02065,Hse:0.04859):0.03728):0.00859,(Esa:0.03785,Aal:0.07123):0.00000):0.00328):0.01291):0.01291;
Формат Phylo по умолчанию использует меньше цифр, чем в исходном дереве. Чтобы сохранить числа без изменений, просто переопределите строку формата длины ветви с помощью «% s»:
Phylo.write(tree, out, "newick", format_branch_length="%s")