如何用 resolve_lineage 脚本验证 Pango 谱系名称是否仍有效或已被重命名
【免费下载链接】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
在病原基因组监测里,Pango 谱系名不是稳定的标识符:名称持续被新命名,也会在被使用多年后被撤回(withdrawn)或重新命名(redesignated)。scientific-agent-skills 仓库中的pathogen-variant-surveillance技能自带resolve_lineage.py脚本,把一批谱系名对到实时命名数据上,逐个回答:这个名字现在还存在吗、展开成什么、从哪来、当前有多少条序列仍携带它。
本文的任务就是:在你引用、查询或写入论文谱系清单之前,用这个脚本核对每个名字的有效性,并让退出码直接充当自动化的"门槛"。
前提条件
脚本 resolve_lineage.py 位于技能目录的scripts/子目录下,其运行要求(来自 SKILL.md 的兼容性声明):
- Python 3.11+,仅用标准库,无需安装第三方包,也不需要 API key;
- 需要访问公开 GenSpectrum LAPIS 实例(lapis.cov-spectrum.org、lapis.genspectrum.org、lapis.pathoplexus.org)以及
raw.githubusercontent.com(运行时从 pango-designation 拉取alias_key.json和lineage_notes.txt)。
如果 pango-designation 不可达,脚本不会崩溃:它会向 stderr 打印warning: pango-designation unreachable: ...,此时名称状态可能退化为unverified(两个命名来源都没拿到),需要按后文的判断方法重新运行。
运行检查:一条命令核对一批名字
在仓库根目录下进入脚本目录,把要核对的名字作为位置参数一次性传入:
cd skills/pathogen-variant-surveillance/scripts python3 resolve_lineage.py XFG.23.1.3 PQ.17 PC.2 NOTALINEAGE下面是 SKILL.md 中给出的文档示例输出(每行还会引用该谱系所属的 lineage proposal,示例中detail列有删节):
query status unaliased parent recombinant_of descendants sequences detail XFG.23.1.3 current XFG.23.1.3 XFG.23.1 LF.7+LP.8.1.2 6 317 S:A1174V, on C29137T branch PQ.17 current XDV.1.5.1.1.8.1.17 NB.1.8.1 23 931 Alias of XDV.1.5.1.1.8.1.17 PC.2 withdrawn B.1.1.529.2.86.1.1.16.1.7.2.1.2 LF.7.2.1 4 25 now LF.7.9; Redesignated as LF.7.9 NOTALINEAGE unknown NOTALINEAGE 0 n/a no such name in the live nomenclature逐列判断这个名字的状态
表格列固定为query、status、unaliased、parent、recombinant_of、descendants、sequences、detail。判断主要看三列:
status是核心结论,取自实时的lineage_notes.txt与实例的谱系定义文件,取值见 脚本源码:current:名字仍是有效命名(notes 标记为designated,或存在于谱系定义中);withdrawn:名字已被撤回或重新命名。如果 notes 里写了Redesignated as X,detail列会被改写成now X; ...的形式(示例中PC.2的now LF.7.9)——这就是"它现在应该叫什么";unknown:两个命名来源里都没有这个名字,detail会写no such name in the live nomenclature for this instance;unverified:两个来源都未能获取,状态无法判定,需要看 stderr 的 warning 后重跑。
unaliased用实时的alias_key.json把别名展开到完整路径(如PQ.17→XDV.1.5.1.1.8.1.17)。这个映射无法靠推理得出,只能查文件,所以别凭记忆展开。recombinant_of只在重命名谱系上有值(如XFG显示LF.7+LP.8.1.2)。LAPIS 自己的谱系定义把所有X*谱系都当根节点处理,重组父本只记录在alias_key.json里,脚本已经替你合并了两个来源;parent列则是谱系定义里直接的上游谱系。sequences是该名字的序列计数。在带谱系索引的列上(如 SARS-CoV-2 的pangoLineage),脚本实际按名字*查询,即含所有后代;stderr 的 provenance 里会有一行# 'sequences' counts the lineage and its descendants提醒这一点。名字无效时索引列会直接拒绝查询,该列显示n/a;其他请求错误显示error。
输入大小写不必纠结:脚本会把字母前缀统一转成大写(xfg.1.1按XFG.1.1处理),但query列保留你输入的原样。
用退出码把谱系清单挡在报错之外
脚本的退出码语义明确(见 脚本 docstring 与 SKILL.md):任何一个名字是withdrawn或unknown,退出码就是 1;全部通过则为 0。所以它可以直接卡在流水线或检查脚本里:
python3 resolve_lineage.py XFG.23.1.3 PQ.17 if [ $? -eq 0 ]; then echo "lineage list OK"; else echo "lineage list contains stale names"; fi这是 SKILL.md 明确给出的用途:"gates a manuscript's lineage list"——论文定稿前跑一遍,有陈旧名字就非零退出。
需要把结果落盘时,用--format tsv(也有table、json可选)重定向 stdout,provenance 信息始终走 stderr,两者不会互相污染:
python3 resolve_lineage.py PC.2 --format tsv > pc2.tsv把来源信息一起记下来
非 JSON 格式下,stderr 会追加 provenance 段:实例名、数据版本(data version)、实际选用的谱系列(如lineage column pangoLineage with a lineage index)、从 pango-designation 读到多少名称、其中多少已撤回,以及两个源文件的 git blob SHA。lapis-api.md 给出的文档示例:
# source blobs lineage_notes.txt@b63582d49216 alias_key.json@0deb39eeac80该文档的建议是:把这行 SHA 和dataVersion一起记录。pango-designation 的拉取是故意不固定版本的(固定到某个 tag 会漏掉新的撤回,那正是这个脚本要抓的东西);审计性来自"记录读到了哪个版本",而不是冻结来源。
换实例:H5N1 clade 与自定义 LAPIS 地址
--instance取注册表名称,默认sars-cov-2(即 lapis.cov-spectrum.org 的 open 实例,谱系列pangoLineage,有谱系索引)。脚本 docstring 中给出的 H5N1 用法:
python3 resolve_lineage.py 2.3.4.4b --instance h5n1注意两点边界(来自 lineage-nomenclature.md 与 SKILL.md):
- H5N1 的谱系列是普通字符串列
clade,没有谱系索引:不支持名字*后代展开,sequences列只统计精确匹配;clade=2.3.4.4b*在这种列上会返回 0 而不是展开后代。 - 遇到未见过的新实例,先不带
--lineage-field跑一次:脚本会打印它没有选中的其他谱系候选列(# other lineage-like columns here: ... (select one with --lineage-field)),再决定是否用--lineage-field覆盖自动选择。
--base-url可以指向任意 LAPIS 部署,替代注册表。lapis-api.md 明确提醒:只把--base-url指向你信任的部署,因为实例返回的字段名、标签和错误detail文本会被原样打印。
两个实用开关:--descendants把descendants列从计数改成逐个列出所有后代名字;--no-counts跳过每名的计数请求(每个名字少一次查询)。
容易误判的两种情况
withdrawn但序列仍在用旧名。文档中反复出现的实例是PC.2:上游已改名为LF.7.9,但实例里的分配管线滞后于命名变更,仍有 25 条序列携带PC.2标签。两个事实同时成立:改名是事实,计数也真实。正确做法是把重新命名和计数一起报告,而不是二选一。- 不同实例上"找不到"的表现不同。索引列(SARS-CoV-2 的
pangoLineage)会对无效名字直接报 400 拒绝查询;无索引列则安静地返回 0,看起来像个"该谱系不存在"的发现。所以引用"某谱系计数为 0"这类结论之前,先用本脚本确认名字本身是有效的。
当前lineage_notes.txt约有 6,230 个名称,其中 294 个处于撤回或重新命名状态(lineage-nomenclature.md,2026-07-27 实测值,会随时间变化)——这就是为什么文档把"凭记忆写谱系名"列为禁止项。
可选:离线核对脚本行为
仓库自带 test_scripts.py,默认测试全部 stub 掉网络调用,可离线运行:
uv run --with pytest python -m pytest tests/pathogen-variant-surveillance -q需要真实 API 冒烟检查时,设置环境变量再跑同一命令(会访问线上 LAPIS 实例):
LAPIS_LIVE_TESTS=1 uv run --with pytest python -m pytest tests/pathogen-variant-surveillance -q测试覆盖withdrawn名字非零退出、current名字零退出、大小写归一化等行为,与正文所述一致。
边界与下一步
resolve_lineage.py只做名字核验:它不回答"这个谱系占多大比例"或"它的突变谱是什么"。名字核验通过后,同一scripts/目录下的lineage_prevalence.py、mutation_profile.py、reporting_lag.py分别处理流行度与增长、突变画像和报告滞后问题(见 SKILL.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),仅供参考