3. 数据源结构解析:Funcotator 的目录层级与必需文件

很多人第一次接触 Funcotator 时,容易被它的数据源目录结构搞晕。我最早用的时候,就干过把不同版本的数据库直接扔进一个目录里的事,结果跑出来的注释结果乱七八糟。后来花了好几天排查,才发现是目录结构没对上。

说白了,数据源就是 Funcotator 的字典库。它按特定规则组织好,工具才能高效地查字典。这一节,我们把这个结构拆开来看清楚。

3.1 数据源文件夹的核心逻辑

Funcotator 要求所有数据源放在一个根目录下,这个目录就是 dataSourcesFolder(也有地方叫 data-sources-path)。你执行命令时,通过 --data-sources-path 参数指定这个根目录。

核心原则: 根目录内,一级子目录的名字必须与数据源版本名完全一致。比如 gnomAD_v2.1、clinvar_20210310。

为什么会这样?因为 Funcotator 在运行时会直接去 dataSourcesFolder/版本名/ 下找必需文件。名字对不上,它就报错。

3.2 目录层级:一个典型示例

我用自己的一个项目目录来举例,你看着会更直观:

funcotator_data/               # 这是 dataSourcesFolder 根目录
├── gnomAD_v2.1_exome/         # 版本目录:外显子群体频率
│   ├── gnomAD_v2.1_exome.vcf
│   ├── gnomAD_v2.1_exome.vcf.idx
│   ├── info_fields.txt
│   └── info_field_types.txt
├── clinvar_20210310/          # 版本目录:临床意义数据库
│   ├── clinvar_20210310.vcf
│   ├── clinvar_20210310.vcf.idx
│   ├── info_fields.txt
│   └── info_field_types.txt
├── dbsnp_b151/                # 版本目录:常见变异数据库
│   ├── dbsnp_b151.vcf
│   ├── dbsnp_b151.vcf.idx
│   ├── info_fields.txt
│   └── info_field_types.txt
└── empty/                     # 不包含必需文件,Funcotator 会直接跳过

嗯,这里要注意:每个版本目录下只能有一个 VCF 文件。如果有多个,Funcotator 会报错,因为它不知道用哪个。

3.3 必需文件清单与作用

每个版本目录里,必须包含以下四个文件(缺一不可):

文件名 类型 作用
数据源名.vcf VCF / 压缩 VCF 包含所有注释记录的变异位点信息
数据源名.vcf.idx 索引文件 Tabix 索引,用于快速定位特定区域的记录
info_fields.txt 文本 定义 VCF INFO 字段的 ID、类型、数量、描述
info_field_types.txt 文本 指定每个 INFO 字段的 GATK 类型(如 String, Integer, Float)

避坑指南: 我曾经只用 bgzip 压缩了 VCF,忘了生成 .tbi 或 .idx 索引。执行注释时,Funcotator 直接卡住,日志里只写了一句 No index file found。后来我学乖了,每次生成完索引后,都会用 ls -lh 确认索引文件大小不为 0。

3.4 info_fields.txt 与 info_field_types.txt 的格式

这两个文件的格式很关键,但它们经常被忽视。我给你们拆开看:

info_fields.txt 的格式,每行对应 VCF 中一个 INFO 字段:

##INFO=
##INFO=
##INFO=

info_field_types.txt 更简单,每行是 字段名\t类型:

AF	Float
AN	Integer
AC	Integer

小技巧: 如果 VCF 里 INFO 字段很多,你不想手动写,可以用 bcftools head 或者 grep ^##INFO 从 VCF 头部提取出来,再稍作格式化。这比手敲快得多,也不容易写错。

3.5 数据源命名约定

虽然 Funcotator 没有强制命名规则,但社区和一些 best practice 建议遵循以下模式:

  • 数据库名_版本号(如 clinvar_20210310)
  • 数据库名_版本号_数据集(如 gnomAD_v2.1_genome 或 gnomAD_v2.1_exome)
  • 数据库名_版本号_日期(如 dbsnp_b151_20210310)

我个人习惯使用 数据库名_版本号 加下划线的格式。这样在写脚本批量处理时,用 ls -d 配合正则就能直接取到所有版本目录。

3.6 实战验证:一个完整的目录检验流程

为了确保你的数据源目录结构没问题,我建议每次添加新数据源后,都执行一次下面这个验证步骤:

# 1. 检查所有版本目录是否包含必需文件
for dir in /path/to/funcotator_data/*/; do
    version=$(basename "$dir")
    # 尝试找到 VCF 文件(不区分 .vcf 还是 .vcf.gz)
    vcf_file=$(ls "$dir"*.vcf* 2>/dev/null | head -n 1)
    if [[ -z "$vcf_file" ]]; then
        echo "ERROR: $version 缺少 VCF 文件"
        continue
    fi
    idx_file=$(ls "$dir"*.idx 2>/dev/null | head -n 1)
    if [[ -z "$idx_file" ]]; then
        echo "ERROR: $version 缺少索引文件"
    fi
    if [[ ! -f "$dir"info_fields.txt ]]; then
        echo "ERROR: $version 缺少 info_fields.txt"
    fi
    if [[ ! -f "$dir"info_field_types.txt ]]; then
        echo "ERROR: $version 缺少 info_field_types.txt"
    fi
done

这个脚本我放在自己的工具库里,每次更新数据库都会跑一次。它帮我省下了不少手动检查的时间。

3.7 知识体系结构图

下面这张图把数据源目录的核心结构、必需文件、以及它们之间的关系画清楚了。你把它当作一个速查图谱,回过头来看时思路会清晰很多:

数据源目录结构速查图谱 dataSourcesFolder gnomAD_v2.1_exome 版本目录 1 clinvar_20210310 版本目录 2 dbsnp_b151 版本目录 3 *.vcf 变异数据 *.vcf.idx 索引文件 info_fields.txt 字段定义 field_types.txt 类型映射 ⚠ 每个版本目录下只能包含一个 VCF 文件 四类文件缺一不可,否则 Funcotator 会报错退出

3.8 常见问题与解决方法

整理几个我经常被问到的问题,你提前看一下,后面真遇到了就不慌了:

  • VCF 文件用了 .gz 压缩,索引文件是 .vcf.gz.tbi,可以吗? —— 可以。.vcf.gz + .tbi 是标准组合。Funcotator 内部调用 Tabix 时会自动识别。
  • info_fields.txt 和 info_field_types.txt 必须跟 VCF 文件中实际使用的字段完全一致吗? —— 严格来说,只需要包含你打算在注释中使用的字段。但我建议保持一致,否则会出现“字段定义了但没用”或“字段引用了但没定义”的情况。
  • 空目录或缺少必需文件的目录, Funcotator 会怎么处理? —— 它会跳过该目录,并在日志里输出 WARN 级别的信息。不会中断整个注释流程,但你的结果里会缺少该数据源的注释。

一句话总结: 数据源目录 = 根目录 + 版本子目录 + 四个必需文件。版本子目录名字不能错,四大金刚一个不能少。