第3章:可选字段与扩展——score、strand、phase的常见约定与默认值

很多新手刚接触 GFF3 时,都觉得前 8 列是主体,后 3 列不过是「可选的」。嗯,这种想法会害死人。我刚开始处理酵母基因组注释时,就因为在 strand 列里填了个乱码……整个下游分析全跑偏了。

今天咱们把 score、strand、phase 三个字段的坑一个一个填平。说白了,它们虽然「可选」,但一旦用错,后果远比你想的严重。

3.1 score 字段:不是所有的「分数」都叫 score

score 是第 6 列,官方说它是「证据支持度」。但实际项目中,这个字段被滥用得太多了。

核心约定:

  • 浮点数或整数,合法范围 0–1000
  • 没有值时用 . 占位
  • 专指「该特征与参考序列比对的置信度」,不是任意打分

我个人习惯是:只有基于序列比对(BLAST、minimap2)产生的特征才填 score,而且一定是标准化后的值。例如 exon 来自 spliced 比对,score 可以填最大 1000;但你要是自己算了个基因长度作为「分数」放进去……抱歉,那不是 GFF3 的约定。

常见陷阱

错误写法问题正确做法
score = 0.85(未乘 1000)范围外,工具可能报错或截断填 850 或直接用 .
score = "high"/"low"字符串,不符合浮点数规范填数值或 .
所有行全填 1000失去区分度,等于没意义按实际置信度填写,或全部留 .

曾经有一次,我帮同事排查一个 RNA-seq 的注释冲突。她所有基因模型的 score 都填了 999,结果 NCBI 的 RefSeq 验证工具直接跳过她的行,导致注释大面积丢失。后来才发现——score 列全是虚值,工具当作「不可信数据」处理了。

默认值策略

  • 实验验证的特征(如 PCR 验证的转录本):填 1000
  • 计算预测的特征(如 ab initio 预测):填预测概率×1000,取整
  • 人工复核过的:填 1000 且注释 attribute 注明
  • 拿不准、或不需要区分时:一律写 .,不要乱编数值

3.2 strand 字段:方向只有 + 和 -,没有也许

strand 是第 7 列。可选值只有 3 种:+、-、.。你想想看,是不是很简单?但现实中的混乱程度超出想象。

我给你们的建议:

  1. 明确特异的基因——填真实方向,别含糊
  2. 双向转录或有歧义的区域——填 .,然后加上 Note=ambiguous_strand
  3. 永远不要用 ?、0、both、1——这些不是标准值

我在一个细菌项目里遇到过这种情况:有人把正链写成 plus,负链写成 minus。解析器直接跳过这些行,因为他没按规范。为什么不去标准化一下?可能是手写表格时的习惯。嗯,这个坑踩一次就够了。

默认值的潜规则

  • 如果所有特征在同一行上(比如只注释了一条链),strand 必须统一
  • mRNA 的 strand 必须与它的 exon 一致,否则视为非法结构
  • 未定位到链的特征(如 repeat_region)建议始终用 .

3.3 phase 字段:CDS 的「对齐记号」,别乱填

phase 是第 8 列。只有 CDS 特征才需要它。其他特征(exon、mRNA、gene)应当填 .。这是很多人的误区——以为每个特征都要填 0。

phase 的取值规则:

  • 0:这个 CDS 片段的第一个碱基正好是密码子的第一个碱基
  • 1:第一个碱基是密码子的第 2 个碱基(即前面有 1 碱基偏移)
  • 2:第一个碱基是密码子的第 3 个碱基(偏移 2 碱基)
  • .:不是 CDS 特征,或者相位不适用

怎么计算?很简单——看这个 CDS 片段的起始位置相对于密码子框架的偏移量。如果你从整个 CDS 的起始密码子开始数,首个 CDS 片段一定是 phase 0。后面的片段根据前一个片段长度 mod 3 来推算。

我拿个例子演示一下

