FASTQ 文件结构与质量控制:序列、质量值、Phred 编码详解
真正开始跑一个空间转录组 pipeline 之前,有一件事我劝你别偷懒——搞懂 FASTQ 文件。
这玩意儿看着就是个四行一组的文本块,很多人直接扔进上游工具就完事了。但我见过太多 case 了:因为质量值编码搞错,整个比对结果全是垃圾;因为 adapter 没切干净,导致聚类图上一堆莫名其妙的噪音。嗯,这块我们得说透。
FASTQ 的四行结构
每一份 FASTQ 记录都包含四行,这是硬性规定。缺一行或顺序乱了,下游工具直接报错。
@EAS139:136:FC706VJ:2:2104:15343:197393 1:Y:18:ATCACG
CTCAAGTTGTCAGCAATGGTGGTGCAATTGGCAGGATGAATATTA
+
B@@FFFFFHHHHHJJJJJJIIIIIIJJJJJJJJIJJJJJJJJJJJH
| 行号 | 标识符 | 内容 |
|---|---|---|
| 第1行 | @ | 序列标识 + 可选注释(如流道位置、barcode) |
| 第2行 | — | 碱基序列(A/T/C/G/N) |
| 第3行 | + | 分隔符,有时跟第1行相同的ID |
| 第4行 | — | 质量值字符串,与第2行碱基一一对应 |
head -n 40 看一眼,确认第四行全是可打印字符,没有换行符乱入。有一次我从云盘下数据,第四行被中间截成两段——后来查出来是传输过程没加 -b 选项搞的。
质量值是什么?
每个碱基的质量值代表这个碱基被测序仪判定正确的概率。说白了就是测序仪自己给的“信心指数”。
质量值的数学定义很简单:
Q = -10 × log₁₀(P)
其中 P 是错误概率。比如 Q=30 表示错误概率 0.001,也就是一千个碱基里大概错一个。
Phred 编码——小心这个坑
质量值存到文件里不直接存数字,而是用 ASCII 字符表示。不同时代、不同测序平台用的编码偏移不一样。
Phred+33: ASCII码 = Q + 33 (Illumina 1.8+,当前主流)
Phred+64: ASCII码 = Q + 64 (早期 Illumina/Solexa,已淘汰)
举个例子,质量值 Q=30,在 Phred+33 下存为 ASCII 码 63(即字符 ?),而在 Phred+64 下存为 ASCII 码 94(即字符 ^)。
fastqc 看 per base sequence quality 图,如果中位数低于 10 或者出现断崖式下降,十有八九是编码问题。
质量控制:从 FASTQ 到干净数据
我一般把 QC 分成三个关卡:
- 基础统计——总读段数、碱基数、GC含量、是否存在过表达序列(adapter)。
- 质量过滤——切除低质量尾部、去掉太短的读段、去除 N 碱基过多的读段。
- adapter 切除——尤其是空间转录组的 read1 包含 barcode/UMI,要特别注意不要误切。
常用的工具组合:
# 推荐流程:先用 FastQC 看报告
fastqc sample_R1.fastq.gz sample_R2.fastq.gz -o qc_reports/
# 然后用 fastp 一站式处理(质量过滤 + adapter 切除 + 统计报告)
fastp -i sample_R1.fastq.gz -I sample_R2.fastq.gz \
-o clean_R1.fastq.gz -O clean_R2.fastq.gz \
--detect_adapter_for_pe \
--cut_front --cut_tail \
--qualified_quality_phred 20 \
--unqualified_percent_limit 40 \
--length_required 50 \
--json fastp_report.json
为什么我偏爱 fastp?
- 一步到位,不需要先 adapter 识别再调用 cutadapt
- 支持 per-read 质量裁切,比滑动窗口更敏感
- 自动检测双端 adapter 方向
- 输出 JSON/HTML 报告,方便集成到 pipeline
从质量控制到 Visium 聚类前的预处理
Visium 空间转录组是双端测序:R1 通常只读 28bp(包含 16bp barcode + 12bp UMI),R2 读 91bp(基因序列)。这意味着 adapter 位置是固定的,不像是 RNA-seq 那样 adapter 随机出现。所以你想想看,如果 R1 被错误切掉几个碱基,barcode 就全乱了,后续聚类就等于瞎猜。
--cut_front,可能导致 barcode 被切掉前几个碱基。我个人建议在 fastp 命令中显式使用 --cut_front 0 来避免这个问题,或者单独处理 R1 和 R2。下图展示了我每次做空间转录组 QC 时脑子里过的流程:
实战检查清单
我每次新到一个项目,都会拿下面这个清单过一遍,避免低级错误:
| 检查项 | 工具/方法 | 合格指标 |
|---|---|---|
| 编码类型确认 | FastQC 的 per base sequence quality 图 |
中位数 Q 值落在 20-40 范围,无底层平台偏移 |
| GC 含量异常 | FastQC / fastp 报告 |
正态分布,无明显双峰或偏移 |
| adapter 残留 | FastQC 的 Overrepresented sequences |
adapter 占比 < 1% |
| Barcode 分配率 | 先跑 spaceranger mkfastq 看指标 |
分配率 > 75%(我的经验:低于 60% 要重做 QC) |
| 双端读段配对完整性 | wc -l 对比 R1/R2 行数 |
行数相等,R1 总读段 = R2 总读段 |
! 到 I 之间(ASCII 33-73),大概率是 Phred+33;如果包含很多 B 到 h 之间的字符(ASCII 66-104),可能是 Phred+64(旧数据)。我的做法是用 python 读一行看看最小 ASCII 码:head -n 4 sample.fastq | tail -n 1 | od -An -tuC | awk '{min=$1; for(i=1;i<=NF;i++) if($i
如果最小值 33 就是普通 Phred+33;如果最小值在 59-64 之间,说明是旧版编码。
嗯,到这里 FASTQ 结构、质量值、Phred 编码这些基础你应该有底了。质量控制这块我强调再多也不为过——数据进 pipeline 之前多花 10 分钟检查,后面能省下好几天排查 bug 的时间。接下来我们继续往下走,看看这些干净的 FASTQ 数据如何和参考基因组对上号。