news 2026/9/19 9:55:19

Fastp实战指南:从参数配置到批量处理,全面掌握fastq质控流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Fastp实战指南:从参数配置到批量处理,全面掌握fastq质控流程

1. 为什么我最终把质控流程全压在了Fastp上

测序数据下机之后,第一件事永远是质控。这个环节做得好不好,直接决定了后续比对率、变异检出灵敏度、甚至整个项目的成败。我见过太多人拿到fastq文件之后,随便跑个FastQC看一眼,觉得"差不多还行"就直接进入比对流程,结果后面各种报错、各种异常,回头排查半天,发现根子还是在原始数据上。

Fastp这个工具,我从它刚出来没多久就开始用,到现在基本上已经成了我处理fastq数据的首选质控方案。原因很简单:它把过去需要FastQC + Trimmomatic + cutadapt + 自写脚本才能搞定的事情,全部集成到了一个命令里,而且速度极快,多线程支持好,输出报告直观,还能自动检测adapter序列。对于日常的WGS、WES、RNA-seq数据,Fastp基本能覆盖90%以上的质控需求。

这篇文章我打算把自己这些年用Fastp的实战经验完整梳理一遍,从最基础的单端/双端处理,到UMI处理、polyG修剪、去重、与Shell脚本的配合使用,再到那些官方文档里不会写的坑和技巧。适合刚接触fastq质控的新手,也适合已经用过Fastp但想进一步榨干它性能的老手。读完你至少能做到:拿到一批fastq文件,知道该怎么设计质控方案,参数怎么调,出了问题怎么排查。

2. Fastp到底解决了什么问题:核心设计思路拆解

2.1 传统质控流程的痛点在哪里

早些年做质控,标准流程是这样的:先用FastQC跑一遍原始数据,看质量分布、GC含量、adapter污染情况;然后根据FastQC的报告,手动决定用Trimmomatic还是cutadapt做修剪;修剪完再用FastQC跑一遍确认效果;如果要做UMI处理,还得额外写脚本或者用fgbio、umi_tools这些工具。整个流程下来,光是工具之间的格式转换、参数协调就够折腾的。

更麻烦的是,Trimmomatic的adapter序列需要你自己提供,不同建库试剂盒的adapter序列还不一样,万一填错了,修剪效果大打折扣。cutadapt虽然支持自动检测adapter,但速度偏慢,而且它只管修剪,不管质量过滤和报告生成。

Fastp的设计思路就是把这些零散的需求整合起来。它内置了常见的adapter序列库,支持自动检测adapter,同时完成质量过滤、长度过滤、polyG/polyX修剪、duplication评估、overrepresentation分析,最后生成一份HTML报告和JSON格式的统计文件。一个命令搞定全流程,这就是它的核心价值。

2.2 Fastp的核心功能模块

Fastp的功能可以分成几个大块来理解:

adapter自动检测与修剪。这是Fastp最实用的功能之一。它通过对reads两端进行k-mer分析,自动识别adapter序列,不需要你手动指定。对于双端数据,它还能利用pair overlap信息来辅助判断。实测下来,对于标准建库的Illumina数据,自动检测的准确率非常高。

质量过滤与修剪。Fastp支持按碱基质量进行滑窗修剪(类似Trimmomatic的SLIDINGWINDOW),也支持按平均质量过滤整条read。默认情况下,它会从read两端向中间扫描,遇到质量低于阈值的碱基就切掉。这个逻辑比固定长度截断要合理得多。

polyG/polyX修剪。这个问题在NextSeq/NovaSeq平台上特别常见,因为双色荧光检测的原因,信号缺失时会被读成G。Fastp默认开启polyG修剪,对这类数据非常友好。polyX修剪则针对其他类型的均聚物污染。

UMI处理。Fastp支持在质控阶段直接处理UMI,包括UMI的提取、移动到read名称中、以及基于UMI的去重。这个功能对于低起始量建库、ctDNA检测等场景非常关键。

重复序列评估。Fastp会统计duplication rate,虽然它不做实际的去重操作(那是MarkDuplicates或UMI去重的事),但这个指标对于判断文库复杂度很有参考价值。

过表达序列分析。Fastp会自动检测过表达的序列,这对于发现污染、接头二聚体、rRNA残留等问题很有帮助。

2.3 为什么选择Fastp而不是其他工具

