news 2026/9/11 17:49:21

如何把 ETE 3 系统发育分析代码迁移到 ETE 4

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何把 ETE 3 系统发育分析代码迁移到 ETE 4

如何把 ETE 3 系统发育分析代码迁移到 ETE 4

【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000+ scientists worldwide. 165 ready-to-use validated skills plus 100+ scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills

ETE 4 是一次破坏性 API 修订,不是简单的换导入名升级:包名从ete3变为ete4,Newick 选择的format=参数改为parser=,节点元数据从features改为propsiter_leaves()一类方法改为返回迭代器的leaves()。本文基于 scientific-agent-skills 仓库中 etetoolkit 技能的迁移参考文档(migration-ete3-to-ete4.md),目标版本为ETE 4.4.0(2025 年 9 月 3 日发布;ETE 4.0.0 与 4.1.1 于 2025 年 3 月 28 日发布,4.1.1 起 ETE 4 标记为 out of beta 并上架 PyPI)。按文操作后,你能把一套基于ete3的旧分析代码改写成在ete4上运行、且科学输出可核对的新代码。

准备:安装并确认 ETE 4.4.0 环境

在开始改代码之前,先按文档固定版本安装基础包:

uv pip install "ete4==4.4.0"

如果旧项目确实还需要 ETE 3,文档建议只在必要时让两个 API 并存,并且不要在同一条代码路径里隐式混用两者——要明确命名兼容边界并分别测试。

安装完成后确认当前环境:

uv run --with "ete4==4.4.0" python -c "import ete4; print(ete4.__version__)"

打印4.4.0说明隔离运行环境里的包版本符合迁移文档的验证基线。若工作流还涉及渲染,按需只加对应 extra:SmartView 静态 PNG 截图需要ete4[render-sm],Qt 树视图(矢量 PDF/SVG)需要ete4[treeview],命令形如uv pip install "ete4[treeview]==4.4.0"

迁移第一步:机械检索 ETE 3 符号

文档给出了一个可直接用于搜索旧代码的模式清单。先在代码库中检索以下字符串,定位所有需要改写的调用点:

from ete3 TreeNode format= features= feature= attributes= attribute= add_feature add_features .features get_ascii get_tree_root get_common_ancestor get_leaves iter_leaves get_descendants iter_descendants get_leaf_names get_leaves_by_name convert_to_ultrametric topology_only is_leaf() is_root() & " ClusterTree TreeStyle NodeStyle

命中之后,对照下面的逐项映射替换;替换完成后再检查 Newick 解析器、迭代器消费方式、属性导出语义、可视化布局这几类容易漏掉的点。

逐项替换 API 变更

导入与类名

# ETE 3 from ete3 import NCBITaxa, PhyloTree, Tree
# ETE 4 from ete4 import GTDBTaxa, NCBITaxa, PhyloTree, Tree

ETE 3 中TreeNodeTree是等价类,ETE 4 只用Tree。可视化相关导入也搬了家:

# ETE 3 from ete3 import NodeStyle, TextFace, TreeStyle # ETE 4 from ete4.treeview import NodeStyle, TextFace, TreeStyle

如果代码用到 Web 可视化:

from ete4.smartview import Layout, PropFace, TextFace

注意 SmartView 和 treeview 的TextFace是不同类型,两套布局字典与 face 互不兼容,迁移时不能交叉使用。

文件读取:路径字符串不再可靠

ETE 3 允许直接传路径:

tree = Tree("tree.nw", format=1)

ETE 4 的约定是:Newick 文本用字符串,文件输入传打开的文件对象:

from pathlib import Path with Path("tree.nw").open(encoding="utf-8") as handle: tree = Tree(handle, parser=1)

ETE 4.4.0 内部仍保留路径字符串启发式,但文档明确说依赖它与文档化契约冲突、会让输入行为变得含糊,所以迁移时应全部改成打开文件对象的方式。

带属性的新节点构造同样变了:

# ETE 3 tree = Tree(name="root", dist=0, support=1) # ETE 4 tree = Tree({"name": "root", "dist": 0, "support": 1})

属性模型:features 到 props

ETE 3 要求 name、distance、support 有默认值;ETE 4 中这些属性可以缺席,便捷访问器可能返回None。读写元数据的方法名全部换掉:

