摘要: Fermi-lite 是一个面向基因组学的独立 C 语言库及命令行工具,专为组装 Illumina 短读序列而设计,适用于 100bp 至 1000 万 bp 规模的区域组装任务。作为 FermiKit 的轻量级内存版本,它无需生成中间文件,在保留原有性能和较低内存占用的同时,显著简化了使用流程。
在方法层面,Fermi-lite 采用基于重叠的组装策略:首先统计 k-mer 频率并估算覆盖度,通过设定阈值筛选可靠 k-mer 以完成测序错误校正;随后对读段进行修剪,构建 FM 索引,并基于此构建经过传递性化简的重叠图;最终通过修剪末端、消除气泡等操作优化组装结果,输出 unitig 序列及 GFA 格式的组装图。
该工具的一项关键特性是能够保留杂合变异位点,因此尤其适用于二倍体基因组区域的局部重组装及变异检测任务。其 API 设计简洁,仅需引入单一头文件即可集成至第三方程序,是当前局部重组装领域易用性较为突出的工具之一。
fermi-lite:轻量级基因组局部组装 C 库¶
概述¶
fermi-lite 是由 Heng Li 开发的一个独立 C 语言库(standalone C library),同时也提供命令行工具,专用于对 Illumina 短读长测序数据(short reads)进行基因组区域组装。其支持的组装规模从 100bp 到 1000 万 bp(10 million bp)不等,覆盖了大多数局部重组装(local re-assembly)的实际需求。
fermi-lite 本质上是 fermikit 的轻量级内存版本(light-weight in-memory version),与 fermikit 的关键区别在于:整个组装流程完全在内存中完成,不产生任何中间文件(intermediate files),因此更适合嵌入其他程序作为库调用。
该工具解决了局部重组装领域中接口复杂、依赖繁重的痛点。它继承了 fermikit 的性能表现与相对较小的内存占用(small memory footprint),并保留了其核心特性。特别重要的是,fermi-lite 能够保留杂合事件(heterozygous events),因此可用于组装二倍体区域(diploid regions)以进行变异检测(variant calling)。
在同类工具中,fermi-lite 是局部重组装的少数可选方案之一,且被认为是其中最易于接口集成的工具。如果在研究中使用 fermi-lite,需引用以下文献:
Li H (2015) FermiKit: assembly-based variant calling for Illumina resequencing data, Bioinformatics, 31:3694-6.
核心原理与功能¶
组装算法流程¶
fermi-lite 是一个基于重叠图(overlap-based assembler)的组装器,其完整的组装流程如下:
1. k-mer 计数与覆盖度估计(k-mer counting and coverage estimation)
给定一组输入读长(input reads),fermi-lite 首先对所有 k-mer 进行计数,并据此估算 k-mer 覆盖度(k-mer coverage)。
2. 测序错误校正(sequencing error correction)
基于 k-mer 出现频次,fermi-lite 设定阈值以确定可信 k-mer(solid k-mers),进而对测序错误进行校正(参考 Li, 2015)。
3. 读长修剪(read trimming)
错误校正完成后,fermi-lite 在读长中找到该读长独有的 l-mer(l-mer unique to the read)处对读长进行截断修剪,去除低质量或歧义末端。
4. FM-index 构建(FM-index construction)
对修剪后的读长构建 FM-index(参考 Li, 2014)。FM-index 是一种基于 Burrows-Wheeler 变换(BWT)的压缩索引结构,支持高效的字符串匹配,是后续重叠图构建的基础。
5. 传递简约重叠图构建(transitively reduced overlap graph construction)
基于 FM-index,fermi-lite 构建传递简约重叠图(transitively reduced overlap graph),要求读长之间至少有 l bp 的重叠(参考 Simpson and Durbin, 2010;Li, 2012)。
6. 图清理(graph cleaning)
在重叠图中,fermi-lite 执行以下清理操作: - 修剪末梢(tip trimming):去除图中由未校正错误产生的短分支末梢。 - 气泡消除(bubble popping):消除由未校正错误导致的气泡结构(bubbles)。 - 短重叠剪除:若图中某序列存在多个重叠,则丢弃明显短于最长重叠的那些——这是专门针对重叠图(overlap graph)的优化技术。
7. 最终输出:单元序列(unitigs)
经过上述流程后,图中保留的序列即为最终输出的单元序列(unitigs)。最终结果实际上是一个图(graph)结构,可进一步导出为 GFA(Graphical Fragment Assembly)格式。
核心特性¶
| 特性 | 说明 |
|---|---|
| 独立 C 库 | 无需外部依赖即可集成到其他程序 |
| 无中间文件 | 全内存运行,适合嵌入式调用场景 |
| 杂合事件保留 | 支持二倍体区域组装与变异检测 |
| 小内存占用 | 继承 fermikit 的内存效率 |
| GFA 图输出 | 支持导出重叠图的 GFA 表示 |
已知局限性¶
- 细菌基因组:fermi-lite 可以高效组装细菌基因组,但尚未针对此类组装场景精细调优。在部分 GAGE-B 数据集上表现良好,但在一般情况下可能不及近期主流组装器(mainstream assemblers)。
- 大基因组限制:fermi-lite 不适用于整体超过数十兆碱基(tens of megabases)的基因组,因为将全部数据驻留内存的内存开销过大。对于大型基因组,应使用 fermikit。
- 参数自动化:当前版本尚不成熟,特别是参数自动推断能力有限——由于输入数据的高度可变性,自动确定各类参数极具挑战性。
安装与使用¶
编译安装¶
编译完成后,目录下会生成命令行工具 fml-asm 以及供链接使用的静态库文件。
命令行工具使用¶
作为 C 库集成到自定义程序¶
将 fermi-lite 作为库链接到自己的程序时,编译命令如下:
# 编译自定义程序 prog.c,链接 fermi-lite 库及其依赖
# -Wall 启用所有编译警告
# -O2 开启二级优化
# -L/path/to/fermi-lite 指定 fermi-lite 库文件所在目录
# -lfml 链接 fermi-lite 主库
# -lz 链接 zlib(处理 gzip 压缩文件)
# -lm 链接数学库
# -lpthread 链接 POSIX 线程库(多线程支持)
gcc -Wall -O2 prog.c -o prog -L/path/to/fermi-lite -lfml -lz -lm -lpthread
关键头文件¶
fermi-lite 的库接口极为简洁,整个 API 只需引入一个头文件:
实战示例¶
以下示例来自官方 example.c,展示了调用 fermi-lite 库进行序列组装的完整流程:
#include <stdio.h> // 引入标准 I/O,用于 printf() 输出
#include "fml.h" // 引入 fermi-lite 唯一所需的头文件
int main(int argc, char *argv[])
{
int i, n_seqs, n_utgs;
bseq1_t *seqs; // 输入序列数组(array of input sequences)
fml_utg_t *utgs; // 输出单元序列数组(array of output unitigs)
fml_opt_t opt; // 组装参数结构体
if (argc == 1) return 1; // 若无输入文件参数则直接退出
// 从文件读取输入序列;也可由调用方自行填充该数组
seqs = bseq_read(argv[1], &n_seqs);
// 初始化组装参数为默认值
fml_opt_init(&opt);
// 执行组装,返回单元序列数组;n_utgs 为输出单元序列数量
utgs = fml_assemble(&opt, n_seqs, seqs, &n_utgs);
// 以 FASTA 格式输出所有单元序列
for (i = 0; i < n_utgs; ++i)
printf(">%d\n%s\n", i+1, utgs[i].seq);
// 释放单元序列占用的内存
fml_utg_destroy(n_utgs, utgs);
return 0;
}
关键 API 说明¶
| 函数 | 说明 |
|---|---|
bseq_read(filename, &n) | 从文件读取序列,返回 bseq1_t 数组 |
fml_opt_init(&opt) | 将 fml_opt_t 参数结构体初始化为默认值 |
fml_assemble(&opt, n, seqs, &n_utgs) | 执行核心组装,返回 fml_utg_t 单元序列数组 |
fml_utg_destroy(n, utgs) | 释放组装结果的内存 |
fml_utg_print_gfa() | 将 fml_utg_t 数组导出为 GFA 格式(位于 misc.c) |
导出 GFA 格式¶
fml_assemble() 的输出本质上是一个图结构。若需将结果导出为 GFA(Graphical Fragment Assembly)格式,可参考 misc.c 中的 fml_utg_print_gfa() 函数,该函数展示了如何从 fml_utg_t 对象数组推导出 GFA 表示。
常见问题¶
Q1:fermi-lite 和 fermikit 有何区别,什么时候应该用哪个?
fermi-lite 是 fermikit 的轻量级内存版本,核心差异在于:fermi-lite 完全在内存中运行,不产生任何中间文件,且提供 C 库接口,便于嵌入其他工具;而 fermikit 是完整的流水线工具,适合处理大型基因组。当需要局部重组装(如变异检测的局部区域)或将组装能力集成进自定义程序时,推荐使用 fermi-lite。当目标基因组超过数十兆碱基时,应改用 fermikit。
Q2:fermi-lite 是否支持处理二倍体(diploid)数据,能用于变异检测吗?
是的。fermi-lite 的一个重要特性是能够保留杂合事件(heterozygous events),因此可以用于组装二倍体区域,并将组装结果用于下游的变异检测(variant calling)。这也是 fermi-lite 区别于部分其他组装器的关键能力之一。
Q3:为什么组装超大基因组时内存会耗尽?
fermi-lite 是纯内存型工具,所有数据(读长、FM-index、重叠图)均驻留内存,不写入磁盘中间文件。对于数十兆碱基以上的基因组,所需内存量会超出实际可用范围。针对此类场景,官方明确建议使用 fermikit 替代。
Q4:如何获取 GFA 格式的组装图,而不仅仅是 FASTA 序列?
fml_assemble() 的返回值本身就是图结构的表示(fml_utg_t 数组包含节点序列及其连接关系)。若要导出标准 GFA 格式,可参考源码中 misc.c 文件里的 fml_utg_print_gfa() 函数,按照其逻辑从 fml_utg_t 数组构建 GFA 输出。
Q5:fermi-lite 是否适合用来组装完整细菌基因组?
技术上可行,fermi-lite 能够高效完成细菌基因组的组装,且在部分 GAGE-B 基准数据集上表现良好。但官方明确指出,fermi-lite 尚未针对细菌全基因组组装场景进行精细调优,在一般情况下可能不及近期主流细菌基因组组装器的表现。对于细菌基因组组装有较高质量要求时,建议结合主流工具进行比较评估。
总结¶
fermi-lite 是一个专为 Illumina 短读长数据局部组装设计的轻量级 C 库,支持 100bp 至 10Mbp 规模的区域组装。其核心优势在于:纯内存运行、无中间文件、提供简洁的 C API(仅需引入 fml.h 一个头文件),以及能够保留杂合事件以支持二倍体变异检测。算法层面,它基于 FM-index 构建传递简约重叠图,并通过 k-mer 纠错、末梢修剪和气泡消除等步骤生成高质量单元序列(unitigs),结果可导出为 FASTA 或 GFA 格式。使用时需注意其局限性:不适用于超过数十兆碱基的整体基因组组装,参数自动化能力尚待完善。在局部重组装领域,fermi-lite 是接口最简洁的可选方案之一。