4. 测序数据(FASTQ)质量控制基础

FASTQ 质控,听起来像是 pipeline 里的例行公事。很多新手拿到数据直接就跑 spaceranger,结果要么比对率低得可怜,要么基因表达矩阵里全是背景噪声。我最初做 Visium 项目时就吃过这个亏——跑了三天,最后一看报告,30% 的 reads 都没比对上去。后来回头补做质控,才发现是接头污染和质量过低导致的。从那以后,我再也不敢跳过这步了。

4.1 FASTQ 文件长什么样?

先快速回顾一下 FASTQ 格式,每四条记录为一组:

  • 第一行:@ 开头,ID+注释
  • 第二行:原始序列(A/T/C/G/N)
  • 第三行:+ 分隔符(通常只有 +)
  • 第四行:质量值字符串,每个字符代表一个碱基的质量(Phred+33 编码)
记住:第四行长度必须和第二行完全一致,否则是损坏的 FASTQ。我用过的所有质控工具都会自动校验这个。

4.2 常见质量“陷阱”

Visium 的文库制备有其特殊性:poly-A 捕获 + 空间条形码连接。这导致三个常见问题:

  1. 低质量尾巴 —— 测序仪读到末端时荧光信号衰减,3′ 端质量尤其差。
  2. 接头污染 —— 空间条形码和 UMI 连接引物未完全去除,会干扰比对。
  3. 重复序列过多 —— PCR 扩增导致的 duplication,影响基因定量。
问题类型诱因后果
低质量碱基(Q<20)测序仪末端衰减错配率高,比对失败
接头残留文库纯化不够read 被错误截断或比对到接头序列
GC biasPCR 扩增偏好部分基因被低估或高估
N 含量过高测序错误或 base caller 无法判定比对时 soft-clip 增多
警告:千万不要只看平均质量就放行。我记得有一次整体平均 Q>30,但 read 前 20 bp 全部低于 Q15,结果 spaceranger 根本认不出 spot 条形码。必须逐位置检查。

4.3 我的质控工具选型

我习惯用这三个工具的配合:

  • FastQC —— 快速生成 HTML 项目报告,各模块一目了然。
  • MultiQC —— 汇总所有样本的 FastQC 结果,适合横向对比。
  • Cutadapt —— 专门用来去接头和质量修剪,灵活且快。

运行 FastQC 极其简单:

fastqc sample_R1.fastq.gz sample_R2.fastq.gz -o fastqc_output/

输出会得到一个 .html 和一个 .zip。打开 HTML,我通常按这个顺序筛查:

  1. Per base sequence quality —— 看第一个 box plot 是否在绿色区域。
  2. Per sequence GC content —— 理想曲线是近似正态分布,如果出现双峰可能意味着污染。
  3. Overrepresented sequences —— 如果出现在前 10 名且占比 >1%,多半是接头或 rRNA。
  4. Adapter content —— 直接告诉你哪一类接头需要去除。

快速参考表:FastQC 核心指标评判

模块PASS(优秀)WARN(注意)FAIL(必需处理)
Per base quality所有位置中位数 Q≥28有位置中位数 20–28有位置中位数 <20
Per sequence GC content与理论曲线偏差 <15%偏差 15–30%偏差 >30% 或双峰
Adapter content任何接头占比 <0.1%0.1–1%>1%
Overrepresented seq无超过 0.1% 的序列有 0.1–1%有 >1%

4.4 修剪策略与实战命令

拿到 FastQC 报告后,我开始写修剪脚本。基本思路:去接头 → 质量裁剪 → 最小长度过滤。Cutadapt 可以一条命令搞定:

cutadapt -a AGATCGGAAGAGCACACGTCTGAACTCCAGTCA \
         -A AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGT \
         -q 20,20 \
         --minimum-length 50 \
         -o clean_R1.fastq.gz \
         -p clean_R2.fastq.gz \
         raw_R1.fastq.gz raw_R2.fastq.gz

参数说明:

  • -a / -A:R1 和 R2 的 adapter 序列。
  • -q 20,20:两端 5′→3′ 滑动窗口修剪,当平均质量低于 20 时切除。
  • --minimum-length 50:扔掉修剪后短于 50 bp 的 read pair。
我的小习惯:Visium 的 read 比较长(R1 一般 28 bp 空间条形码,R2 一般 50–100 bp 转录本)。如果 R1 太短不建议截太多,会损坏条形码。我会将 R1 单独用 -u -10 从 3′ 端去掉 10 bp 低质量区域,而不是用滑动窗口。

修剪完别忘了再做一次 FastQC,确认问题已解决:

fastqc clean_R1.fastq.gz clean_R2.fastq.gz -o fastqc_post/

4.5 进阶:k-mer 分析与污染排查

如果你发现 Per base GC 和 Per sequence GC 都正常,但比对率仍然偏低,可以跑 FastQC 的“Kmer Content”模块。它会列出过度表示的 k-mer(默认 7-mer)。我遇到过一例:k-mer 中出现大量 “CCCCCCC” 和 “GGGGGGG” —— 后来发现是样本中的线粒体 rRNA 污染。这种污染普通接头去不掉,需要额外用 bbmap 或 bowtie2 过滤。

方法很简单:构建一个已知污染序列库(rRNA、线粒体、phiX),用 bowtie2 直接比对并取出未比对的 reads:

bowtie2 -x contaminants_index -U clean_R2.fastq.gz \
       --un unaligned.fastq.gz -S /dev/null

然后用 unaligned.fastq.gz 跑 spaceranger。这一步我通常在质控报告里记录了 k-mer warning 之后才执行,属于“按需操作”。

4.6 关于 MultiQC 的横向对比

如果项目里有几十个样本,逐个点开 HTML 太慢。MultiQC 能汇总所有 FastQC 输出:

multiqc fastqc_output/ -o multiqc_report/

我最看重的是“General Statistics”表格 —— 一行就能看到所有样本的总 reads 数、GC 含量、Q20/Q30 比例。如果某个样本的 GC 异常偏离群体,我会单独标记它,准备深度排查。

注意:MultiQC 只是汇总,不会自动过滤样本。我建议设定一条硬线:Q30 比例 <75% 的样本直接重测或剔除,否则后期空间分析全部白做。

4.7 整章知识脉络

下面这张图概括了我日常的 FASTQ 质控流程,从原始数据到可以放心提交给 spaceranger 的干净数据:

FASTQ 质量控制流程 原始 FASTQ FastQC 检查 有问题? 是 Cutadapt 修剪 循环确认 否 干净 FASTQ → 下游 修剪后需再次 FastQC 验证问题是否解决,确认通过后才进入下游 spaceranger 分析

总结一下:质控不是跑一次工具就完了,它是一轮迭代。先跑 FastQC 看状况,再根据问题选择合适的修剪手段,最后用第二次 FastQC 确认干净。我刚开始带团队时,总有人嫌这一步耽误时间,想直接跳到比对。但你想啊,如果输入数据就有 30% 的无用 reads,后面花更多时间调试参数、怀疑算法,岂不是更亏?