我对比过几个主流方案:

工具组合速度功能覆盖易用性报告质量
FastQC + Trimmomatic中等需手动配置adapter一般分开两份报告
FastQC + cutadapt较慢adapter检测好一般分开两份报告
Fastp全集成一条命令单份HTML报告
自写Python脚本完全自定义需自己写

Fastp在速度上的优势特别明显。它用C++编写,多线程效率高,处理一个30X的WGS样本(约60GB fastq),在16线程下大概20-30分钟就能跑完。同样的数据用Trimmomatic,时间大概要翻倍。

当然Fastp也不是万能的。它不做比对,所以不能做基于比对的污染检测;它的去重是基于UMI或序列本身的,不如Picard MarkDuplicates那么精细。但对于质控这个环节来说,Fastp已经足够好了。

3. 核心参数详解与实操配置

3.1 输入输出参数:最基础但最容易出错

Fastp的输入输出参数看起来简单,但有几个细节不注意就会踩坑。

单端数据:

fastp -i input.fq -o output.fq

双端数据:

fastp -i read1.fq -I read2.fq -o clean1.fq -O clean2.fq

注意双端模式下,read1和read2的输入输出参数大小写不同:-i-I-o-O。这个设计一开始让我很不习惯,但用多了也就记住了。

输出报告:

fastp -i input.fq -o output.fq -h report.html -j report.json

-h指定HTML报告路径,-j指定JSON报告路径。JSON报告特别有用,方便后续用脚本提取统计指标做批量汇总。

注意:Fastp默认会输出到标准输出(stdout),如果你不指定-o,结果会直接打印到终端。我第一次用的时候没注意,屏幕上刷了一大堆序列,吓了一跳。所以务必指定输出文件。

还有一个实用参数是--stdout,当你需要把Fastp接入管道时很有用:

fastp -i input.fq --stdout | other_tool

3.2 质量过滤参数:怎么设才合理

Fastp的质量过滤参数主要有这几个:

  • -q/--qualified_quality_phred:碱基质量阈值,默认15。意思是质量值低于15的碱基会被认为是"不合格"。
  • -u/--unqualified_percent_limit:一条read中不合格碱基的比例上限,默认40%。超过这个比例,整条read被丢弃。
  • -n/--n_base_limit:一条read中N碱基的数量上限,默认5。
  • -l/--length_required:修剪后read的最小长度,默认15。
  • --cut_front/--cut_tail/--cut_right:从不同方向进行质量修剪。

关于-q的设置,我的经验是:对于Illumina数据,Q15作为过滤阈值偏宽松,Q20更严格一些。但也不要设太高,Q30会导致大量数据被丢弃,尤其是read末端。一般WGS用Q15,RNA-seq用Q20,具体要看数据质量。

--cut_right这个参数值得单独说一下。它开启滑窗修剪模式,窗口大小由--cut_window_size控制(默认4),滑窗平均质量低于--cut_mean_quality(默认20)时,从窗口开始位置截断。这个逻辑和Trimmomatic的SLIDINGWINDOW很像,但Fastp的实现更快。

fastp -i input.fq -o output.fq \ -q 20 -u 30 -n 3 -l 36 \ --cut_right --cut_window_size 4 --cut_mean_quality 20

这套参数是我常用的"严格模式",适合对数据质量要求高的场景。

3.3 Adapter修剪参数:自动还是手动

Fastp默认开启adapter自动检测和修剪。相关参数:

  • -a/--adapter_sequence:指定read1的adapter序列。
  • --adapter_sequence_r2:指定read2的adapter序列。
  • --detect_adapter_for_pe:双端模式下开启adapter自动检测。

这里有个坑:双端模式下,adapter自动检测默认是关闭的!你需要显式加上--detect_adapter_for_pe。这个设计是因为双端adapter检测需要额外的计算,Fastp为了速度默认关掉了。但实际使用中,我强烈建议双端数据都加上这个参数。

fastp -i r1.fq -I r2.fq -o c1.fq -O c2.fq \ --detect_adapter_for_pe

如果你明确知道adapter序列,手动指定会更快更准:

fastp -i r1.fq -I r2.fq -o c1.fq -O c2.fq \ -a AGATCGGAAGAGCACACGTCTGAACTCCAGTCA \ --adapter_sequence_r2 AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGT

