第4章:变异注释基础——ANNOVAR与SnpEff实战
变异注释,说白了就是给VCF文件里的每个突变位点“贴标签”。
你光知道某个位置是A>G没有用——你得知道它是不是导致蛋白质改变、在哪个基因上、在人群里的频率是多少。我刚开始做全外显子分析时,对着几十万个位点一脸茫然。后来才发现,注释这一步没做好,后面所有分析都是白搭。
核心观点:注释不是锦上添花,而是必备步骤。未经注释的VCF就像没有标签的快递——你不知道里面是什么,也不知道该送到哪里。
4.1 注释工具的选择:SnpEff vs ANNOVAR
市面上主流的注释工具有不少,但我用的最多的就是SnpEff和ANNOVAR。它们俩各有侧重,你完全可以搭配使用。
| 特性 | SnpEff | ANNOVAR |
|---|---|---|
| 数据库内置 | 自带预建库,下载即用 | 需手动下载,但可选范围大 |
| 速度 | 快,适合批量处理 | 中等,单体功能细粒度更高 |
| 输出格式 | VCF直接带注释字段 | 输出到表格,可定制列 |
| 功能基因预测 | 支持最多 | 通过插件扩展 |
| 学习曲线 | 平缓,命令行友好 | 参数多,需要花时间理解 |
我个人习惯:小项目用SnpEff快速出结果,大项目或需要精细控制时切到ANNOVAR。其实这两个工具在语法上完全不同,但设计思想是相通的——都是把变异信息和参考数据库做比对。
4.2 SnpEff实战:三分钟上手
SnpEff的核心理念是“一键注释”。它内置了GRCh37、GRCh38等主流基因组的数据库,装好就能跑。
安装很简单,下载JAR包就行:
wget https://snpeff.blob.core.windows.net/versions/snpEff_latest_core.zip
unzip snpEff_latest_core.zip
cd snpEff
然后下载你需要的基因组数据库。我记得第一次跑的时候不知道要提前下载,结果报错说找不到数据库——白白浪费了一个小时。所以一定要先跑这步:
java -jar snpEff.jar download GRCh38.99
下载完成后,注释一条命令就搞定:
java -jar snpEff.jar GRCh38.99 input.vcf > annotated.vcf
输出文件里的INFO字段会多出ANN这个标签。里面包含了变异类型、影响基因、转录本ID、氨基酸变化等信息。举个例子:
ANN=A|missense_variant|MODERATE|TP53|ENSG00000141510|transcript|ENST00000269305|protein_coding|7/11|c.817C>T|p.Arg273Cys|...
这个意思很清楚:位于TP53基因的错义突变,编码蛋白的第273位精氨酸变成了半胱氨酸。我在项目中见过类似的注释几百次,每次看到p.Arg273Cys就知道这个突变很可能跟肿瘤相关。
我的小技巧:SnpEff除了标准注释,还可以做-canon只输出代表性转录本,减少冗余。或者用-hgvs让输出带上HGVS格式命名,方便论文引用。
4.3 ANNOVAR实战:定制化强者
ANNOVAR(也叫annovar)比SnpEff更灵活,但也更粘手。它采用Perl脚本+数据库文件的结构。
下载后需要先配置数据库路径。我个人习惯统一放在一个目录下:
mkdir -p humandb
perl annotate_variation.pl -buildver hg38 -downdb -webfrom annovar refGene humandb/
这一步会下载refGene数据库。ANNOVAR支持超多数据库,比如clinvar_20230501、gnomAD_genome、dbSNP等等。你想想看,这些数据库就能让你一次性拿到人群频率、临床意义、保守性评分等十几个维度的信息。
注释命令是这样的:
table_annovar.pl input.vcf humandb/ -buildver hg38 -out output -remove -protocol refGene,clinvar_20230501,gnomAD_genome -operation g,f,f -nastring . -vcfinput
参数看似复杂,其实拆开看就几条规则:-protocol指定要用的数据库列表,-operation定义每个数据库类型(g表示gene-based,f表示filter-based)。输出会生成一个.hg38_multianno.vcf文件和一个同名的txt表格。
为什么要输出txt表格?因为有时候VCF格式太冗余,用Excel打开看表格更直观。我在项目中经常把ANNOVAR的结果直接导入Python做突变筛选,表格格式方便多了。
请注意:ANNOVAR的数据库版本必须和你的VCF参考基因组版本对应。比如hg38的VCF不能用hg19的数据库。我见过不止一个同事因为数据库版本错乱导致注释结果全空——排查起来真的很痛苦。
4.4 注释结果的解读与筛选
注释完成后,你面对的是一个带有几十个额外字段的VCF。这种信息密度会让初学者头晕。嗯,这里要注意一点——不要试图全部看懂所有字段。我只关注几类核心信息:
- 功能影响:是不是错义、无义、移码?是否有已知的致病性(Pathogenic)?
- 基因名称:落在哪个基因上?是不是已知的疾病相关基因?
- 人群频率:gnomAD中的等位基因频率(MAF)有多高?一般MAF<0.01才值得关注。
- 保守性打分:PhyloP、GERP++、SIFT、Polyphen2这些值是否提示有害?
我在项目中遇到过一个情况:一个看起来很漂亮的错义突变,SIFT和Polyphen2都预测有害,结果一看gnomAD频率是0.5。说白了这就是一个常见多态,根本不可能是致病突变。所以频率信息绝对是筛查的第一道门。
4.5 注释流程的整体脉络
为了让你的理解更清晰,我画了一张流程图。它展示了从原始VCF到知识图谱的全过程,注释这一步是连接原数据和知识的桥梁。
从这个图能看明白:原始VCF同时输入到SnpEff和ANNOVAR,它们各自拉取数据库。注释结果再交到知识图谱模块。两条路径不是互斥的——我经常先用SnpEff快速过一遍,再用ANNOVAR补充精细注释。
4.6 注释后的VCF结构变化
原始VCF的每个位点只有CHROM-POS-ID-REF-ALT-Q-FILTER-INFO这8列。注释后,INFO字段会变得非常夸张:
##INFO=<ID=ANN,Number=.,Type=String,Description="Functional annotations from SnpEff">
##INFO=<ID=LOF,Number=.,Type=String,Description="Predicted loss-of-function effects">
##INFO=<ID=NMD,Number=.,Type=String,Description="Predicted nonsense-mediated decay">
#CHROM POS ID REF ALT QUAL FILTER INFO
chr17 7673803 rs11540652 C T 999 PASS ANN=T|missense_variant|MODERATE|TP53|...;
LOF=(TP53|ENSG00000141510|0.96);NMD=...
为什么要保留这么多层次?因为下游分析针对不同场景需要不同的信息。做基因筛选的人看基因名,做机制研究的人看氨基酸变化,做遗传咨询的人看致病性。
我记得有一次做知识图谱整合,发现ANNOVAR输出的字段名和SnpEff不一致,需要做字段映射。这个映射表的复杂度不低,但这是后面章节要解决的问题。
4.7 避坑指南与常见问题
最后,我把这些年踩过的坑总结一下:
- 注释不全——可能是数据库没更新或路径设置错误。很多新手把数据库下载到别处忘了指定路径。
- 版本冲突——VCF的参考基因组必须和注释工具的基因组版本严格一致。GRCh37和GRCh38的坐标偏移会让你所有结果都错位。
- 速度慢——大规模WGS文件的注释很耗时。我建议用SnpEff的
-lof模式先跑一轮快速筛选,再用ANNOVAR做精细注释。 - 输出文件太大——10万个位点注释后能膨胀到原始文件的3-5倍。磁盘空间自己预估好。
- 多等位基因位点的歧义——在同一个位置出现A>C和A>G两个ALT时,注释工具可能分开也可能合并处理。要注意参数控制。
我曾经遇到的一个坑:用ANNOVAR注释时,-nastring参数设成了空字符串,结果缺失值全变成了空列。导入Python时把表格结构搞乱了,排查了整整一个下午。后来我给这个参数固定设为.,再没出过问题。
说到底,注释这一步就是“增广”你的数据。有了注释,VCF才从一串坐标变成有生物学意义的变异集合。你掌握了SnpEff和ANNOVAR这两套工具,就拥有了处理绝大多数注释场景的能力。
接下来的知识图谱部分,就是把这些注释好的变异和外部数据链接起来。那是另一个层面的挑战了。