跳转到内容

OLC:Overlap-Layout-Consensus

快速概览

OLC 是经典的三阶段组装范式:先找 reads 之间的重叠关系,再构建布局确定相对位置,最后综合多条 read 的信息生成共识序列。

  • Overlap:快速筛选并精确计算 read 之间的重叠
  • Layout:将重叠关系组织成图或路径,推断顺序和方向
  • Consensus:利用冗余覆盖纠正错误,输出稳定序列
  • 长读长时代,OLC 思路因重叠信息更丰富而重新受到重视

OLC(Overlap-Layout-Consensus)是一类经典组装思路,它把序列重建问题拆成三个阶段:

  1. Overlap:寻找 reads 之间的重叠关系;
  2. Layout:根据重叠关系构建布局;
  3. Consensus:从布局中求共识序列。

和 de Bruijn graph 相比,OLC 更强调"read 与 read 之间的真实重叠",而不是先分解成 k-mer 再建图。

组装的核心问题始终是:如何从局部观测恢复整体序列。

在 OLC 框架中,我们假设:

  • 如果两条 read 有足够可靠的重叠,它们就可能来自原始序列上的相邻区域;
  • 把许多这样的重叠关系拼接起来,就有机会恢复更长的序列骨架;
  • 最后再用多条 read 的信息求出更稳健的共识序列。

长读长时代让这套思路重新变得非常重要,因为长读长之间的重叠信息更丰富,更有机会跨过重复区域并提供稳定布局线索。

OLC 的思想可以用一个更简化的理论模型来理解——最短超串问题(Shortest Superstring Problem)

  • 输入:一组字符串 s1,s2,,sns_1, s_2, \ldots, s_n(视为测序 reads);
  • 输出:一个包含所有输入串作为子串、且长度尽可能短的字符串。

定义 overlap(si,sj)\text{overlap}(s_i, s_j)sjs_j 的最长前缀同时也是 sis_i 后缀的长度(如 overlap(ABCDEF,DEFGHI)=3\text{overlap}(\text{ABCDEF}, \text{DEFGHI}) = 3)。把每个字符串看作顶点,边权设为 overlap(si,sj)-\text{overlap}(s_i, s_j),则"找最大总重叠的排列"等价于旅行商问题(TSP),因此最短超串问题是 NP-完全的,不存在已知的多项式时间精确算法。

实用的近似策略是贪心:反复选取重叠最长的一对字符串合并(重叠部分只保留一次),直到只剩一个串。该贪心算法的近似比被推测为 2,实际表现通常远好于最坏上界。OLC 的 Layout 阶段正是这一思想在真实数据上的扩展——它额外处理测序错误、重复序列和正负链等理论模型忽略的因素。

OLC 组装流程示意图
OLC 组装的三个核心阶段:重叠检测、布局构建与一致性序列生成。

目标是找出哪些 reads 之间存在显著重叠。

这一阶段最直接,但往往也是最贵的,因为潜在 read 对数目很大。要解决的问题包括:

  • 如何快速筛掉不可能重叠的 read 对;
  • 如何区分真实重叠与重复/错误造成的假重叠;
  • 如何给重叠边打分。

得到重叠关系后,可以把 reads 组织成图或路径结构,尝试推断它们在原始序列上的相对顺序和方向。

这一阶段最容易遇到的麻烦是:

  • 重复区域造成歧义;
  • 某些 read 质量差,使布局不稳定;
  • 图中存在多个看似合理的延伸方向。

即使 layout 大体正确,read 本身也可能有错误。因此最后还需要把多条重叠 read 综合起来,得到更可靠的 consensus sequence。

这一步强调的是"用冗余覆盖纠正单条 read 的错误"。

假设有三条 read:

R1: ACGTAC
R2: GTACGA
R3: ACGATT

如果发现:

  • R1R2GTAC 上有高质量重叠;
  • R2R3ACGA 上有高质量重叠;

那么 layout 阶段就可能推断它们沿同一条更长序列排列。最后 consensus 阶段再综合覆盖信息,输出更稳定的结果。

OLC 不是单一算法,而是一整类设计范式。它的思想在很多长读长组装和共识构建流程中都能看到:

  • 先找重叠;
  • 再构布局;
  • 最后做共识纠错。

与 de Bruijn graph 相比,可以粗略理解为:

| 思路 | 更关注什么 | 常见优势 | 常见挑战 | |---|---|---|---| | OLC | read-read overlap | 长读长信息利用更直接 | overlap 搜索昂贵 | | de Bruijn graph | k-mer 图结构 | 短读长场景更高效 | 对错误和重复非常敏感 |

因此,它们并不是简单的"新旧替代关系",而更像不同数据条件下的不同建模选择。

给定两条 read r1r_1r2r_2,目标是找到它们之间的最大重叠。这可以形式化为序列对齐问题。

算法 1:后缀-前缀最长公共子串

