3. UMI 计数与过滤:去重原理、有效比例与同源序列处理
哈,聊到 UMI(Unique Molecular Identifier,独特分子标识符)了。这是空间转录组 QC 里我最喜欢的一个环节。为什么?因为它直接关系到你最终拿到的那个基因表达矩阵到底靠不靠谱。
你可能听过一句话:「空间转录组的数据质量,一半看 UMI 去重做得好不好。」这话不夸张。我在好几个项目里都见过,明明组织切片做得很漂亮,结果一跑 QC,有效 UMI 比例低得可怜——说白了,大量数据其实是被 PCR 重复浪费掉了。
好,我们一步步拆开来看。先从最基础的 UMI 去重原理说起。
3.1 UMI 去重原理:到底在去什么?
UMI 说白了就是一段随机的核苷酸序列,长度从 8 bp 到 12 bp 不等。在建库的时候,每一个 mRNA 分子都会被打上一个独一无二的标签——你把它理解为分子条形码就行。
测序后,同一条 mRNA 会产生多个测序 read,但这些 read 都会带着同一个 UMI。所以,如果我们看到多组 read 拥有完全相同的 UMI + 空间条码 + 基因映射,那它们大概率来自同一个原始 mRNA 分子。这时候,我们只保留一条就够了。
嗯,具体流程可以这样理解:
- 第一步:读出 UMI 序列。注意,这里 UMI 的碱基质量非常关键。
- 第二步:按「空间条码 + 基因 ID + UMI 序列」进行分组。
- 第三步:每组只保留一条 read(通常是 UMI 质量最高的那条)。
- 第四步:扔掉其他所有重复 read。
这就是最经典的 UMI deduplication。但这里有个坑——如果 UMI 本身有测序错误,那原本是同一个分子的 read,可能因为一两个碱基错误被分到不同组去了。我刚刚接触这个领域时就吃过这个亏,结果去重后 UMI 数目反而膨胀了。嗯,后来我养成了一个习惯:在去重前先做 UMI 校正。
下面这个图可以帮你快速理解 UMI 去重的完整逻辑:
3.2 有效 UMI 比例(UQI):你的文库还剩多少有价值的数据?
有效 UMI 比例,我习惯叫它 UQI(UMI Quality Index)。计算公式很简单:
UQI = 去重后 UMI 数 ÷ 去重前 UMI 数
举个例子:一个 spot 捕获了 5000 个 UMI,经过 deduplication 后剩下 1800 个有效 UMI,那 UQI = 0.36。这意味着什么?意味着原始数据里有 64% 的 UMI 对应的是同一个分子——说白了,你的建库效率或者测序深度产生了大量的冗余。
我个人习惯的 UQI 阈值参考:
| UQI 范围 | 文库质量说明 | 建议操作 |
|---|---|---|
| > 0.55 | 文库复杂度极高,数据利用率好 | 信心十足,进入下游分析 |
| 0.35 – 0.55 | 中等,可接受 | 正常分析,留意个别低 UQI spot |
| 0.20 – 0.35 | 偏低,存在冗余过多或低质量 UMI | 强烈建议排查建库和测序过程 |
| < 0.20 | 极低,基因组表达信号被严重压缩 | 考虑重新建库或调整捕获参数 |
你想想看,如果 UQI 只有 0.1,意味着你 90% 的 UMI 其实都是噪音。这时候你用这些数据做差异表达分析,结果能信吗?反正我是不敢直接用。
3.3 低 UQI 的常见病因排查
为什么 UQI 会低?我在项目中遇到过三种典型情况:
- PCR 循环过多:这是最常见的原因。PCR 扩增越狠,同一个 UMI 的复制品就越多。去重后有效比例自然下降。
- 测序深度过高:测得太深,每个 UMI 被覆盖几十甚至上百次。表现上看是数据量大,但有效 UMI 数并没有增加。
- UMI 碱基质量差:低质量 UMI 无法被正确读取,导致去重算法出错——原本一个 UMI,由于测序错误被识别成多个,去重不干净。
我记得有个项目,建库时 PCR 循环数从 12 增加到了 18,结果 UQI 直接从 0.45 掉到了 0.19。你说亏不亏?那时候我就在想,一定要在实验设计阶段就把 PCR 循环控制好。
小技巧:
如果你用的是 10x Genomics 的 Visium 数据,可以检查一下 possorted_genome_bam.bam 中每张标签的 UB tag 对应的 UMI 质量。如果 UMI 质量普遍低于 Q20,那就是测序仪器或试剂出了问题。
3.4 同源序列处理:一个 UMI 漏网之鱼都不能放过
好,讲到这里,我们进入最麻烦的一个环节——同源序列处理。什么是同源序列?简单说就是:两个或更多不同的 UMI,它们原本来自同一个 mRNA 分子,但由于 UMI 扩增或测序过程中产生了 1~2 个碱基的变异,导致它们看起来像是不同的 UMI。
举个例子:
原始 UMI: ATCGATCG
错误 UMI1: ATCGATCC (最后一个碱基 T→C)
错误 UMI2: ATCGATCG (正确)
错误 UMI3: ATCGATCA (最后一个碱基 T→A)
如果不去管同源序列,这些看起来是 3 个不同的 UMI,但其实是同一个分子被重复统计了。结果就是:你的 UQI 比实际还要虚高,但基因表达量却被低估了,因为同一个分子被分到了多个桶里。
怎么处理?我推荐的做法是 Hamming 距离 ≤ 1 的 UMI 合并。意思是:如果两个 UMI 的序列差异不超过 1 个碱基,就把它们视为同一个分子,合并并保留质量更高的那一条。
具体的处理流程,我在一个项目中写了个小脚本:
# 伪代码示例:同源 UMI 合并
# 输入:按 CB + Gene 分组的 UMI 集合
# 输出:合并后的唯一 UMI 列表
def dedup_umi_similar(umi_set, max_hamming_distance=1):
"""
基于 Hamming 距离合并相似 UMI
"""
import itertools
# 按 UMI 质量排序(降序)
sorted_umis = sorted(umi_set, key=lambda x: x.quality, reverse=True)
final_umis = []
used = set()
for umi in sorted_umis:
if umi.seq in used:
continue
# 查找与当前 UMI 差异 ≤ 1 的所有邻居
for other_umi in sorted_umis:
if other_umi.seq in used:
continue
if hamming_distance(umi.seq, other_umi.seq) <= 1:
used.add(other_umi.seq)
# 只保留质量最高的那个(已在 sorted_umis 中排好)
final_umis.append(umi.seq)
return final_umis
嗯,这里要注意:Haming 距离的阈值设置要谨慎。我之前设过 2,结果把一些确实不同的稀有分子也合并了,导致假阴性。现在我一般用 1,除非数据质量极差(UMI 错误率 > 5%)才考虑放宽到 2。
避坑指南:
我曾经遇到过一个坑:某批次数据 UMI 长度是 10 bp,但我用的去重工具默认了 8 bp 的 UMI 长度。结果所有 UMI 的最后 2 个碱基都被截断了,去重时错把很多不同分子合并了。那个项目的 UQI 明明很高,但下游分析却一塌糊涂——最后排查了整整两天才发现是参数问题。所以,一定要确认 UMI 长度和你的工具配置一致。
3.5 总结一下本章重点
好了,内容不少,我来帮你收一下:
- UMI 去重的核心是把「同分子多 read」合并成一条,减少 PCR 冗余。
- UQI(有效 UMI 比例)是衡量文库复杂度最直接的指标,建议保持在 0.35 以上。
- 低 UQI 排查方向:PCR 循环 > 测序深度 > 碱基质量。
- 同源序列处理要善用 Hamming 距离 ≤ 1 的合并策略,但不要过拟合。