Mutect2默认过滤规则解析:硬过滤参数详解
说实话,我刚接触Mutect2那会儿,看到一堆过滤参数简直是头皮发麻。什么FS、QD、MQ……每个缩写背后都藏着一套统计逻辑。我习惯把硬过滤比作「变异位点的安检门」——只有通过所有关卡,你才敢把这个位点放进下游分析。
为什么要搞这么复杂?因为你想想看,测序数据太脏了。PCR重复、链偏好、比对错误、同源区域……这些噪声都会伪装成「看起来很真的变异」。硬过滤就是一把快刀,先把明显靠不住的砍掉,剩下的再交给更精细的模型(比如FilterMutectCalls)。
硬过滤参数全家桶
Mutect2在Calling阶段会为每个变异位点计算一组统计量。默认的硬过滤规则写在GATK的源码里,直接在VCF的FILTER字段打标记。下面这几个参数是核心中的核心:
| 参数 | 全称 | 默认阈值 | 它想表达什么 |
|---|---|---|---|
| FS | Fisher Strand | > 30.0 | 链偏好的证据强度(p值取-log10) |
| QD | QualByDepth | < 2.0 | 质量值除以深度,类似于信噪比 |
| MQ | RMSMappingQuality | < 40.0 | 支持该变异的reads的平均比对质量 |
| MQRankSum | MappingQualityRankSumTest | < -12.5 | 变异位点内外reads的比对质量分布差异 |
| ReadPosRankSum | ReadPosRankSumTest | < -8.0 | 变异位点内外reads的位置分布差异 |
这些都是RNA-seq或肿瘤体细胞突变中常见的「噪声指标」。FS太高说明链偏好严重,可能是个假阳性;QD太低说明质量虽高但深度不足,可能是随机错误;MQ低于40说明比对质量差,可能来自重复区域或同源序列。
参数之间的「互相牵制」
单独看每个参数没问题,但组合起来就有意思了。举个例子,FS高但QD也高的位点,可能是真实的链偏好还是假阳性?我个人习惯先看QD:如果QD > 5.0,即使FS到50,我也倾向于保留,因为深度足够大时链偏好会被稀释。反过来,QD < 1.0的位点,就算FS只有5,我也直接过滤掉——因为信噪比太差。
这里有一张我常用的决策逻辑图,帮你理清思路:
看到没有,这是一个串联的安检流程。每个位点必须连续通过所有关卡。不过在实际项目中,我经常碰到FS很高但QD也很高的位点——比如肿瘤扩增子测序的高深度区域。默认阈值会把这些位点过滤掉,但我通过调整FS到50,就保留了这些可能是真的突变。
直接在命令行里改阈值
你不需要等FilterMutectCalls才改阈值。在Mutect2运行的时候就能指定硬过滤规则。看一个例子:
gatk Mutect2 \
-R hg38.fa \
-I tumor.bam \
-I normal.bam \
-O raw.vcf \
--max-reads-per-alignment-start 6 \
--f1r2-tar-gz f1r2.tar.gz \
--germline-resource af-only-gnomad.vcf \
--custom-filter "FS > 30.0" \
--custom-filter "QD < 2.0" \
--custom-filter "MQ < 40.0" \
--custom-filter "MQRankSum < -12.5" \
--custom-filter "ReadPosRankSum < -8.0"
注意这些--custom-filter参数写的是过滤条件,而不是通过条件。如果变异位点满足其中任意一条,它就会被标记为custom_filter。默认的硬过滤名字叫hard_filtered,但你用--custom-filter-name可以自定义。
避坑指南:那些年我掉过的坑
- 坑1: 默认阈值对低深度数据太激进。我做过一个cfDNA项目,平均深度只有15x。QD的2.0阈值把80%的位点都过滤了。后来我把QD降到1.0,同时把FS放宽到50,召回率就正常了。
- 坑2: FS和QD的交互效应被忽略。你光看FS高就过滤,但QD如果>5,那个高FS可能是PCR偏好引起的,不是真正的链偏好。我的方案是:先过滤QD<2.0的,再过滤FS>60的。
- 坑3: MQRankSum和ReadPosRankSum对插入/缺失更敏感。有时候SNP的RankSum看起来正常,但indel的RankSum特别差。我在某个项目里把indel的ReadPosRankSum阈值从-8.0改到-10.0,假阳性就降了不少。
# 默认版本
gatk Mutect2 ... -O default.vcf
# 宽松版本
gatk Mutect2 ... -O relaxed.vcf \
--custom-filter "QD < 1.5" \
--custom-filter "FS > 50.0"
然后grep -v "^#" default.vcf | wc -l看看过滤了多少。
我一直觉得硬过滤是整套流程里最「经验主义」的一环。你调的阈值必须贴合你的数据特征——测序平台、覆盖深度、样本类型、肿瘤纯度,这些都会影响最优点。没有万能配方,只有反复验证。