这是标准Illumina TruSeq的adapter序列。不同试剂盒的adapter可能不同,用之前最好确认一下。

还有一个参数--adapter_fasta,可以提供一个FASTA文件包含多个adapter序列,Fastp会逐一比对。对于可能混有多种adapter的样本很有用。

3.4 polyG和polyX修剪:平台特异性处理

-g/--trim_poly_g:开启polyG修剪,默认开启。--poly_g_min_len控制最小长度,默认10。

-x/--trim_poly_x:开启polyX修剪,默认关闭。--poly_x_min_len默认10。

NextSeq和NovaSeq的数据一定要保持polyG修剪开启。我遇到过好几次,用户拿着NovaSeq数据来找我,说比对率特别低,一看fastq,read末端全是G,明显是polyG问题。开启修剪后,比对率直接上去了。

对于其他平台的数据,polyX修剪可以按需开启。但要注意,polyX修剪可能会误伤真实的polyA尾巴(比如RNA-seq中),所以RNA-seq数据要谨慎使用。

3.5 UMI处理参数:低起始量建库的救星

UMI(Unique Molecular Identifier)是一段随机序列,在建库时加到每个原始DNA分子上。它的作用是标记每个原始分子,这样在后续分析中可以区分真正的生物学重复和PCR扩增产生的重复。

Fastp处理UMI的方式很灵活,支持多种UMI位置:

  • -U/--umi:开启UMI处理。
  • --umi_loc:UMI的位置,可选index1index2read1read2per_indexper_read
  • --umi_len:UMI长度。
  • --umi_prefix:UMI前缀,添加到read名称中。
  • --umi_skip:UMI后面需要跳过的碱基数。

最常见的场景是UMI在read1的前几个碱基:

fastp -i r1.fq -I r2.fq -o c1.fq -O c2.fq \ -U --umi_loc=read1 --umi_len=8 --umi_prefix=UMI

这样处理后,UMI序列会被移到read名称中,格式类似@UMI_ACGTACGT:...。后续用umi_tools或fgbio做去重时,就能直接从这个名称中提取UMI。

如果UMI在index中:

fastp -i r1.fq -I r2.fq -o c1.fq -O c2.fq \ -U --umi_loc=index1 --umi_len=8

注意:Fastp的UMI处理只是把UMI提取出来放到read名称中,它本身不做基于UMI的去重。去重需要后续用专门工具完成。这一点很多人会误解。

3.6 去重参数:什么时候该开

Fastp提供了-D/--dedup参数,开启基于序列的去重。它的逻辑是:如果两条read的序列完全相同(或者UMI相同),只保留一条。

这个功能对于去除PCR重复有一定效果,但要注意:

  • 它不基于比对位置,所以不同基因组位置但序列相同的read会被误判为重复。
  • 对于高覆盖度数据,去重会显著减少数据量。
  • 如果后续还要用MarkDuplicates,这里去重就重复了。

我的建议是:如果做了UMI,用--dedup基于UMI去重是合理的;如果没有UMI,一般不在Fastp阶段去重,留给后续的MarkDuplicates处理。

fastp -i r1.fq -I r2.fq -o c1.fq -O c2.fq \ -U --umi_loc=read1 --umi_len=8 --dedup

3.7 其他实用参数

-w/--thread:线程数,默认3。建议设为CPU核心数的1-1.5倍。我一般用16或32。

-z/--compression:输出压缩级别,1-9,默认4。级别越高压缩率越好但越慢。4是个不错的平衡点。

--overrepresentation_analysis:开启过表达序列分析。对于发现污染很有用,但会增加运行时间。

--correction:开启碱基校正。利用双端overlap信息校正错误碱基。对于低质量数据有帮助,但也会增加时间。

-R/--report_title:自定义报告标题。批量处理时很有用,方便区分不同样本。

4. 完整实操流程:从原始数据到干净fastq

4.1 场景设定与数据准备

假设我们有一批双端测序数据,来自NovaSeq平台,建库时加了8bp的UMI在read1前端,需要做完整的质控处理。数据存放在raw_data/目录下,样本名为sample1sample10

先看一下数据结构:

ls raw_data/ # sample1_R1.fastq.gz sample1_R2.fastq.gz # sample2_R1.fastq.gz sample2_R2.fastq.gz # ...

4.2 单样本Fastp命令设计