# ETE 3 node.add_feature("habitat", "marine") node.add_features(group="case", score=0.8) print(node.features) # ETE 4 node.add_prop("habitat", "marine") node.add_props(group="case", score=0.8) print(node.props)

参数重命名规律:feature/featuresattribute/attributesproperty/properties统一映射到prop/props。原来用hasattr(node, "x")判断自定义元数据的写法,改为:

if "x" in node.props: value = node.props["x"]

查找、谓词与迭代器重命名

查找和谓词的对照:

ETE 3ETE 4
tree & "A"tree["A"]
tree.get_tree_root()tree.root
node.is_leaf()node.is_leaf
node.is_root()node.is_root
tree.get_common_ancestor(a, b)tree.common_ancestor(a, b)
node.get_ancestors()node.ancestors()
tree.get_leaves_by_name("A")tree.search_leaves_by_name("A")

注意is_leafis_root在 ETE 4 中是属性,不带括号调用。

迭代器重命名:

ETE 3ETE 4
get_leaves()/iter_leaves()leaves()
get_descendants()/iter_descendants()descendants()
get_edges()/iter_edges()edges()
get_leaf_names()leaf_names()
get_ancestors()ancestors()

一个容易踩的坑:ETE 4 的这些方法返回的是迭代器len(tree.leaves())或对结果下标取值都会失败,必须先转成列表:

leaves = list(tree.leaves()) names = list(tree.leaf_names())

按名查找两种实现下都返回第一个匹配;当节点名是身份标识时,要自行校验唯一性。

Newick 读写:format= 到 parser=

# ETE 3 tree = Tree(newick, format=1) newick = tree.write(format=1) # ETE 4 tree = Tree(newick, parser=1) newick = tree.write(parser=1)

解析器也支持"name""support"这类命名别名。

ASCII 输出改为to_str()

# ETE 3 print(tree.get_ascii(show_internal=True)) # ETE 4 print(tree.to_str(show_internal=True, props=["name", "dist"]))

扩展属性语义是反的,务必单独检查。ETE 3 里features=[]表示导出所有可用属性;ETE 4 中:

tree.write(props=[]) # 不导出任何扩展属性 tree.write(props=["species", "host"]) # 只导出选定属性 tree.write(props=None) # 导出全部可用属性

文档强调对外输出时应使用显式的选定属性列表。另外write()要使用关键字参数:ETE 4 中它的第一个位置参数是outfile,不再是 ETE 3 的属性选择。

自定义格式化器的写法也变了:

# ETE 3 newick = tree.write( format=1, dist_formatter="%0.1f", name_formatter="TEST-%s", ) # ETE 4 from ete4.parser import newick parser = newick.make_parser( 1, dist="%0.1f", name="TEST-%s", ) text = tree.write(parser=parser)

距离、拓扑与 Robinson-Foulds

ETE 3ETE 4
A.get_distance(B)tree.get_distance(A, B)
topology_only=Truetopological=True
convert_to_ultrametric()to_ultrametric()
resolve_polytomy(recursive=True)resolve_polytomy(descendants=True)

中点外群的旧两步写法(get_midpoint_outgroup()+set_outgroup())仍然有效,ETE 4 另加了直接写法tree.set_midpoint_outgroup()。距离矩阵方面,ETE 4.4.0 新增distance_matrix(),文档说明它取代cophenetic_matrix(),新代码用前者。

robinson_foulds()的返回值从 5 个变成 7 个,只解包 5 个值的旧代码必须更新:

( rf, max_rf, common, edges_self, edges_other, discarded_self, discarded_other, ) = tree.robinson_foulds(other)

参数名也从 feature 系改成了prop_t1prop_t2系。

随机树生成

# ETE 3 tree.populate( size, names_library=names, random_branches=True, dist_range=(0, 1), ) # ETE 4 import random tree.populate( size, names=names, model="yule", dist_fn=random.random, support_fn=lambda: 1, )

如果生成的拓扑或距离需要可复现,要自己设置随机种子。

PhyloTree 基因树分析的陷阱

PhyloTree的核心方法保留了,但要用 ETE 4 的属性和迭代器语法:

