1. GFF/GTF 格式概述与区别归纳总结

做基因组分析的朋友,一定绕不开 GFF 和 GTF。这两个格式就像一对双胞胎,长得像,但性格不同。我刚入行那会儿,就因为这俩格式混用,把一个流程跑出了莫名其妙的错误,排查了整整一天。嗯,从那天起我就养成了一个习惯——拿到注释文件先看一眼是 GFF 还是 GTF。

说白了,GFF 是通用特征格式(General Feature Format),GTF 是基因转移格式(Gene Transfer Format)。它们都用来描述基因组上的注释信息——基因在哪个位置、有多少个外显子、UTR 边界在哪等等。但设计思路和语法细节上,差别不小。你想想看,如果拿 GTF 的解析器去读 GFF3 文件,大概率会在第 9 列报错。这不是工具不好,是格式没对齐。

1.1 格式起源与版本演变

GFF 最早由 Sanger 研究所推动,目的是为基因组注释提供一个统一的表格形式。我记得最早接触的是 GFF2,那时候还在用 Perl 脚本手工解析。后来社区发现 GFF2 在表示复杂基因结构时不够灵活,于是在 2005 年左右推出了 GFF3,这也是目前最主流的版本。

GTF 呢,本质上是从 GFF2 衍生出来的。UCSC 和 Ensembl 这两个基因组浏览器团队,为了更精确地描述基因和转录本关系,在 GFF2 基础上做了一些调整,形成了 GTF。所以你会发现,GTF 的很多规则跟 GFF2 很像,但跟 GFF3 反而不太兼容。

下面是几个常见版本的对照:

格式名称 全称 当前状态 主要维护方
GFF1 General Feature Format 1 已淘汰 Sanger
GFF2 General Feature Format 2 少量使用 Sanger
GFF3 General Feature Format 3 推荐使用 GMOD / NCBI
GTF1 Gene Transfer Format 1 已淘汰 UCSC
GTF2 Gene Transfer Format 2 广泛使用 Ensembl / UCSC

个人建议:新项目优先用 GFF3 或 GTF2。如果团队已有管道,别急着换,先把格式兼容性测清楚。我曾经见过一个团队因为升级 GFF 版本,导致所有下游分析脚本全部重写,代价不小。

1.2 九列核心结构——万变不离其宗

不管 GFF 还是 GTF,核心都是 9 列,用 Tab 分隔。每一行代表一个注释特征。我习惯把这 9 列分成三组:定位信息(1-5列)、打分与方向(6-8列)、属性描述(第9列)。下面这张表你最好收藏一下,排查格式错误时经常要用到。

列号 字段名 GFF3 规则 GTF2 规则
1 seqid 染色体/ scaffold ID 同 GFF3
2 source 注释来源(如 Braker3) 同 GFF3
3 type 特征类型(如 gene, mRNA, exon) 同 GFF3,但必须用受控词汇
4 start 起始坐标(1-based) 同 GFF3,也是 1-based
5 end 终止坐标(包含) 同 GFF3
6 score 置信度或 E-value 同 GFF3,可用 . 填充
7 strand + / - / . 同 GFF3
8 phase / frame CDS 相位(0, 1, 2) 读框(0, 1, 2),含义相同
9 attributes / group Tag=Value 格式,分号分隔 key "value" 格式,引号包裹

避坑指南:我曾经犯过一个低级错误——把 GFF3 中第 8 列的 phase 直接当成 GTF 的 frame 用,结果翻译起始位点总是偏移一个碱基。后来一查才发现,phase 和 frame 虽然含义一样,但 GFF3 要求 CDS 特征必须填,而 GTF 允许用 . 代替。这点差异在长基因流程中特别容易踩坑。

1.3 第 9 列——核心差异所在

前 8 列两家基本一致,真正的分歧在第 9 列。这也是我排查格式错误时第一个检查的位置。来看两个实际例子:

GFF3 的第 9 列风格:

ID=transcript_001;Parent=gene_001;Name=TP53-201;biotype=protein_coding

GTF2 的第 9 列风格:

gene_id "ENSG000001"; transcript_id "ENST000002"; gene_name "TP53"; transcript_name "TP53-201"

看出来了吗?GFF3 用 key=value,等号两边没有空格,多个标签用分号隔开。GTF 用 key "value",值和关键词之间用空格,值必须用双引号包裹。就这个小小的引号差异,每年不知道让多少管道崩溃。

还有一个容易忽略的点:GFF3 要求 ID 和 Parent 标签来构建层级关系,而 GTF 用 gene_id 和 transcript_id 来表达归属。这意味着,GFF3 可以轻松表示 mRNA ↔ 外显子 ↔ CDS 的多级嵌套,GTF 则更扁平,适合基因→转录本→外显子这种两层结构。

1.4 格式选择——没有银弹

到底该用 GFF 还是 GTF?说实话,得看你的下游工具链。我个人遵循三条原则:

  • 看浏览器:去 UCSC 提交数据,优先用 GTF;去 JBrowse 或 IGV,GFF3 表现更好。
  • 看流程:如果管道里有 gffread、agat 这类工具,它们对 GFF3 支持更完整。如果用的是 cufflinks、stringtie,那 GTFs 是标准输入。
  • 看复杂度:需要表示可变剪接、融合基因、假基因这些复杂结构时,GFF3 的层级模型更灵活。

实用建议:如果你跟我一样,经常在两种格式之间切换,可以在流程里内置一个格式检测步骤。检测方法很简单——读取第 9 列的第一个特征,看看值是跟在 = 后面还是包在引号里。一两行脚本就能避免后续所有解析错误。

1.5 知识体系一览

下面这张图把这章的核心逻辑串起来了。你可以把它当作一个快速索引,遇到格式问题先在这张图上定位一下。

GFF / GTF 格式核心知识框架 GFF / GTF 格式总览 第 1-8 列:定位 + 评分 + 方向 第 9 列:格式核心差异 GFF3:Tag=Value;ID/Parent 层级 GTF:key "value";gene_id/transcript_id 选择依据:工具链 + 浏览器 + 结构复杂度 混乱的根源:第 9 列语法差异 + 版本混用 排查第一步:先看 attributes 用的是 = 还是 引号

看着这张图,其实就一句话:前 8 列两者高度一致,第 9 列是分水岭。你只要抓住第 9 列的语法差异,就能快速判断手里的文件是 GFF 还是 GTF,也能解释为什么同一个解析器换了文件就罢工。

一个小技巧:在 Linux 下,直接用 head -1 your_file.gff | cut -f9 | head -c 50 看一眼第 9 列的前 50 个字符。如果有 = 且没有引号,大概率是 GFF3;如果有 " 包裹的值,那就是 GTF。这个办法在我手里救过无数次急。