SplitAligner:从头到尾走一遍
把一棵物种树和一组基因树,变成一张枝坐标矩阵——每根枝要么携带数值,要么带有明确的缺失状态:结构性、融合相关、拓扑导致,或残余 NA。本教程使用随附的示例,你可以在自己的机器上复现每一份输出。
SplitAligner.pl 即可。下面的命令对应 examples/run.sh 中的实际步骤。一根枝,就是它所作的那个划分
SplitAligner 识别一根枝,靠的不是它画在哪里、也不是节点顺序,而是它在类群上诱导出的二分划分(split)。对于只采样了部分类群 Tg 的基因 g,把物种树的每根枝 b 投影到实际存在的类群上:
在与物种树限制拓扑一致的基准层中,两根未被删除的原始枝投影划分相同,当且仅当它们落到同一条约化枝上。这并不是说两根原始枝变成了同一根;而是它们在该基因的类群集合下无法再独立区分,形成融合。若投影后有一侧为空,则是结构性缺失。对于经验 free 拓扑基因树,SplitAligner 还会另行判断每个可独立观测的投影划分是否被找回。
显示根不是坐标。SplitAligner 的生物学坐标是规范化无根 split,而不是绘制出来的根位置、内部节点编号、遍历顺序或子节点顺序。若两个 Newick 表示编码的是同一个加权无根 split 对象,那么仅改变显示根或序列化方式,并不会改变底层的生物学 split 身份。
便于阅读的 B 别名是序列化局部的,在独立序列化的物种树之间可能不同。比较独立表示时,权威身份是规范化 split key,而不是 B 编号本身。
在需要方向或祖先关系的分析中,生根仍然可以承载生物学含义;它只是不定义 SplitAligner 的枝坐标身份。
整个流程有两个模式:matrix 构建坐标系并把所有基因投影上去;finalize 再根据成对证据区分缺失状态。
安装
你需要 Perl 5(macOS 和大多数 Linux 自带)。SplitAligner 只用核心模块——无需安装任何 CPAN 包。
# 克隆仓库 git clone https://github.com/wujiaqi06/SplitAligner cd SplitAligner # 确认可运行(会打印用法说明) perl SplitAligner.pl
安装到此为止。主控脚本是 SplitAligner.pl;各步骤的辅助脚本在 scripts/ 中,会被自动调用。
准备输入
物种树 —— 一棵 Newick 树。允许带枝长和支持度,在基于划分的映射中会被直接忽略。
((A:0.1,B:0.2):0.2,(C:0.1,D:0.1):0.1):0.1;
基因树 —— Newick 格式,一行一条记录,每行以基因标识符开头,紧接着是该基因的树。类群名必须与物种树一致。
GeneA((A:0.1,B:0.2):0.2,(C:0.1,D:0.1):0.1):0.1; GeneB((A:0.2,C:0.1):0.1,(B:0.1,D:0.2):0.1):0.1;
SplitAligner 区分两类基因树输入,通常两者都要提供:
- free —— 每个基因独立推断的树(拓扑可以与物种树不一致);
- fix —— 在物种树拓扑约束下推断的树(只有枝长)。
比较这两者,正是之后区分覆盖度导致的缺失与不一致导致的缺失的关键。
快速开始:示例数据
仓库在 examples/302mammal/ 下附带了一个小示例(free / fix 基因树的子集),用于快速的端到端冒烟测试。在仓库根目录下运行:
bash examples/run.sh toy它会依次运行下面三次程序调用。教程余下部分逐一拆解每一步做了什么、产出什么。
matrix 模式 —— 构建坐标系
每组基因树运行一次 matrix。它给物种树的枝打标签,把所有基因投影上去,写出一张基因 × 枝矩阵。
# 从仓库根目录开始 cd examples/302mammal perl ../../SplitAligner.pl --mode matrix \ --species input/speciesTree302.nwk \ --gene input/free_tree.examples.nwk \ --label free perl ../../SplitAligner.pl --mode matrix \ --species input/speciesTree302.nwk \ --gene input/fix_tree.examples.nwk \ --label fix
主要输出(以 --label 为前缀):
species_tree.splits.txt—— 标准的枝坐标系(物种树骨架上的B1、B2……)。这是所有基因据以度量的共同坐标轴。<label>.matrix_no_fuse.txt—— 仅原始枝。<label>.matrix_with_fuse.txt—— 在此基础上,额外加入显式的融合枝列(如B12|B47),对应因类群修剪而合并的枝。<label>_splits/和<label>_split_branch_label/—— 每个基因的划分表示,及其到骨架的映射。
若枝的投影划分被找回,单元格即为其枝长(数值);否则为 NA——但只是暂时的。为这些 NA 命名,就是下一步。
gene B1 B2 B3 B4 ... A1BG 0.1809315089 NA 0.0047384154 0.0057110032 ... A1CF 0.0376651404 0.0583312140 0.0032591533 ...
finalize 模式 —— 区分缺失状态
把两张矩阵都交给 finalize。它先识别由数值融合坐标解释的原始枝 NA,标为 NA_fuse;再在共享基因上比较 free 与 fix 矩阵,把结构性缺失(NA_struct)与拓扑导致的缺失(NA_topo)分开。若 fix 侧没有可供判断的数值证据,则保留残余 NA。传入 --species_tree 时,还会计算枝级支持度。
perl ../../SplitAligner.pl --mode finalize \ --free free.matrix_with_fuse.txt \ --fix fix.matrix_with_fuse.txt \ --final_label final \ --species_tree species_tree.forSplit.nwk
输出:
final.free.na_classified.txt/final.fix.na_classified.txt—— 完成状态分类的矩阵;fix 侧缺少数值证据时会保留残余NA;<input>.na_fuse.txt—— 融合救回的中间表;final.support_b.txt和species_tree.support_b.nwk—— 枝级支持度(见第 7 步)。
比较只对两个输入都存在的基因有定义;若没有共享基因,SplitAligner 会直接报错停止,而不去猜。
gene B1 B2 B3 ... A1BG 0.1809315089 NA_struct 0.0047384154 ...
读懂各状态
每个基因 × 枝单元格最终都恰好取下列一种值。残余 NA 是有意保留的记账状态:没有 fix 侧数值证据时,不能把它升级为 NA_topo。
| 单元格取值 | 含义 |
|---|---|
| 数值 | Mapped(已映射)。该枝的投影划分在此基因中被观测到;数值即其枝长。 |
| NA_fuse | 类群修剪后,该原始枝不再能被独立观测。一个融合坐标可以带有数值枝长,但该数值不是这根原始枝的独立估计。 |
| NA_struct | 投影后有一侧为空,该枝对此基因没有投影身份、无法评估(覆盖度效应)。 |
| NA_topo | fix 侧有原始枝数值证据,但该投影划分没有在推断出的 free 拓扑树中找回——与拓扑导致的不一致相符。 |
| NA | 残余:当 fix 侧没有可据以判定的数值证据时保留。 |
这些类别对坐标轴构成一个划分——加起来就是整本台账:
一旦 NA 按原因拆开,下游的速率或选择分析就能明确地处理、过滤和审计各类状态,而不是把所有缺失都压成同一个不透明的值。
枝级 Support
当你传入 --species_tree,finalize 会写出 final.support_b.txt:对骨架上的每根枝,给出它在共享基因上、free 树相对 fix 树保留了多少数值证据。
branch_id branch_type n_shared_genes n_fix_non_na n_free_non_na support_percent discordance_percent B1 terminal 5 5 5 100.0000000000 0.0000000000 B2 terminal 5 4 4 100.0000000000 0.0000000000 B3 terminal 5 4 4 100.0000000000 0.0000000000
配套的 species_tree.support_b.nwk 是一棵标准 Newick 树,把每根内部枝的 Support 写在自展值(bootstrap)位置上,可在任意树浏览器(如 FigTree)中打开,直接把一致度映射到拓扑上查看。
扩展到全量
同样这两个模式,在全量规模上照样运行。随附的 preprint 示例使用了 302 种哺乳类、2,275 棵 free 拓扑与 2,275 棵 fix 拓扑基因树:
bash examples/run.sh preprint在共享的一致性子问题上,SplitAligner 的 Support(b) 与 PhyParts 高度一致(299 根内部枝上 Pearson r = 0.99997)。在论文报告的同机测试中,SplitAligner 完整流程用时 9 分 52 秒,PhyParts 的快速一致性设置用时 1 小时 50 分 53 秒——在这套数据上约快 11 倍。这是校准与运行时间比较,并不表示两种方法功能等价。
动手玩 Catnip10
这里只让类群缺失发生,不引入基因树不一致。完整的 B1–B17 坐标轴始终冻结;每次删除后,由图决定的台账会更新为 observed、NA_fuse 或 NA_struct。在这个实验里,NA_topo 始终为零。