必需字段详解:seqid、source、type、start、end、score、strand、phase、attributes
GFF3的每一行,都必须包含这9个字段。
缺一个都不行。顺序也不能乱。
我刚接触GFF3那会儿,总以为这是搞形式主义。后来被坑过几次,才明白每个字段都有它的设计逻辑。
2.1 字段概览
先说整体结构。9个字段用制表符分隔,做成一列一列的样子。
| 字段名 | 类型 | 必填 | 占位符 |
|---|---|---|---|
| seqid | 字符串 | 是 | 无 |
| source | 字符串 | 是 | . |
| type | 字符串 | 是 | 无 |
| start | 正整数 | 是 | 无 |
| end | 正整数 | 是 | 无 |
| score | 浮点数 | 否 | . |
| strand | 字符 | 是 | . |
| phase | 整数 | 参见说明 | . |
| attributes | 键值对 | 是 | 无 |
这张表可以当速查卡用。
我习惯把它贴在终端旁边的墙上,编码的时候瞄一眼就行。
2.2 字段逐个拆解
下面一个一个讲。
每个字段我都会给出:官方定义、我的理解、常见错误。
2.2.1 seqid:序列标识符
这个字段就是告诉你,当前记录在哪个染色体或scaffold上。
我曾碰到有人把seqid写成"chr1"和"1"混着来。文件里一半是chr1,一半是1。结果下游工具当成两个不同的序列在处理,注释全乱了。
我的建议很简单。统一用同一个命名约定,大小写、前缀、连字符都要保持一致。
grep按seqid分组计数,快速排查不一致问题。
2.2.2 source:注释来源
这个字段描述注释的产生方式。可以是软件名、数据库名、或者实验方法。
比如Augustus、RefSeq、RNA-Seq_evidence。
如果不知道来源,就用点做占位符:.。
但我必须提醒你。source字段不要写太个性化的名字。
我见过有人写my_best_guess,虽然语法没问题,但别人根本看不懂。最好使用标准名称。
2.2.3 type:特征类型
这是核心字段。它指定这条记录是什么。比如gene、mRNA、CDS、exon。
类型名必须符合SO(Sequence Ontology)术语。GFF3官方推荐使用SO术语。但这不是强制性的。
不过我个人强烈建议遵守。否则兼容性会很差。
# 推荐写法
gene
mRNA
CDS
exon
# 不推荐写法(虽然能通过语法检查)
genetic_element
coding_region
transcript_unit
我在项目中遇到过使用自定义类型名的情况。结果下游工具解析时直接崩溃了。因为那种工具只认特定几个SO术语。从那以后我就再也不敢乱取名了。
2.2.4 start和end:坐标对
这两个字段定义特征在序列上的起止位置。
关键规则有两条:
- 坐标是基于1的整数。不是0基。
- end必须大于等于start。
也许有人会问:为什么不是0基?
因为GFF3从GenBank格式继承来的一套规则。最早就是这么设计的。你想想看,生物学家习惯从1开始数碱基位置。所以GFF3遵循了这个习惯。
还有一个容易搞混的概念:区间类型。
| 区间 | 坐标示例 | 起始 | 终止 |
|---|---|---|---|
| 点特征 | start=10, end=10 | 10 | 10 |
| 区间特征 | start=10, end=20 | 10 | 20 |
start=10, end=11,虽然语法检查能通过,但代表一个长度为1的碱基区间。意义完全不同。
2.2.5 score:分数
这个字段可选。通常用于表示比对置信度或计算得分。
如果不使用,用点.占位。
典型用法如下:
# 比对得分
score=254.3
# 无得分
score=.
要注意的是,score不是自由格式的文本。必须是一个数字或点。我曾经看到有人写high和low。结果下游统计脚本直接炸了。
2.2.6 strand:链方向
这个字段告诉特征位于DNA的正链还是负链。
取值就3种:
+:正链-:负链.:不知道或不适用(链不明)
有一个很容易忽略的点:链方向影响CDS相位计算。
负链基因的外显子和CDS坐标,基因组浏览器内部会进行反向翻译。如果你手动调整坐标,很可能搞错。
2.2.7 phase:相位
这个字段只对CDS特征有意义。表示CDS的第一个碱基相对于密码子起始位置的偏移量。
取值只能是0、1、2或者点。
- 0:特征起始与密码子边界对齐
- 1:特征起始相对于密码子边界右移一个碱基
- 2:特征起始相对于密码子边界右移两个碱基
- 只用于CDS,其他类型用点占位
我遇到的最离谱的错误,是把负链的phase算错了。
负链CDS的phase计算是基于反向互补序列,而不是原始序列。很多人直接复用正链phase,结果翻译出来的蛋白质序列全错。
# 负链CDS的phase示例:第二个外显子phase=2
# 表示这个外显子起始处缺失两个碱基,才能对齐密码子
2.2.8 attributes:属性键值对
这个字段是最灵活,也是最多人出错的地方。
它是Key=Value;Key=Value的格式。多个键值对用分号分隔。
ID=gene001;Name=BRCA1;Note=tumor suppressor gene
属性键值对的编码规则:某些特殊字符需要进行Percent-Encoding(百分号编码)。
- 分号
;需要编码为%3B - 等号
=需要编码为%3D - 制表符、换行符也需要编码
我在项目中遇到过有人把Note=gene mutation写成了Note=splice variant;functional。因为分号没编码,解析器把functional当成了另一个键,直接解析出错了。
核心原则
推荐保留的键有:ID、Name、Parent、Alias、Note、Ontology_term、Dbxref。
ID必须是唯一的。Parent用于建立层次关系。
GFF3还有一个推荐但非强制的要求:ID值应该在整个文件中唯一。
虽然这不是语法错误,但多个特征共享同一个ID,下游工具往往会报错或忽略重复记录。
2.3 字段关系图
下面这张图能帮助你直观理解各个字段如何协同工作。
2.4 常见错误与避坑指南
下面我列出一些我实际踩过的坑。希望能帮你避免走弯路。
- seqid不一致:FASTA头部和GFF3的seqid对不上。解决方案:做一次交叉验证。
- 坐标混淆:0基和1基混用。GFF3固定使用1基。转换时务必确认。
- phase用错:负链CDS的phase需要基于反向互补序列计算。不要直接用正链的值。
- 属性键名冲突:同一个特征内出现重复的键名。虽然语法不禁止,但多数解析器会覆盖前面的值。
- 占位符与值的混淆:score和phase使用
.占位,表示缺失。不要填NA、none或其他字符串。
- seqid是否唯一且与FASTA匹配?
- start是否小于等于end?
- 负链CDS的phase计算是否正确?
- attributes是否做了百分号编码?
- ID是否全局唯一?
2.5 本章小结
9个字段,每个都有它的设计逻辑。
标识类字段帮你定位特征在哪里、由谁产生、是什么类型。
位置类字段告诉你特征的位置坐标和链方向。
属性类字段提供剩余的所有辅助信息。
只要把这三类字段搞清楚,GFF3的骨架就搭起来了。