from ete4 import PhyloTree tree = PhyloTree( "((Hsa|g1,Ptr|g1),Mmu|g1);", sp_naming_function=lambda name: name.split("|", 1)[0], ) events = tree.get_descendant_evol_events(sos_thr=0.0) for leaf in tree.leaves(): print(leaf.name, leaf.species)

三个具体要点:

  1. 物种感知方法要显式传入sp_naming_function。文档指出当前源码的默认值是None,尽管旧文档描述过"自动取前三位"的规则,不能依赖它。
  2. 物种重叠事件检测要求 rooted 且完全二歧化的基因树。
  3. 不要把物种树传给get_descendant_evol_events()——ETE 4.4.0 中它的签名只接受sos_thr。做比对时用:
reconciled_tree, events = gene_tree.reconcile(species_tree)

事件检测后,读取node.props.get("evoltype")来检查节点事件类型,不要再依赖 ETE 3 的 feature 辅助方法。

分类数据库:存储位置与 GTDB

ETE 3 时代的示例通常指~/.etetoolkit/taxa.sqlite;ETE 4 把分类数据存到:

~/.local/share/ete/

文档把当前文档中约 600 MB(NCBI)与 72 MB(GTDB)的数字定性为本地首次使用的占用估算,而不是压缩后的网络下载体积——归档大小随版本变化,解析后的 SQLite 和临时转换文件还需要额外空间,磁盘预算要留足。

ETE 4 新增了一等公民式的 GTDB 支持:

from ete4 import GTDBTaxa

NCBI 数字 TaxID 与 GTDB 字符串标识符不可互换,混用会出错。

可视化迁移

SmartView 是 ETE 4 的首选路径:

from ete4 import Tree tree = Tree("((A,B),C);") tree.explore() tree.render_sm("tree.png")

自定义 SmartView 布局:

from ete4.smartview import Layout, PropFace def draw_node(node): if node.is_leaf: return PropFace("name", position="right") layout = Layout("labels", draw_node=draw_node) tree.explore(layouts=[layout])

保留 Qt treeview 的旧代码只需要改导入位置(from ete4.treeview import NodeStyle, TreeStyle),并按前面说明安装ete4[treeview]extra。文档给出的分工是:需要矢量 PDF/SVG 时 Qt treeview 仍是选项;SmartView 的render_sm()在 ETE 4.4.0 中产出的是 PNG 截图数据。

ClusterTree 在 ETE 4 中不存在

这是迁移中的"不支持项",旧代码如果依赖它必须移除或重做:

# ETE 3 from ete3 import ClusterTree
# ETE 4.4.0 下的实际报错 ImportError: cannot import name 'ClusterTree' from 'ete4'

文档明确不要把ClusterTree、linked matrix profiles、silhouette、Dunn 方法描述为 ETE 4 的能力:这些计算应改用受维护的聚类库,树拓扑展示用普通 ETETree即可。

ete4 compare命令行的已知问题

文档记录:ETE 4.4.0 自带的ete4 compare命令内部仍调用Tree(..., format=...),会因该关键字被移除而失败。替代方案是用Tree.robinson_foulds()、唯一标签场景下的Tree.compare(),或者本技能自带的scripts/tree_operations.py compare辅助命令。同时避免走Tree.compare(has_duplications=True)路径——上游源码把该分支标记为可能损坏。

一个完整的移植对照

文档给出的端到端示例,左边是典型 ETE 3 写法,右边是等价 ETE 4 代码:

# ETE 3 from ete3 import Tree tree = Tree("tree.nw", format=1) node = tree & "A" node.add_feature("group", "case") for leaf in tree.iter_leaves(): if leaf.is_leaf(): print(leaf.name) tree.write( outfile="out.nhx", format=1, features=["group"], )
# ETE 4 from pathlib import Path from ete4 import Tree with Path("tree.nw").open(encoding="utf-8") as handle: tree = Tree(handle, parser=1) node = tree["A"] node.add_prop("group", "case") for leaf in tree.leaves(): if leaf.is_leaf: print(leaf.name) tree.write( outfile="out.nhx", parser=1, props=["group"], )

这段示例覆盖了迁移中最高频的组合:文件对象读入、parser=、下标查找、add_prop、迭代器、属性导出列表。

