跨界科研笔记|用计组与通信编码读懂单细胞 R1/R2/I1 测序架构
前序知识(生物信息部分)
单细胞测序数据流
┌─────────────────────────────────────────────────────────────────────┐
│ 单细胞测序数据流 │
├─────────────────────────────────────────────────────────────────────┤
│ 原始测序数据 (FASTQ) │
│ ├─ R1: [16bp Barcode][12bp UMI] ← "地址标签"(谁 + 哪个分子) │
│ ├─ R2: [cDNA 序列 ~50-100bp] ← "实际数据"(基因序列) │
│ └─ I1: [6-8bp Index] ← "样本标签"(多样本时用) │
├─────────────────────────────────────────────────────────────────────┤
│ Cell Ranger 处理 │
│ ├─ 1. 用 Barcode 把 reads 分组到细胞(进程调度) │
│ ├─ 2. 用 UMI 去重(PCR 拷贝只算一次) │
│ ├─ 3. 把 R2 比对到参考基因组(虚拟地址 → 物理地址) │
│ └─ 4. 统计每个细胞每个基因的 UMI 数 │
├─────────────────────────────────────────────────────────────────────┤
│ 输出: 表达矩阵 (genes × cells) │
│ ├─ barcodes.tsv: 细胞列表(进程表) │
│ ├─ features.tsv: 基因列表(系统调用表) │
│ └─ matrix.mtx: 稀疏表达矩阵(每个进程的内存使用统计) │
└─────────────────────────────────────────────────────────────────────┘
原始测序数据FASTQ(测序仪直接输出的原始文件)
- 以上的 R1 /R2 /I1 并非需要同时出现
- FASTQ 文件的"配对"取决于测序策略
核心原则:一个 DNA 片段产生几条 reads,就有几个 FASTQ 文件
| 测序策略 | 文件组合 | 说明 |
|---|---|---|
| 单端测序 (Single-end) | 只有 R1 | 只从一端读一次 |
| 双端测序 (Paired-end) | R1 + R2 | 从两端各读一次 |
| 双端 + 单 Index | R1 + R2 + I1 | 双端 + 1 个样本标签 |
| 双端 + 双 Index | R1 + R2 + I1 + I2 | 双端 + 2 个样本标签(i5 + i7) |
10x Genomics 单细胞的实际情况为例:
- 标准 10x 单细胞(如 3’ Gene Expression)——最少 2 个,最多 3 个(单 Lane 情况下)
📁 fastqs/
├── sample_S1_L001_R1_001.fastq.gz ← 必有:Barcode + UMI
├── sample_S1_L001_R2_001.fastq.gz ← 必有:cDNA 序列
└── sample_S1_L001_I1_001.fastq.gz ← 可选:样本 Index(多样本混测时)
- 10x 多样本混测(Cell Multiplexing)——使用 CMO(Cell Multiplexing Oligo) 时,每个细胞自带一个标签,不需要 I1:
📁 fastqs/
├── sample_S1_L001_R1_001.fastq.gz
└── sample_S1_L001_R2_001.fastq.gz
样本区分信息在 R1 的 CMO 序列 里,不需要额外的 I1 文件。
Notes:不是R1/R2/I1 “三种配对”
一个 DNA 片段
│
┌───────┴───────┐
│ │
双端测序 单端测序
│ │
R1 + R2 只有 R1
│ │
┌─┴─┐ (无配对)
│ │
有Index? 无Index?
│ │
├─ 是 → +I1 └─ 只有 R1
│ (+I2双Index)
└─ 否 → 只有 R1+R2
- 常见类型总结
| 场景 | 文件数 | 组成 |
|---|---|---|
| 单端、无 Index | 1 | R1 |
| 单端、有 Index | 2 | R1 + I1 |
| 双端、无 Index | 2 | R1 + R2 |
| 双端、单 Index | 3 | R1 + R2 + I1 |
| 双端、双 Index | 4 | R1 + R2 + I1 + I2 |
| 10x 单细胞标准 | 2-3 | R1 + R2 (+ I1) |
“一般 fastq 有三种配对的文件,R1/R2/I1”
- 双端测序产生 R1 和 R2 两个文件,它们是一对相互配对的 reads(来自同一个 DNA 片段的两端)
- I1 不是 R1/R2 的"配对",而是独立的 Index read,用于样本拆分
- 有些实验根本没有 I1(单样本测序),有些有 I1+I2(双端 Index)
R1 和 R2 是"物理配对"(来自同一 fragment),I1 是"逻辑标签"(用于区分样本),两者性质不同。
互通逻辑1:原始测序数据R1/R2/I1 = 指令格式中的不同字段
1. 计算机组成原理中的一条机器指令:
┌─────────┬─────────┬─────────┬─────────┐
│ 操作码 │ 源操作数1 │ 源操作数2 │ 目的地址 │
│ (Opcode) │ (Src1) │ (Src2) │ (Dest) │
└─────────┴─────────┴─────────┴─────────┘
2. 10x 测序中,一个DNA 片段的"读取指令"被拆分成三条 reads:
┌─────────────────────────────────────────────────────────────┐
│ 一个 DNA 片段 = 三条 Reads │
├─────────────────────────────────────────────────────────────┤
│ I1 (Index Read) │
│ ┌─────────────────┐ │
│ │ 6-8 bp Index │ ← "样本选择信号" / 多路复用器选择端 │
│ │ = 样本标签 │ 类似:内存地址的高位(体选信号) │
│ └─────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ R1 (Read 1) │
│ ┌──────────────────────────────────┐ │
│ │ [16bp Cell Barcode][12bp UMI] │ ← "地址字段" │
│ │ = 细胞ID + 分子ID │ 类似:内存地址+序列号 │
│ └──────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ R2 (Read 2) │
│ ┌────────────────────────────────────┐ │
│ │ ~50-100 bp cDNA 序列 │ ← "数据字段" │
│ │ = 实际的基因序列 │ 类似:操作数/数据 │
│ └────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
3. 多层类比
- 第一层:R1 = 地址总线,R2 = 数据总线
| 测序组件 | 计算机组成原理概念 | 解释 |
|---|---|---|
| R1 | 地址总线 (Address Bus) | 只传"去哪里"的信息(哪个细胞、哪个分子),不传实际数据 |
| R2 | 数据总线 (Data Bus) | 只传"是什么"的信息(基因序列),不带地址标签 |
| I1 | 体选信号 / Bank Select | 多样本混测时,选择"当前数据属于哪个样本" |
就像 内存读取操作:CPU 先发送地址(R1),然后内存返回数据(R2)。地址和数据走不同的总线,不会混在一起。
- 第二层:R1 = 页表项,R2 = 物理页内容
用虚拟内存系统来类比:
┌──────────────────────────────────────────────────────────────┐
│ 虚拟内存 ↔ 单细胞测序 │
├──────────────────────────────────────────────────────────────┤
│ 虚拟地址 (Virtual Address) │
│ ├─ VPN (Virtual Page Number) = Cell Barcode │
│ │ → 标识"这个数据属于哪个进程(细胞)" │
│ └─ Offset = UMI + 序列位置 │
│ → 标识"这是进程内的哪个具体位置(哪个分子)" │
├──────────────────────────────────────────────────────────────┤
│ 页表 (Page Table) = Cell Ranger 的 Barcode 映射表 │
│ ├─ 输入: Cell Barcode (16bp) │
│ └─ 输出: Cell ID (如 Cell_001, Cell_002...) │
├──────────────────────────────────────────────────────────────┤
│ 物理页 (Physical Page) = 参考基因组上的基因位置 │
│ └─ R2 的序列比对到基因组后,确定"这个基因在哪个染色体位置" │
├──────────────────────────────────────────────────────────────┤
│ TLB (快表) = Cell Ranger 的内存缓存 │
│ └─ 常用 Barcode 直接查缓存,不用每次都遍历映射表 │
└──────────────────────────────────────────────────────────────┘
R1 的作用 = 页表查询的 key:
没有 R1,你不知道这条 reads 属于哪个细胞(就像没有虚拟地址,你不知道数据属于哪个进程)
- R1 本身不包含"内容",只包含"地址信息"
- 第三层:R1 = 标签字段,R2 = 数据字段(Cache Line 视角)
现代 CPU 的 Cache Line 通常包含:
┌─────────┬─────────────────────┐
│ Tag │ Data │
│ (标记) │ (数据) │
│ 用于匹配 │ 实际存储的内容 │
└─────────┴─────────────────────┘
在 10x 测序中:
┌─────────────────────────────────────────────────────────────┐
│ Cache Line = 一个 DNA 片段 │
├─────────────────────────────────────────────────────────────┤
│ Tag 字段 (R1 + I1) │
│ ├─ I1: 样本 Index → "属于哪个 Cache 组(样本)" │
│ ├─ Barcode: 细胞 ID → "属于哪个 Cache 行(细胞)" │
│ └─ UMI: 分子 ID → "这个 Cache 行的版本号(去重用)" │
├─────────────────────────────────────────────────────────────┤
│ Data 字段 (R2) │
│ └─ cDNA 序列 → "Cache 行中存储的实际数据" │
│ 比对到参考基因组后,确定"这个数据是什么基因" │
└─────────────────────────────────────────────────────────────┘
UMI = 时间戳/版本号:PCR 扩增会产生多个相同的拷贝,UMI 就像 MESI 协议中的状态标记,用于识别"这是同一个原始数据的副本",去重时只保留一个。
- 第四层:R1/R2 分离 = 哈佛架构 vs 冯·诺依曼架构
| 架构 | 特点 | 类比 |
|---|---|---|
| 冯·诺依曼 | 指令和数据共享同一总线 | 如果 R1 和 R2 混在一起,需要额外解析 |
| 哈佛架构 | 指令和数据分开存储、分开传输 | R1(地址/控制)和 R2(数据)物理分离 |
10x 测序采用的是"类哈佛架构":
- R1 走一条测序通道(只读 barcode + UMI)
- R2 走另一条测序通道(只读 cDNA)
- 两条通道并行,互不干扰
好处:R1 可以读得更短(28bp),R2 可以读得更长(50-100bp),就像 哈佛架构中指令缓存和数据缓存可以独立优化。
对应关系
| 测序概念 | 计算机组成原理概念 | 解释 |
|---|---|---|
| R1 | 地址总线 + 控制总线 | “这条数据给谁、是第几个副本” |
| R2 | 数据总线 | “这条数据的内容是什么” |
| I1 | 片选信号 / Bank Select | “这批数据属于哪个芯片(样本)” |
| Barcode | 虚拟页号 (VPN) | 映射到具体的细胞(进程) |
| UMI | 序列号 / 时间戳 | 用于去重的唯一标识 |
| 参考基因组 | 物理地址空间 | 所有可能的基因位置的总和 |
| 比对 (Alignment) | 地址转换 (MMU) | 把虚拟地址(序列)转成物理地址(基因组坐标) |
4. CPU 取指执行的流程类比
CPU 执行指令 ↔ Cell Ranger 处理 reads
─────────────────────────────────────────────────────────────
1. PC 发出地址 ↔ R1 提供 Barcode(虚拟地址)
2. MMU 查页表 ↔ 查 Barcode→Cell 映射表
3. 从内存取指令 ↔ 根据 Barcode 把 reads 分到对应细胞
4. 指令译码 ↔ R2 序列比对到参考基因组
5. 执行运算 ↔ 统计 UMI,去重,生成表达量
6. 写回结果 ↔ 写入表达矩阵
R1 是"地址和控制阶段",R2 是"数据执行阶段"——两者分离,流水线才能高效运转。
互通逻辑2: Index样本标签设计 与 通信容错编码设计
1. Index 不是随机命名的,是精心设计的"纠错码"
一个真实的 Index 序列示例(Illumina Nextera 接头):
| Index 名称 | 序列 | 用途 |
|---|---|---|
N701 |
TAAGGCGA |
样本 1 |
N702 |
CGTACTAG |
样本 2 |
N703 |
AGGCAGAA |
样本 3 |
N704 |
TCCTGAGC |
样本 4 |
N705 |
GGACTCCT |
样本 5 |
N706 |
TAGGCATG |
样本 6 |
| … | … | … |
这些序列不是随机的,而是经过算法优化的,满足以下数学约束:
2. 保证不重复的三大设计原则
原则一:汉明距离(Hamming Distance)≥ 2
汉明距离:两个等长字符串,对应位置不同字符的个数。
N701: TAAGGCGA
N702: CGTACTAG
↑↑↑↑↑↑↑↑
8 个位置全不同 → 汉明距离 = 8
N701: TAAGGCGA
N703: AGGCAGAA
↑↑↑↑↑↑↑↑
位置1,2,3,5,6,7,8不同 → 汉明距离 = 7
设计要求:任意两个 Index 之间的汉明距离 ≥ 2(通常 ≥ 3 或 4)
为什么?
假设测序时某个碱基读错了(Q20 意味着 1% 错误率):
- 如果汉明距离 = 1:一个碱基错误就会导致误判为另一个样本
- 如果汉明距离 = 2:一个碱基错误后,仍然最近的是原序列,不会误判
- 如果汉明距离 = 3:可以纠正 1 个错误(纠错码原理)
类比计算机:就像 RAID 的校验位 或 ECC 内存 —— 用冗余度换取容错能力。
原则二:碱基组成平衡(Color Balance)
Illumina 测序是基于荧光信号的,每个循环(cycle)同时读取所有 cluster:
Cycle 1: 所有 cluster 的第一个碱基同时被激发荧光
Cycle 2: 所有 cluster 的第二个碱基同时被激发荧光
...
问题:如果某个 cycle 上某个碱基(如 A)占比过高,荧光信号会饱和,导致信号串扰(cross-talk)。
设计要求:每个 Index 序列中,A/T/C/G 的比例尽量接近 25%。
好的 Index: CGTACTAG → C:25%, G:25%, T:25%, A:25%
差的 Index: AAAAAAAA → A:100%(信号饱和,无法区分)
类比计算机:就像 时钟信号的占空比 —— 50% 占空比最稳定,0% 或 100% 会导致时钟恢复失败。
原则三:无连续重复碱基(Homopolymer 限制)
差的 Index: AATTTTGG → 连续 4 个 T
好的 Index: CGTACTAG → 无连续重复超过 2 个
原因:连续相同碱基会导致信号相位漂移(phasing) —— 测序仪在不同 cycle 之间"失步"。
类比计算机:就像 曼彻斯特编码 或 8b/10b 编码 —— 避免长串的 0 或 1,保证时钟恢复。
3. Index 的设计算法
Illumina 的 Index 序列是通过组合优化算法生成的:
目标:从 4^8 = 65536 个可能的 8bp 序列中,选出 N 个满足:
1. 两两汉明距离 ≥ d(通常 d=3)
2. 每个序列内部碱基平衡
3. 无长串重复碱基
4. 与接头序列无互补(避免形成发夹结构)
这是一个典型的"球包装问题"(Sphere Packing Problem)
类比计算机:就像 CDMA 的扩频码设计 —— 从巨大的码空间中选出正交性好的码组,保证多用户同时通信不干扰。
4. 实际拆分流程(Demultiplexing)
混合测序数据(所有样本混在一起)
│
▼
┌─────────────────────────────────────┐
│ 读取每条 reads 的 I1(或 I1+I2) │
│ 例如:读到 ATCACG │
├─────────────────────────────────────┤
│ 与已知的 Index 列表进行比对 │
│ ATCACG ──匹配──→ 患者1 │
│ CGATGT ──匹配──→ 患者2 │
│ TTAGGC ──匹配──→ 患者3 │
│ GATCGA ──匹配──→ 患者4 │
├─────────────────────────────────────┤
│ 允许错配(Mismatch) │
│ 如果读到 ATTAGG(与 ATCACG 差1位) │
│ → 汉明距离=1,最近的是 ATCACG │
│ → 判定为患者1(纠错成功) │
│ │
│ 如果读到 AAAAAA(与所有 Index 差很多) │
│ → 无法匹配,丢弃或归入 "Undetermined" │
└─────────────────────────────────────┘
Cell Ranger / bcl2fastq 的拆分逻辑:
# 配置文件 samplesheet.csv
Lane,Sample_ID,index
1,Patient_1,ATCACG
1,Patient_2,CGATGT
1,Patient_3,TTAGGC
1,Patient_4,GATCGA
软件会:
- 读取每个 reads 的 I1 序列
- 计算与所有已知 Index 的汉明距离
- 选择距离最小的匹配
- 如果最小距离 > 阈值(如 1),则丢弃
5. 为什么不会重复?数学保证
- 组合数学角度
8bp Index 的总空间:4^8 = 65,536 种可能
实际使用的 Index 数量:
- 单端 Index(I1):通常 12-24 个
- 双端 Index(I1+I2):8×8 = 64 个组合,或 96×96 = 9,216 个组合
即使使用 96 个 Index,也只占用了 65,536 的 0.15%
设计时通过算法保证:
- 任意两个 Index 的汉明距离 ≥ 3
- 这意味着:即使 1 个碱基测错,仍然能正确归属
- 错误归属的概率极低(< 0.1%)
6. 类比总结
| 概念 | 计算机/通信类比 | 解释 |
|---|---|---|
| Index 序列 | CDMA 扩频码 | 多个信号共享同一信道,用正交码区分 |
| 汉明距离 ≥ 3 | ECC 纠错码 | 汉明码可以纠正 1 位错误 |
| 碱基平衡 | 时钟恢复编码(8b/10b) | 避免长串同符号,保证信号同步 |
| 无连续重复 | 游程长度限制(RLL) | 硬盘编码避免长串 0/1 |
| Demultiplexing | 路由器根据 VLAN Tag 分流 | 根据标签把混合流拆分到不同端口 |
| Undetermined reads | CRC 校验失败的帧丢弃 | 无法匹配的 reads 丢弃,保证 purity |
“为什么可以通过 Index 区分样本,怎么保证不重复?”
I1/I2的Index 不是随机的,而是像 CDMA 码或 ECC 码一样,通过数学算法精心设计的。它们在序列空间中彼此"远离"(汉明距离大),即使测序有错误也能正确归属,就像纠错内存能自动纠正位翻转一样。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)