3、输入文件格式:AVinput格式详解
好,咱们开始聊 AVinput 格式。说实话,在我刚接触 ANNOVAR 那会儿,觉得这格式有点奇怪——既不是标准的 VCF,也不是常见的 BED。但用久了你会发现,ANNOVAR 之所以搞出这么个格式,就是为了省事。它把位置、碱基、等位基因信息全塞进几个列里,一行就搞定一个变异。
我个人习惯,拿到一批数据后,第一件事就是检查格式。因为格式错了,后面的分析全白搭。今天咱们就把 AVinput 的每一个字段掰开揉碎了讲清楚。
3.1 AVinput 格式长什么样
先看一个标准例子。一个 AVinput 文件,每行就是一个变异位点,用制表符(Tab)分隔。我建议你永远别用空格,否则 ANNOVAR 会直接报错。
chr1 948921 948922 A G NA12878 60 pass . .
chr1 949523 949524 T C NA12878 45 pass . .
chr1 950003 950004 G A NA12878 55 lowqual 0.01 .
说白了,这文件是个纯文本。你拿 Excel 打开,很可能把某些列变成科学计数法。别问我是怎么知道的……
3.2 每一列到底是什么意思
AVinput 固定要求前五列不能少。我整理了一张表,方便你对照着看。
| 列序号 | 列名 | 说明 | 示例值 |
|---|---|---|---|
| 1 | 染色体 | 支持 chr1 或 1 两种形式。需要与参考基因组保持一致 |
chr1 |
| 2 | 起始位置 | 1-based 坐标。注意不是 0-based 的 BED 坐标 | 948921 |
| 3 | 结束位置 | 对于 SNP,结束 = 起始 + 1。对于插入缺失,按真实长度算 | 948922 |
| 4 | 参考等位基因 | 与参考基因组完全一致。如果有多个碱基,用大写字母 | A |
| 5 | 替代等位基因 | 样本中检测到的变异碱基。可以跟参考一样(纯合参考) | G |
| 6+ | 附加列 | 样本名、测序深度、质量值、过滤标签等。ANNOVAR 不强制,但数据库过滤会用 | NA12878 |
3.3 为什么要有起始和结束两列
你可能会问:SNP 明明就一个位点,为什么非要给两列?
嗯,这里有个历史原因。AVinput 设计时考虑了 Indel。假设你有一个三碱基的缺失:
chr1 1000 1003 ACT .
起始是 1000,结束是 1003,参考碱基是 ACT,替代是点(表示缺失)。这样一来,ANNOVAR 内部就能准确定位到 Indel 的范围。如果是 SNP,那就写成起始和结束差 1 的形式。我见过不少人把 SNP 的结束写成和起始一样,结果 ANNOVAR 报了个错…… 那错误信息特别隐晦。
3.4 等位基因字段必须大写
这个坑我踩过。有一次从某个流程出来的 VCF 里,有的替代等位基因是小写的 a,我直接拿去做 AVinput 了。结果 ANNOVAR 不停报错说找不到参考序列——实际上就是大小写不匹配。
AVinput 要求参考和替代等位基因必须用大写字母。如果你是从 VCF 转换过来的,记得加一步 tr '[:lower:]' '[:upper:]'。
sed 's/\t[a-z]/\t\u&/g' input.txt > fixed_input.txt
3.5 附加列:它们是干什么的
前五列之后的东西,ANNOVAR 默认不关心具体含义。它只是把这些列原样保留到输出文件中。但你想想看,如果你不做质量控制,结果里一堆低质量的假阳性,数据库注释再全也是白搭。
我一般会留三列:
- 第6列:样本 ID。方便多样本合并分析
- 第7列:测序深度。低于 10× 的变异,我会标记为 low_depth
- 第8列:过滤标签。可以是
pass、lowqual、strand_bias等
awk 或 python 过滤掉深度低于 8× 的位点。这样做有三个好处:减少假阳性、缩短运行时间、输出文件更小。我几乎每个项目都会加这一步。
3.6 从 VCF 转换成 AVinput
大部分时候你手里的数据是 VCF 格式。AVinput 跟 VCF 最大的区别:VCF 是 0-based 的,AVinput 是 1-based 的。千万别忘了加 1。
我这里有个随手用的脚本,分享给你做参考:
awk -F'\t' 'BEGIN{OFS="\t"}
/^#/ {next}
{
chr = $1
pos = $2 + 1
end = pos + length($4) - 1
ref = $4
alt = $5
sample = "SAMPLE"
qual = $6
filter = $7
print chr, pos, end, ref, alt, sample, qual, filter
}' input.vcf > input.avinput
注意这里有一个细节:$2 + 1 就是把 VCF 的 0-based 转成 AVinput 的 1-based。对于 SNP,end = pos 实际上就是起始位置;对于 Indel,它会自动算成正确长度。
3.7 格式验证的小窍门
文件写好了,别急着跑 ANNOVAR。先用这行命令快速检查:
awk -F'\t' '{
if(NF < 5) print "Error: line " NR " has fewer than 5 columns";
if($2 >= $3) print "Error: line " NR " start >= end";
if(length($4) == 0 || length($5) == 0) print "Error: line " NR " empty ref or alt";
}' input.avinput
我在项目中遇到最多的问题是:Indel 的结束位置写错了。尤其是大片段缺失,你以为是 1000-2000,但 ANNOVAR 其实只要求覆盖缺失的两个端点。具体来说,先写缺失的起始位点,再写起始+1,参考等位基因写成完整的缺失序列,替代写成 - 表示的空白序列。
WARNING: chromosome not found in reference 错误,百分之九十是因为染色体前缀不一致。比如参考基因组是 1,而你写了 chr1。用 sed 's/^chr//' 或 sed 's/^/chr/' 统一一下就行。
3.8 AVinput 的整体结构
下图把这章的知识点串在了一起。从原始 VCF 开始,经过格式转换、坐标调整、质量控制,最终生成干净的 AVinput 文件,送入 ANNOVAR 进行数据库注释。
3.9 我的日常检查清单
最后,分享一份我自己用的 AVinput 质量检查清单。每次跑 ANNOVAR 之前,我都会在终端跑一遍这些命令,心里才踏实。
- 检查染色体格式:
awk -F'\t' '{print $1}' input.avinput | sort -u,确认跟参考基因组一致 - 检查位置逻辑:
awk -F'\t' '$2 >= $3' input.avinput,不能有任何输出 - 检查等位基因:
grep -i '[a-z]' input.avinput | head,确认没有小写字母 - 检查空值:
awk -F'\t' 'length($4)==0 || length($5)==0' input.avinput,不能有输出 - 检查列数:
awk '{print NF}' input.avinput | sort -u,确保每一行列数相同
嗯,能把这些都过了,你的 AVinput 文件就基本没问题了。剩下的就是丢给 ANNOVAR,等着拿结果了。