# 假设 CDS 起始于基因组的 100 位,总长 18bp,分成三个片段
100  105  CDS  phase 0   # 前 6bp,完整 2 个密码子
106  111  CDS  phase 0   # 起始对齐
112  117  CDS  phase 0   # 起始对齐

# 但如果第一个片段是 4bp(非 3 倍数)
100  103  CDS  phase 0   # 4bp,多出 1 碱基
104  110  CDS  phase 1   # 前面多 1 个,所以偏移 1

避坑提醒:我亲眼见过有人把所有 CDS 片段全标成 phase 0。结果翻译出来的蛋白质序列完全错位了——因为忽略了这个「偏移链条」。特别是内含子长度不是 3 的倍数时,相位一错,整个蛋白质序列都废了。

phase 的「默认值」陷阱

  • 不填 phase → 工具要么报错,要么当 0 处理,但可能错
  • 非 CDS 特征填 phase → 很多解析器会忽略,但部分严格工具会报警告
  • 相位值不能「中断」——必须连续传递。每个 CDS 片段的 phase 由前一个片段的长度决定

3.4 三个字段的整体使用检查清单

我把日常项目中常用的规则总结了一张表,你可以贴在工位上。

字段合法值必须填?典型错误我的推荐
score0–1000 浮点数或 .可选,但填了必须规范字符串、超出范围、人为虚构用 . 代替无意义数据
strand+ - .建议填,除非未知? 0 both未知则填 . 并加 Note
phase0 1 2 .仅 CDS 必须非 CDS 也填数值、不连续非 CDS 始终 .

3.5 一张图看懂三个字段的关系

下面这张 SVG 图帮你理清每个字段的关键点和常见错误。画布小,但信息集中,一眼扫过去就明白。

score · strand · phase 质控要点 score(第6列) strand(第7列) phase(第8列) 合法值:0–1000 浮点数 无值时必须用 . 不可用字符串/字母 常见错误 • 填 0.85(未乘1000) • 填 high/low • 所有行全填1000 合法值:+ - . 三种 无歧义必须明确方向 特征间一致 常见错误 • 填 ? 0 both • mRNA 和 exon 方向矛盾 • 未知区域不填 . 合法值:0 1 2 . 仅 CDS 特征必须填 非 CDS 必须填 . 常见错误 • 非 CDS 行填数值 • 所有 CDS 强行填 0 • 相位不连续(偏移错误) 核心原则:不确定就填 .,不要编造数据

你可以把这张图当作速查手册。下次写 GFF3 时,对着每个字段扫一遍这三个框——基本不会出大问题。

3.6 实战:如何用脚本自动校验这三个字段

总不能每次都手查吧?我写了一个简单的 awk 脚本,能快速扫描 GFF3 中这三个字段的异常。你直接贴到终端就能用。

awk -F'\t' '
!/^#/ {
  # score 检查(第6列)
  if($6 != "." && ($6 !~ /^[0-9]+\.?[0-9]*$/ || $6 > 1000 || $6 < 0))
    print "score 异常: 行" NR, $0

  # strand 检查(第7列)
  if($7 != "+" && $7 != "-" && $7 != ".")
    print "strand 异常: 行" NR, $0

  # phase 检查(第8列)——只对 CDS 检查
  if($3 == "CDS") {
    if($8 != "0" && $8 != "1" && $8 != "2" && $8 != ".")
      print "CDS phase 异常: 行" NR, $0
  } else {
    if($8 != ".")
      print "非CDS 行 phase 异常: 行" NR, $0
  }
}' your_file.gff3

小提示:这个脚本只做了基础格式检查。更严格的相位连续性校验,你需要结合前一个 CDS 片段的长度来做。不过,作为初筛,它已经能过滤掉 80% 的低级错误了。

好了,三个可选字段的核心要点就这些。记住一句话:. 是最好的默认值——比胡乱填一个数字安全得多。