前序知识(生物信息部分)

单细胞测序数据流

┌─────────────────────────────────────────────────────────────────────┐
│                         单细胞测序数据流                              │
├─────────────────────────────────────────────────────────────────────┤
│  原始测序数据 (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

软件会:

  1. 读取每个 reads 的 I1 序列
  2. 计算与所有已知 Index 的汉明距离
  3. 选择距离最小的匹配
  4. 如果最小距离 > 阈值(如 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 码一样,通过数学算法精心设计的。它们在序列空间中彼此"远离"(汉明距离大),即使测序有错误也能正确归属,就像纠错内存能自动纠正位翻转一样。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