3. Per base sequence quality 模块详解与阈值设定
Per base sequence quality,中文叫“每个碱基的测序质量”。这玩意儿是 FastQC 报告里最受关注的一张图,没有之一。我刚入行时,QC 报告看都不看,直接往下游跑。后来有一次,一个 RNA-seq 项目,差异基因怎么调都调不出来,最后回头一查——Per base quality 图尾端掉得一塌糊涂。嗯,从那以后我再也不敢跳过这张图了。
说白了,这张图展示的是测序 reads 里每个位置(从第一个碱基到最后一个)的质量分布。横轴是碱基位置(1-based),纵轴是质量分数(Phred score)。图上能看到箱线图、均值线,还有三条参考线:绿线(Q28)、橙线(Q20)、红线(Q10)。FastQC 默认把 Q28 以上标为绿色“好”,Q20~Q28 标为橙色“还行”,Q10~Q20 标为黄色“一般”,Q10 以下标为红色“差”。
3.1 这张图到底在告诉你什么?
很多新手以为只要整条 read 平均质量够高就行。但 Per base quality 图能暴露一个关键问题:测序质量是否均匀。我见过不少项目,整体平均 Q30 高达 90%,但读长末尾 20 个碱基质量直接掉到 Q15 以下。这种情况,下游的 SNP calling 和拼接会非常惨。
下面这张图总结了 Per base quality 审计的核心决策逻辑:
3.2 怎么读图?关键要看三个指标
我个人解读这张图时,会按以下三个维度快速扫描:
- 中位数线(图上粗的黑线):代表该位置上所有 read 质量的中位数。如果中位数掉到 Q20 以下,这个位置就得警惕。
- 箱体高度:箱体的上下四分位距(IQR)反映该位置的质量波动。箱体越宽,说明不同 read 在该位置的质量差异越大。我见过有的数据,前 50bp 箱体很窄,到 100bp 突然炸开——这种通常意味着模板长度不均一。
- 离群点(箱线图上的小圈):代表异常低质量的 read。如果离群点大量出现,说明文库中混入了低质量片段。
经验技巧:建议先看 末端的 10% 区域。比如 150bp 的 read,重点关注 135~150bp。这块是质量衰减最明显的地方。如果末端中位数还在 Q25 以上,基本问题不大。
3.3 审计阈值怎么设?别再只用 FastQC 默认线
FastQC 内置的颜色规则(绿/橙/红)只是一个快速参考,不能作为生产环境的审计阈值。我参与过好几个大型测序项目,逐渐总结出一套更实用的阈值体系。直接上表:
| 阈值等级 | 判断条件 | 建议动作 |
|---|---|---|
| PASS | 所有位置的箱线图中位数 ≥ Q25 且 IQR 下沿 ≥ Q15(即 25% 分位数 ≥ Q15) |
无需截断,直接用于全部下游分析 |
| WARN | 存在 1~5 个位置 的中位数在 Q15~Q20 之间 或 25% 分位数在 Q8~Q15 之间 |
考虑截断尾部 5~10 bp,或使用软修剪 (如 Trimmomatic 的 SLIDINGWINDOW) |
| FAIL | 存在任意位置中位数 < Q15 或 25% 分位数 < Q8 或箱体高度超过 Q20 跨度(即 IQR > 20) |
必须截断到质量稳定区域,或返回湿实验排查原因 |
重点强调:我在审计标准化流程时,把 WARN 和 FAIL 的边界收紧了一档。为啥?因为很多项目误判往往出在“看起来还行但实际不行”的灰色区域。比如某个位置中位数 Q18,但 25% 分位数已经掉到 Q6 了,这时候如果只看中位数可能会漏判。所以我们生产线置的硬规则是:任意位置 25% 分位数 < Q10 直接判 FAIL,不管中位数是多少。
3.4 常见陷阱与避坑
- 陷阱一:只看平均值。 平均值会被高质量碱基拉高,掩盖了末尾的剧烈下降。务必看箱线图的中位数和四分位数。
- 陷阱二:忽略文库类型。 我做过一个 Amplicon 项目,Per base quality 图显示整条 read 质量都很好,但中间有一段质量骤降。这是因为引物二聚体导致的局部失败。如果只看头尾,完全发现不了。
- 陷阱三:盲目截断固定长度。 我曾经接手过一个项目,QC 报告尾部质量确实下降,但只下降了 3bp。操作员直接硬截了 50bp,损失了大量有效数据。其实这种情况保留 147bp 完全够用。
3.5 实操:用命令行快速抓取 Per base quality 数据
FastQC 的网页报告只能看个大概。要大规模审计时,我更习惯用 fastqc -o outdir --extract 把 zip 包解出来,然后直接读 fastqc_data.txt。里面有一节叫 Per base sequence quality,每一行就是一个位置的质量统计。
# 提取每个位置的质量统计
grep -A 100 "Per base sequence quality" fastqc_data.txt | tail -n +2 | head -N
# 示例输出(150bp read 前几行):
# Base Mean Median Lower Quartile Upper Quartile 10th Percentile 90th Percentile
# 1 37.25 38.0 36.0 39.0 34.0 40.0
# 2 37.30 38.0 36.0 39.0 34.0 40.0
# ...
# 149 27.10 28.5 19.0 34.0 15.0 36.0
# 150 24.85 25.0 16.0 32.0 12.0 34.0
拿到这些数值后,写个简单的脚本就能自动判定 PASS/WARN/FAIL。我个人用 Python 写过一个审计函数,核心就二十行:
def audit_per_base_quality(data, median_threshold=20, lower_q_threshold=10):
"""
data: list of dicts with keys 'median', 'lower_quartile'
返回: ('PASS'|'WARN'|'FAIL', 失败位置列表)
"""
fail_positions = []
warn_positions = []
for idx, row in enumerate(data, start=1):
median = row['median']
lower_q = row['lower_quartile']
if median < 15 or lower_q < 8:
fail_positions.append(idx)
elif median < 20 or lower_q < 10:
warn_positions.append(idx)
if fail_positions:
return 'FAIL', fail_positions
elif warn_positions:
return 'WARN', warn_positions
else:
return 'PASS', []
⚠️ 注意:上面的阈值是我针对 Illumina 2×150 PE 测序平台定的。如果你用的是 PacBio 或 Nanopore,质量体系完全不同,阈值需要重新标定。我曾帮一个团队把同样的脚本跑在 PacBio HiFi 数据上,结果全是 FAIL——因为 HiFi 的质量分数定义与 Illumina 不同,不能直接套用。
3.6 本章小结:你需要记住这三点
- 看分布,不看平均。 中位数和四分位数比平均值更可靠。
- 硬性指标设双保险。 中位数 < Q15 或下四分位 < Q10 都是 FAIL 信号。
- 落地自动化脚本。 别手动翻网页,用
fastqc_data.txt写个审计函数,每次跑流水线自动出判定。
Per base sequence quality 是质控的门神。这块看得准,后面一马平川;这块放松了,下游分析无异于沙上建塔。我个人的实验室准则就是:Per base quality 没通过审计的数据,不送下游分析管线。哪怕它是来自顶刊的合作项目。