3、TMB计算原理与标准化流程归纳总结
TMB(Tumor Mutational Burden)这几年在免疫治疗里热度一直很高。但说实话,很多同行对它的理解还停留在“数一数突变个数”的层面。实际操作起来,坑不少。我最早接触TMB计算是在一个多中心临床项目里,不同site送来的数据、不同panel的覆盖区域、甚至用的参考基因组版本都不一样——那会儿我才意识到:不把流程标准化,出来的TMB根本没法比。
这一节我就把TMB的计算原理掰开了讲,再给出一套我自己项目中沉淀下来的标准化流程。希望能帮你少走弯路。
TMB到底怎么算?
TMB的核心定义很简单:每百万碱基(Mb)中所包含的体细胞突变数目。计算公式就是:
TMB = (体细胞非同义突变个数) / (目标区域有效大小,单位 Mb)
这里有几个关键点我跟你细说一下。
- 体细胞突变:必须是肿瘤组织vs正常对照(或通过算法推断)检出的体细胞变异,胚系突变(germline)要剔除。
- 非同义突变:通常只统计导致氨基酸改变的突变,比如错义、无义、移码、框内插入缺失等。同义突变一般不算,因为不直接影响蛋白。但我遇到过有些商业panel会把同义也算进去,这个做法我不太认同,因为会稀释真正的信号。
- 目标区域有效大小:不是panel的总长度,而是去除低覆盖区域、重复区域、难比对区域后,实际能可靠检出突变的碱基数。这个数字在计算时很关键,不同处理方式会导致TMB结果差几倍。
给一个简单的Python计算脚本示例,帮你理解每一步:
# 示例:从突变列表计算TMB
mutations = load_vcf("tumor_only.vcf")
# 1. 过滤胚系变异(这里简单示例,实际需要数据库或配对)
somatic_muts = [m for m in mutations if m["filter"] == "PASS" and m["is_germline"] is False]
# 2. 只保留非同义突变
nonsynonymous = [m for m in somatic_muts if m["effect"] in ["missense", "nonsense", "frameshift"]]
# 3. 获取目标区域有效大小(单位:Mb)
effective_bases = get_panel_bed("panel.bed") # 返回有效碱基数(如 1.2e6)
effective_mb = effective_bases / 1_000_000
# 4. 计算TMB
tmb = len(nonsynonymous) / effective_mb
print(f"TMB = {tmb:.2f} muts/Mb")
is_germline的判断,没有配对正常组织时,必须依赖公共数据库和严格的等位基因频率阈值(比如gnomAD AF > 0.001 视为可能胚系)。我见过有人直接忽略这一条,结果TMB虚高,导致临床决策失误。
标准化流程有多重要?
你想想看,同一个肿瘤样本,用Illumina平台和MGI平台跑,再用不同生信流程(比如GATK4 vs Sentieon),最后算出来TMB能差多少?我亲身经历过一个案例:同一份FFPE样本在两个中心分别建库、测序、分析,一个TMB=12.3 muts/Mb,一个TMB=8.1 muts/Mb。患者最终能否用免疫治疗,直接看这个数字的。如果没有标准流程,人跟人之间没法交流。
所以我归纳了一套TMB标准化计算流程,分成8个关键步骤:
- 原始数据质控(FASTQ质检,去除低质量reads和接头)
- 比对(BWA-MEM或Sentieon等,推荐GRCh38/hg38)
- 标记重复(Picard MarkDuplicates,处理PCR重复)
- 碱基质量重校准(BQSR,减少系统误差)
- 体细胞突变检出(Mutect2、Strelka2、VarScan2等,建议双调用工具)
- 突变过滤(普通变异过滤 + 胚系过滤 + 假阳性过滤)
- 突变注释(VEP或annovar,获取效用信息)
- TMB计算(按上述公式,使用panel的bed文件)
为了你更直观地看到差异,我把常见参数列了一个表:
| 步骤 | 推荐工具/参数 | 常见坑 |
|---|---|---|
| 比对 | BWA-MEM(-M、-t 4) | 不同版本对比对质量有影响,我统一用0.7.17 |
| 突变检出 | Mutect2(--tumor-lod 6.3) | LOD太低假阳性高,太高会漏掉低频突变 |
| 胚系过滤 | gnomAD AF > 0.0005 排除 | 阈值需要根据panel大小调整,小panel建议更严格 |
| 假阳性过滤 | 链偏好(FS > 60)、映射质量 < 30 | 千万别只用PASS标记,很多假阳性也在PASS里 |
| 区域大小 | 从panel bed文件计算,排除低覆盖(<100×)位点 | 很多人直接拿panel总长度,这是错的 |
我的经验:不要在过滤阶段手软。宁可TMB略低,也比虚高导致假阳性临床决策好。我宁愿多花一天时间做手工QC,也不要直接信任管道的默认输出。
我的标准化建议
上面讲了流程和参数。下面我给出三条我自己项目中反复验证过的硬性建议。
1. 统一背景数据库
胚系过滤强烈依赖公共数据库。我建议使用gnomAD v3.1.2(非癌症人群)作为主数据库,并辅以1000 Genomes和ExAC。不同site必须使用同一版本数据库。曾经有个合作方用了gnomAD v2.1,我们用的v3.1,结果差异很大,最后只好全部重跑。
2. 白名单区域文件
不要用panel厂商给的bed文件直接计算区域大小。那些区域常常包含重复序列、难以比对区域、同源区。我建议自己用全基因组测序的黑色列表(如ENCODE的blacklist),手动剔除。这一步能把TMB结果的波动降低50%以上。
3. 双工具交叉验证
如果条件允许,同时用Mutect2和Strelka2分别跑一遍,只取交集。虽然敏感度会稍有下降,但特异度提升非常明显。在临床项目中,患者分组的准确率比多检出几个突变重要得多。
上面这张图概括了从原始数据到最终TMB报告的全流程。你可以把它贴在工位上,每次跑分析前对照检查是否有遗漏或偏差。