输入:read r₁, read r₂,最小重叠长度 L_min
输出:最大重叠长度和重叠位置
1. 构造后缀数组 SA₁ 包含 r₁ 的所有后缀
2. 构造前缀数组 PA₂ 包含 r₂ 的所有前缀
3. 对于每个后缀 s ∈ SA₁:
a. 如果 |s| < L_min,跳过
b. 在 PA₂ 中二分搜索与 s 匹配的最长前缀
c. 记录匹配长度
4. 返回最大匹配长度及其位置

时间复杂度O(nlogn)O(n \log n),其中 nn 为 read 长度(使用后缀数组)

空间复杂度O(n)O(n)

为了避免对所有 read 对进行昂贵的对齐计算,先使用 k-mer 进行快速筛选:

算法 2:k-mer 索引筛选

输入:read 集合 R,k-mer 长度 k,最小共享 k-mer 数 t
输出:候选重叠对集合 C
1. 构建倒排索引 I:k-mer → {read ids}
2. 对于每个 read r ∈ R:
a. 提取 r 的所有 k-mer 集合 K_r
b. 对于每个 k-mer k' ∈ K_r:
- 将 r 添加到 I[k']
3. 对于每对 read (r_i, r_j):
a. 计算 |K_{r_i} ∩ K_{r_j}|
b. 如果 |K_{r_i} ∩ K_{r_j}| ≥ t,加入候选集 C
4. 返回 C

时间复杂度O(NL)O(N \cdot L) 构建,O(CL)O(|C| \cdot L) 验证,其中 NN 为 read 数量,LL 为 read 长度

将 reads 作为顶点,重叠关系作为边,构建有向图:

定义:重叠图 G=(V,E)G = (V, E),其中

  • VV:所有 reads
  • E={(ri,rj,w,o)}E = \{(r_i, r_j, w, o)\}rir_irjr_j 有权重为 ww、偏移为 oo 的重叠

算法 3:重叠图构建

输入:候选重叠对集合 C
输出:重叠图 G = (V, E)
1. 初始化空图 G
2. 对于每个候选重叠对(r_i, r_j) ∈ C:
a. 计算精确重叠长度 o 和对齐分数 s
b. 如果 s ≥ 阈值 S_min:
- 添加边(r_i, r_j) 到 E
- 设置边权重 w = s
3. 返回 G

在重叠图中寻找 Hamiltonian 路径或近似路径:

算法 4:贪心路径延伸

输入:重叠图 G = (V, E)
输出:路径集合 P
1. P = ∅
2. 标记所有顶点为未访问
3. 当存在未访问顶点时:
a. 选择未访问且入度最小的顶点 v_start
b. path = [v_start]
c. 标记 v_start 为已访问
d. while 当前顶点 v 有出边:
- 选择权重最大的边(v, u)
- 如果 u 未访问:
* 将 u 加入 path
* 标记 u 为已访问
* v = u
- 否则:break
e. 将 path 加入 P
4. 返回 P

时间复杂度O(V+E)O(|V| + |E|),假设每次选择出边是常数时间

注意:这是启发式算法,不保证最优解。精确的 Hamiltonian 路径问题是 NP-hard。

给定 layout 中的重叠 reads,计算 consensus 序列:

算法 5:基于列投票的 Consensus

输入:对齐后的 reads A = {a₁, a₂, ..., a_m}(每行长度为 n)
输出:consensus 序列 c
1. c = ""(空字符串)
2. 对于列 j = 1 到 n:
a. 统计该列各碱基的计数:count[A, C, G, T, -]
b. 计算各碱基的频率
c. 选择频率最高的碱基 b_max
d. 如果 b_max 的频率 ≥ 阈值 Q_min:
- c += b_max
否则:
- c += 'N'(不确定)
3. 返回 c

时间复杂度O(mn)O(m \cdot n),其中 mm 为 reads 数量,nn 为对齐长度

考虑测序质量分数的改进算法:

算法 6:质量加权 Consensus

输入:对齐后的 reads A,质量分数 Q = {q₁, q₂, ..., q_m}
输出:consensus 序列 c
1. c = ""
2. 对于列 j = 1 到 n:
a. 对于每个碱基 b ∈ {A, C, G, T}:
- score[b] = Σ log₁₀(P(b|q)),其中 P(b|q) 是质量分数 q 下碱基 b 的正确概率
b. 选择 score 最大的碱基 b_max
c. c += b_max
3. 返回 c

质量分数转换:质量分数 qq 通常定义为 q=10log10(Perror)q = -10 \log_{10}(P_{error})

| 阶段 | 主要算法 | 时间复杂度 | 空间复杂度 | |------|---------|-----------|-----------| | Overlap | k-mer 筛选 + 动态规划 | O(NL)O(N \cdot L) | O(NL)O(N \cdot L) | | Layout | 图构建 + 贪心路径 | O(V+E) | O(V+E) | | Consensus | 列投票 | O(mn)O(m \cdot n) | O(n)O(n) |

其中 NN 为总 read 数量,LL 为平均 read 长度,mm 为局部区域 read 数量,nn 为对齐长度。