针对这个场景,我设计的Fastp命令如下:

fastp \ -i raw_data/sample1_R1.fastq.gz \ -I raw_data/sample1_R2.fastq.gz \ -o clean_data/sample1_R1.clean.fastq.gz \ -O clean_data/sample1_R2.clean.fastq.gz \ -w 16 \ -q 20 \ -u 30 \ -n 3 \ -l 36 \ --detect_adapter_for_pe \ --cut_right \ --cut_window_size 4 \ --cut_mean_quality 20 \ -g \ --poly_g_min_len 10 \ -U \ --umi_loc=read1 \ --umi_len=8 \ --umi_prefix=UMI \ --dedup \ -h reports/sample1.html \ -j reports/sample1.json \ -R "sample1 QC Report" \ -z 4

逐段解释这个命令的设计逻辑:

输入输出:用-i/-I指定双端输入,-o/-O指定双端输出。输出用.gz压缩,节省磁盘空间。

线程-w 16,根据服务器配置调整。Fastp的多线程效率很高,16线程基本能跑满。

质量过滤-q 20 -u 30 -n 3 -l 36。Q20阈值,不合格碱基比例上限30%,N碱基上限3,最小长度36。这套参数比默认值严格,适合对质量要求高的项目。

adapter检测--detect_adapter_for_pe,双端模式必须显式开启。

滑窗修剪--cut_right配合窗口大小4和平均质量20。从5'到3'扫描,遇到低质量窗口就截断。

polyG修剪-g --poly_g_min_len 10,NovaSeq数据必开。

UMI处理-U --umi_loc=read1 --umi_len=8 --umi_prefix=UMI,从read1前端提取8bp UMI。

去重--dedup,基于UMI去重。

报告-h-j分别输出HTML和JSON报告,-R设置报告标题。

压缩-z 4,平衡压缩率和速度。

4.3 批量处理的Shell脚本

单个样本跑通了,接下来要批量处理。这里用Shell脚本的for循环来实现:

#!/bin/bash # 配置 RAW_DIR="raw_data" CLEAN_DIR="clean_data" REPORT_DIR="reports" THREADS=16 # 创建输出目录 mkdir -p ${CLEAN_DIR} ${REPORT_DIR} # 获取样本列表 for R1 in ${RAW_DIR}/*_R1.fastq.gz; do # 提取样本名 sample=$(basename ${R1} _R1.fastq.gz) R2="${RAW_DIR}/${sample}_R2.fastq.gz" # 检查R2是否存在 if [ ! -f "${R2}" ]; then echo "Warning: ${R2} not found, skipping ${sample}" continue fi echo "Processing ${sample}..." fastp \ -i ${R1} \ -I ${R2} \ -o ${CLEAN_DIR}/${sample}_R1.clean.fastq.gz \ -O ${CLEAN_DIR}/${sample}_R2.clean.fastq.gz \ -w ${THREADS} \ -q 20 -u 30 -n 3 -l 36 \ --detect_adapter_for_pe \ --cut_right --cut_window_size 4 --cut_mean_quality 20 \ -g --poly_g_min_len 10 \ -U --umi_loc=read1 --umi_len=8 --umi_prefix=UMI \ --dedup \ -h ${REPORT_DIR}/${sample}.html \ -j ${REPORT_DIR}/${sample}.json \ -R "${sample} QC Report" \ -z 4 if [ $? -eq 0 ]; then echo "${sample} done." else echo "Error: ${sample} failed!" fi done echo "All samples processed."

这个脚本有几个细节值得说明:

basename ${R1} _R1.fastq.gz用来提取样本名。basename的第二个参数是后缀,它会去掉这个后缀。比如raw_data/sample1_R1.fastq.gz会变成sample1

if [ ! -f "${R2}" ]检查R2文件是否存在,避免因为缺失文件导致脚本中断。

if [ $? -eq 0 ]检查上一条命令的退出状态。Fastp成功返回0,失败返回非0。这样可以及时发现失败的样本。

4.4 并行加速:让批量处理快起来

上面的脚本是串行执行的,10个样本要跑10次。如果服务器核心多,可以并行处理。有两种方式:

方式一:用GNU parallel