验证迁移结果

文档给出了一段验证代码,用于确认环境版本和新语法都生效:

import ete4 from ete4 import Tree assert ete4.__version__ == "4.4.0" tree = Tree("((A:1,B:1)95:0.2,C:1);", parser="support") assert list(tree.leaf_names()) == ["A", "B", "C"] assert tree["A"].is_leaf round_trip = tree.write(parser="support", props=[]) assert round_trip == "((A:1,B:1)95:0.2,C:1);"

其中字符串((A:1,B:1)95:0.2,C:1);同时作为输入和期望回写值,是文档示例里带支持值、分支长度的完整 Newick,parser="support"保证支持值95按支持值而非节点名解析;这段代码本身即是对解析器选择、props=[](不导出扩展属性)语义和迭代器用法的联合验证。

命令行侧可以用本技能目录skills/etetoolkit/下的脚本做二次核对。在该目录下执行(tree.nw换成你的实际树文件):

uv run --with "ete4==4.4.0" python scripts/tree_operations.py \ stats tree.nw --parser 1 uv run --with "ete4==4.4.0" python scripts/tree_operations.py \ ascii tree.nw --parser 1 --props name,dist uv run --with "ete4==4.4.0" python scripts/tree_operations.py \ compare tree_a.nw tree_b.nw

compare子命令内部走的是 ETE 4 的robinson_foulds()七元组解包,并会对无名称或重复的叶节点名直接报错拒绝,而不是静默产出部分结果,适合用来验证旧的两棵树比较流程改写后行为一致。

最后按文档的收尾要求执行:用带节点名、支持值、分支长度、NHX 属性、重复叶节点和多歧化的代表性树做测试,并且比较的是科学输出,而不只是代码能否跑通

限制与后续

  • 迁移基线是 ETE 4.4.0;文档中sp_naming_function默认值、get_descendant_evol_events()签名等结论均针对 4.4.0,升级其他版本前需重新核对。
  • ClusterTree相关能力(聚类轮廓系数、Dunn 方法等)没有 ETE 4 等价物,必须换库实现。
  • ete4 compareTree.compare(has_duplications=True)在 4.4.0 下不可用,树比较走robinson_foulds()或 tree_operations.py。
  • 分类数据库首次更新会占用可观磁盘空间,详见 taxonomy.md;解析器选择与核心 API 的完整对照见 api_reference.md。

【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000+ scientists worldwide. 165 ready-to-use validated skills plus 100+ scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 17:45:45

Linux行业盒子芯片选型:RK3588、S922X与S905X3实战决策指南

1. 项目概述:为什么“行业定制盒子”的芯片选型,比你想象中更像一场精密的工业手术 最近半年,我跑了七家做Linux行业定制盒子的源头工厂,从深圳华强北的方案商小作坊,到东莞松山湖的ODM大厂产线,再到浙江慈…

作者头像 李华
网站建设 2026/9/11 17:44:59

基于YOLOv8的农田虫情测报灯系统:目标检测与部署实践

简介:面向毕业设计与课程设计的基于YOLOv8的农田智能虫情测报灯害虫种类识别系统,完整覆盖数据准备、模型训练、视频检测与可视化界面展示全流程,旨在解决农田虫害监测场景中的目标检测需求;项目代码经测试可运行,适合…

作者头像 李华
网站建设 2026/9/11 17:41:45

丝状真菌的制剂加工——为什么它们“不耐加工“?

一、从发酵罐到制剂车间:一个被低估的"断点"一个事实被行业低估了:丝状真菌的产业化瓶颈,不只在发酵端,更在制剂端。前四篇文章分别聊了开篇、菌种制备、液体发酵、固体发酵,把"怎么把菌养好、把孢子产…

作者头像 李华
网站建设 2026/9/11 17:41:17

装备制造企业非标定制订单多,生产进度该如何透明化跟踪?

本文要点:本文针对装备制造行业"非标定制订单多、设计变更频繁、交期长"带来的生产进度跟踪难题,盘点轻流及市面多款工具在订单进度可视化、变更协同方面的能力差异。文章覆盖从中小型非标装配厂到集团型装备企业的不同场景,帮助该…

作者头像 李华