ls raw_data/*_R1.fastq.gz | \ sed 's/_R1.fastq.gz//' | \ parallel -j 4 ' sample={} fastp -i raw_data/${sample}_R1.fastq.gz \ -I raw_data/${sample}_R2.fastq.gz \ -o clean_data/${sample}_R1.clean.fastq.gz \ -O clean_data/${sample}_R2.clean.fastq.gz \ -w 8 -q 20 -u 30 -n 3 -l 36 \ --detect_adapter_for_pe \ --cut_right --cut_window_size 4 --cut_mean_quality 20 \ -g --poly_g_min_len 10 \ -U --umi_loc=read1 --umi_len=8 --umi_prefix=UMI \ --dedup \ -h reports/${sample}.html \ -j reports/${sample}.json \ -R "${sample} QC Report" -z 4 '

-j 4表示同时跑4个样本,每个样本用8线程。总共32线程。这样比串行快很多。

方式二:用Shell的后台任务

for R1 in raw_data/*_R1.fastq.gz; do sample=$(basename ${R1} _R1.fastq.gz) R2="raw_data/${sample}_R2.fastq.gz" fastp -i ${R1} -I ${R2} \ -o clean_data/${sample}_R1.clean.fastq.gz \ -O clean_data/${sample}_R2.clean.fastq.gz \ -w 8 -q 20 -u 30 -n 3 -l 36 \ --detect_adapter_for_pe \ --cut_right --cut_window_size 4 --cut_mean_quality 20 \ -g --poly_g_min_len 10 \ -U --umi_loc=read1 --umi_len=8 --umi_prefix=UMI \ --dedup \ -h reports/${sample}.html \ -j reports/${sample}.json \ -R "${sample} QC Report" -z 4 & # 控制并发数 while [ $(jobs -r | wc -l) -ge 4 ]; do sleep 1 done done wait echo "All done."

&把命令放到后台执行,jobs -r | wc -l统计正在运行的后台任务数,超过4个就等待。wait等待所有后台任务完成。

注意:并行处理时要注意内存和磁盘I/O。Fastp本身内存占用不大,但多个实例同时读写磁盘可能会成为瓶颈。如果发现速度上不去,可能是磁盘I/O限制了。

4.5 结果验证与报告解读

跑完之后,先看JSON报告里的关键指标:

# 提取关键统计 cat reports/sample1.json | python3 -c " import json, sys data = json.load(sys.stdin) summary = data['summary'] before = summary['before_filtering'] after = summary['after_filtering'] print(f\"Total reads before: {before['total_reads']}\") print(f\"Total reads after: {after['total_reads']}\") print(f\"Pass rate: {after['total_reads']/before['total_reads']*100:.2f}%\") print(f\"Q30 before: {before['q30_rate']*100:.2f}%\") print(f\"Q30 after: {after['q30_rate']*100:.2f}%\") print(f\"GC content: {after['gc_content']*100:.2f}%\") "

一般来说,合格的质控结果应该满足:

  • Pass rate在80%以上(严格模式可能70%左右)
  • Q30 after在90%以上
  • GC content与物种预期相符
  • Duplication rate在合理范围(WGS一般<20%,RNA-seq可能更高)

如果Pass rate过低,要检查是不是质量阈值设得太严,或者原始数据本身质量差。如果Q30 after没有明显提升,说明修剪效果不好,可能需要调整参数。

HTML报告更直观,用浏览器打开就能看到各种图表:质量分布、碱基组成、adapter含量、duplication等。我一般会重点看几个图:

  • Quality curve:修剪前后的质量分布对比
  • Base composition:碱基组成是否正常,有没有异常偏移
  • Adapter content:adapter是否被有效去除
  • Duplication:重复率是否正常

5. 常见问题与排查技巧实录

5.1 Fastp运行报错怎么办

报错一:Failed to open file

最常见的原因是路径写错了,或者文件不存在。检查:

ls -lh raw_data/sample1_R1.fastq.gz

如果文件存在但还是报错,可能是权限问题:

chmod +r raw_data/sample1_R1.fastq.gz

报错二:std::bad_alloc

内存不足。Fastp处理大文件时需要一定内存,尤其是开启overrepresentation分析时。解决方法:

  • 减少线程数(每个线程会占用一定内存)
  • 关闭overrepresentation分析
  • 增加服务器内存

报错三:Segmentation fault

段错误,通常是输入文件损坏。检查fastq文件完整性:

gzip -t raw_data/sample1_R1.fastq.gz

如果gzip测试报错,说明文件损坏,需要重新下载或从备份恢复。

5.2 质控效果不理想的排查思路

问题:adapter去除不干净

先确认adapter序列是否正确。如果自动检测效果不好,手动指定:

fastp -i r1.fq -I r2.fq -o c1.fq -O c2.fq \ -a AGATCGGAAGAGCACACGTCTGAACTCCAGTCA \ --adapter_sequence_r2 AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGT

如果还是不行,可能是adapter发生了突变或者有多个adapter。用--adapter_fasta提供多个候选序列。

问题:polyG修剪过度

如果发现read被切得太短,可能是polyG阈值设得太低。默认--poly_g_min_len 10,可以提高到15或20:

fastp -i r1.fq -I r2.fq -o c1.fq -O c2.fq \ -g --poly_g_min_len 15

问题:UMI提取不正确

检查UMI位置和长度是否与建库方案一致。如果不确定,可以先不开启UMI处理,跑一遍Fastp,看看read前几个碱基的组成。如果前8bp的碱基组成是随机的(每种碱基约25%),那很可能就是UMI。

# 查看前10bp的碱基组成 zcat raw_data/sample1_R1.fastq.gz | head -1000 | \ awk 'NR%4==2 {print substr($0,1,10)}' | \ sort | uniq -c | sort -rn | head -20

5.3 性能优化技巧

技巧一:用管道避免中间文件

如果Fastp后面还有其他处理步骤,可以用管道直接传递:

fastp -i input.fq --stdout -w 8 | \ bwa mem -t 8 reference.fa - | \ samtools sort -@ 8 -o output.bam

这样避免了写中间fastq文件,节省磁盘I/O。

技巧二:合理设置压缩级别

-z 4是默认值,平衡了速度和压缩率。如果磁盘空间紧张,可以设-z 6-z 9,但会慢一些。如果追求速度,设-z 1-z 2

技巧三:用--stdin从管道读取

Fastp支持从标准输入读取:

zcat input.fq.gz | fastp --stdin -o output.fq

这在处理流式数据时很有用。

5.4 常见问题速查表

问题现象可能原因解决方法
Pass rate过低质量阈值太严降低-q-u
Q30 after无提升修剪参数不当调整--cut_right参数
adapter残留检测未开启或序列不对--detect_adapter_for_pe或手动指定
read过短polyG/polyX修剪过度提高--poly_g_min_len
UMI未提取位置或长度不对检查--umi_loc--umi_len
运行速度慢线程数不足或I/O瓶颈增加-w,检查磁盘
内存不足线程过多或开启overrepresentation减少线程,关闭overrepresentation
输出文件为空输入文件损坏或参数错误检查输入文件,查看日志

5.5 几个我踩过的坑

坑一:双端adapter检测默认关闭

这个前面提过,但值得再强调。我第一次用Fastp处理双端数据时,没加--detect_adapter_for_pe,结果adapter残留严重。后来看文档才发现这个默认行为。现在我的脚本里这个参数是必加的。

坑二:UMI处理不等于UMI去重

Fastp的-U只是把UMI提取到read名称中,--dedup才是去重。而且--dedup在没有UMI时是基于序列去重,有UMI时是基于UMI去重。这两个参数要配合使用。

坑三:polyG修剪对非NextSeq数据的影响

有一次处理MiSeq数据,习惯性开了polyG修剪,结果发现一些真实的polyG区域被误切了。后来查资料才知道,polyG问题主要是双色荧光平台的特性,MiSeq是四色荧光,不存在这个问题。所以polyG修剪要按平台决定是否开启。

坑四:JSON报告中的百分比是小数

Fastp的JSON报告中,q30_rategc_content这些字段是0-1之间的小数,不是百分比。我第一次用脚本提取时忘了乘100,结果报告里Q30是0.95%,闹了笑话。

坑五:输出文件名不要和输入相同

Fastp会先读输入再写输出,但如果输入输出文件名相同,可能会出问题。虽然Fastp有保护机制,但最好还是用不同的文件名。

6. 进阶技巧:让Fastp发挥更大价值

6.1 与umi_tools的配合使用

Fastp处理完UMI后,read名称中会带有UMI信息。接下来可以用umi_tools做基于UMI的去重和定量:

# Fastp处理 fastp -i r1.fq -I r2.fq -o c1.fq -O c2.fq \ -U --umi_loc=read1 --umi_len=8 --umi_prefix=UMI # 比对 bwa mem -t 16 reference.fa c1.fq c2.fq | \ samtools sort -@ 16 -o aligned.bam # 提取UMI并去重 umi_tools extract --stdin=c1.fq --stdout=c1.umi.fq \ --read2-in=c2.fq --read2-out=c2.umi.fq \ --bc-pattern=NNNNNNNN # 或者从BAM中提取 umi_tools dedup -I aligned.bam -S dedup.bam \ --extract-umi-method=read_name \ --umi-separator=:

注意Fastp的UMI前缀格式是UMI_,umi_tools默认的分隔符是_,可能需要调整--umi-separator参数。

6.2 用Shell脚本做质控报告汇总

批量处理完后,通常需要把所有样本的统计指标汇总成一张表。用Shell + Python可以轻松搞定:

#!/bin/bash echo -e "Sample\tTotal_Reads\tPass_Rate\tQ30_Before\tQ30_After\tGC\tDup_Rate" > qc_summary.tsv for json in reports/*.json; do sample=$(basename ${json} .json) python3 -c " import json with open('${json}') as f: data = json.load(f) s = data['summary'] b = s['before_filtering'] a = s['after_filtering'] d = data.get('duplication', {}) print(f\"${sample}\t{b['total_reads']}\t{a['total_reads']/b['total_reads']*100:.2f}%\t{b['q30_rate']*100:.2f}%\t{a['q30_rate']*100:.2f}%\t{a['gc_content']*100:.2f}%\t{d.get('rate', 0)*100:.2f}%\") " >> qc_summary.tsv done echo "Summary written to qc_summary.tsv"

这个脚本会生成一个TSV文件,可以直接用Excel打开或者导入R做可视化。

6.3 处理特殊类型数据的参数调整

RNA-seq数据

  • 不要开polyX修剪,会误伤polyA尾巴
  • --cut_right可以保留,但窗口质量阈值可以放宽到15
  • 考虑开启--correction,利用双端overlap校正错误
fastp -i r1.fq -I r2.fq -o c1.fq -O c2.fq \ --detect_adapter_for_pe \ --cut_right --cut_window_size 4 --cut_mean_quality 15 \ -g --poly_g_min_len 10 \ --correction \ -q 15 -u 40 -l 36

扩增子数据

  • 长度过滤要严格,因为扩增子长度是已知的
  • adapter修剪要彻底,因为扩增子数据adapter污染通常较严重
  • 考虑开启--dedup,扩增子数据重复率通常很高
fastp -i r1.fq -I r2.fq -o c1.fq -O c2.fq \ --detect_adapter_for_pe \ -l 200 -q 20 -u 20 \ --dedup \ -g

低起始量数据

  • UMI处理必开
  • 去重必开
  • 质量阈值可以适当放宽,因为低起始量数据本身质量可能就一般
fastp -i r1.fq -I r2.fq -o c1.fq -O c2.fq \ --detect_adapter_for_pe \ -U --umi_loc=read1 --umi_len=8 --umi_prefix=UMI \ --dedup \ -q 15 -u 40 -l 30 \ -g

6.4 与Nextflow/Snakemake的集成

如果项目规模大,建议把Fastp集成到工作流管理工具中。以Nextflow为例:

process fastp { tag "$sample" publishDir "results/clean", mode: 'copy' input: tuple val(sample), path(r1), path(r2) output: tuple val(sample), path("${sample}_R1.clean.fastq.gz"), path("${sample}_R2.clean.fastq.gz") path("${sample}.html") path("${sample}.json") script: """ fastp \\ -i ${r1} -I ${r2} \\ -o ${sample}_R1.clean.fastq.gz \\ -O ${sample}_R2.clean.fastq.gz \\ -w ${task.cpus} \\ -q 20 -u 30 -n 3 -l 36 \\ --detect_adapter_for_pe \\ --cut_right --cut_window_size 4 --cut_mean_quality 20 \\ -g --poly_g_min_len 10 \\ -U --umi_loc=read1 --umi_len=8 --umi_prefix=UMI \\ --dedup \\ -h ${sample}.html -j ${sample}.json \\ -R "${sample} QC Report" -z 4 """ }

这样可以利用Nextflow的并行调度、错误重试、断点续跑等功能,比裸写Shell脚本更可靠。

6.5 质控后的数据管理建议

质控完成后,建议保留以下文件:

  • 干净的fastq文件(压缩)
  • Fastp的HTML报告
  • Fastp的JSON报告
  • 运行日志(如果有)
  • 使用的命令或脚本

目录结构建议:

project/ ├── raw_data/ # 原始数据(只读) ├── clean_data/ # 质控后数据 ├── reports/ # 质控报告 │ ├── html/ │ └── json/ ├── scripts/ # 处理脚本 ├── logs/ # 运行日志 └── qc_summary.tsv # 汇总统计

原始数据一定要保留,不要为了省空间删掉。万一后续发现质控参数需要调整,还能重新跑。我一般会在项目结束后把原始数据归档到冷存储,但至少保留到项目发表。

7. 一些个人体会

Fastp这个工具我用了快五年,从最早的0.20版本到现在,功能越来越完善。它最大的价值在于把质控流程标准化了——以前每个人写的质控脚本都不一样,现在一个Fastp命令就能覆盖大部分需求,结果可复现,报告可比较。

但工具再好,也只是工具。质控参数怎么设,还是要根据具体的数据类型、建库方案、下游分析需求来决定。我见过有人直接抄别人的参数,结果数据被切得太狠,后面分析灵敏度下降。也见过有人参数太宽松,adapter没去干净,导致假阳性。

我的建议是:新项目开始时,先拿一两个样本做参数测试,看看不同参数下的Pass rate、Q30、adapter去除效果,找到最适合这个项目的参数组合,再批量处理。这个前期投入是值得的,能避免后面返工。

另外,Fastp的报告一定要认真看。很多人跑完Fastp就直接进入下一步,报告看都不看。其实报告里有很多有价值的信息:过表达序列可能提示污染,duplication rate可能提示文库复杂度问题,adapter含量可能提示建库质量。这些信息对于判断数据是否可用非常关键。

最后说一个实际工作中的小习惯:我会把每次Fastp运行的完整命令记录在一个commands.log文件里,包括日期、样本名、参数。这样半年后回头看,还能知道当时是怎么处理的。这个习惯帮我省了很多次"当时到底怎么跑的"的困惑。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 9:54:33

React脚手架从入门到进阶:CRA与Vite对比及工程化实践

很多人在学 React 时都会卡在“脚手架”这一步&#xff1a;跟着教程敲了npx create-react-app my-app&#xff0c;项目是跑起来了&#xff0c;但里面的 Webpack 配置、Babel 配置、react-scripts到底做了什么&#xff0c;完全是一团黑盒。换个场景——公司要用 Vite 搭新项目&a…

作者头像 李华
网站建设 2026/9/19 9:54:06

Claude Code 代码验收实战:从能跑到敢上的完整指南

1. 一个需求做完之后&#xff0c;我才意识到验收才是真正的深水区用 Claude Code 写代码这件事&#xff0c;我算是比较早开始折腾的那批人。从最早在终端里敲claude命令&#xff0c;到后来在 VS Code 里配好插件、调通中文启动器&#xff0c;再到把常用开发工具的配置摸了个遍&…

作者头像 李华
网站建设 2026/9/19 9:53:39

SBC2332+LVGL嵌入式HMI实战:G2D加速与双核协同设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 9:53:08

SPSS相关与回归分析实战:从课件到落地,含语法与诊断

简介&#xff1a;这份SPSS相关分析与回归分析PPT课件面向统计学、数据分析初学者及需要完成课程作业或论文实证分析的高校学生与职场人士&#xff0c;帮助系统掌握变量间关系的测度与建模方法。课件围绕相关分析与回归分析两大主线展开&#xff0c;涵盖函数关系与统计关系的区分…

作者头像 李华
网站建设 2026/9/19 9:51:46

多头注意力机制原理解析:从QKV设计到工业级诊断

1. 为什么Transformer不用CNN或RNN&#xff0c;而偏偏选中“多头注意力”&#xff1f;我第一次在论文里看到“Multi-Head Attention”这个词时&#xff0c;正用LSTM跑一个文本分类任务——模型训练了三天&#xff0c;验证集F1卡在0.82不动&#xff0c;调参调到怀疑人生。直到我…

作者头像 李华