fastp-fastq-preprocessing について
Illumina シーケンス解析向けの FASTQ 前処理スキルです。fastp により、アダプター除去、品質フィルタリング、QC レポート作成をマルチスレッドで一度に行います。シングルエンドとペアエンドに対応し、ペアエンドではアダプターを自動検出できます。
主な機能
- 01アダプターと低品質塩基の除去
- 02ペアエンドアダプターの自動検出
- 03品質と長さによるリードのフィルタリング
- 04polyX テールの除去
- 05HTML と JSON の QC レポート作成
活用シーン
- 01アライメント前の RNA-seq・WGS リード処理
- 02複数サンプルの QC レポート作成
- 033′ 富化 RNA-seq の polyA テール除去
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jaechang-hits/ sciagent-skills --skill fastp-fastq-preprocessingインストール後、Claude Code で/fastp-fastq-preprocessingを入力して読み込まれたか確認します。
詳細
fastp — FASTQ の高速品質管理とアダプタートリミング
概要
fastp は、Illumina FASTQ ファイルのアダプタートリミング、品質フィルタリング、QC レポート生成を、マルチスレッドの単一パスで実行します。ペアエンドリードのオーバーラップからアダプター配列を自動検出するため、アダプターを手動で指定する必要はありません。fastp はペアエンドのオーバーラップ領域でミスマッチを補正し、品質スコアと長さに基づいてリードをフィルタリングし、polyX テール(RNA-seq では polyA)を除去して、インタラクティブな HTML と機械可読な JSON の QC レポートを生成します。Trim Galore や Trimmomatic より 3~10 倍高速で、同等以上の結果が得られるため、fastp は WGS、RNA-seq、ChIP-seq パイプラインにおけるアライメント前の標準的な前処理ステップとなっています。
使用する場面
- NGS パイプライン(RNA-seq、WGS、WES、ChIP-seq、ATAC-seq)のアライメント前に、Illumina アダプターと低品質塩基をトリミングする場合
- パイプラインの最初のステップで、MultiQC による集約前にサンプルごとの QC レポート(HTML + JSON)を生成する場合
- アダプターを手動で指定するより、オーバーラップからアダプターを自動検出する方法が望ましいペアエンドリードを処理する場合
- 3′ 末端濃縮プロトコル(Smart-seq、QuantSeq)由来の RNA-seq リードから polyA テールを除去する場合
- デマルチプレックスのワークフローで、UMI またはインデックスに基づいて FASTQ ファイルを分割する場合
- トリミングと併せて FastQC による塩基ごとの詳細な品質レポートが必要な場合は、代替手段として Trim Galore を使用します
- スライディングウィンドウによるトリミング手順を細かく制御する場合は、代替手段として Trimmomatic を使用します
前提条件
- ソフトウェア: fastp(conda またはコンパイル済みバイナリ)
- 入力: 生の Illumina FASTQ ファイル(シングルエンドまたはペアエンド、.fastq または .fastq.gz)
インストール前に確認してください: ツールは現在の環境(例:
pixi/conda環境内)ですでに利用可能な場合があります。まずcommand -v fastpを実行し、パスが返された場合は以下のインストールコマンドを省略してください。pixi プロジェクト内で実行する場合は、fastpを直接実行するのではなく、pixi run fastpを使用してください。
# Install with conda
conda install -c bioconda fastp
# Or download pre-compiled binary (Linux)
wget https://github.com/OpenGene/fastp/releases/download/v0.24.0/fastp
chmod +x fastp
./fastp --version
# fastp 0.24.0
# Verify
fastp --version
事前確認
解析コードを書く前に、以下の項目をユーザーと確認してください。
decisions:
- id: D1
param: -i / -I
kind: required
source: data
ask: "Were these reads sequenced from single-end or paired-ends of each fragment?"
default: "read off the file inventory - paired when R1/R2 mates are present"
- id: D2
param: library_prep
kind: required
source: user
ask: "Which library prep produced these reads - 5'-, 3'-, small RNA, lnRNA or amplicon?"
default: null
- id: D3
param: --trim_poly_x
kind: optional
source: user
depends_on: [D2]
ask: "Trim polyA/polyT tails left by the capture step?"
default: "on for 3'-enriched RNA-seq, off otherwise"
- id: D4
param: --adapter_sequence / --detect_adapter_for_pe
kind: required
source: user
depends_on: [D1]
ask: "Auto-detect the adapter, or supply the kit's sequence explicitly?"
default: "auto-detect"
- id: D5
param: --length_required
kind: required
source: user
depends_on: [D2]
ask: "Reads shorter than this after trimming are discarded - how short is too short to map?"
default: "15 (raise to ~36 for standard RNA-seq; keep low for small RNA)"
- id: D6
param: --qualified_quality_phred
kind: optional
source: user
ask: "How confident must a base call be before it counts as good quality?"
default: "15 (20 = 1% error)"
- id: D7
param: --correction
kind: optional
source: user
depends_on: [D1]
ask: "Correct mismatched bases where the two mates overlap?"
default: "off"
skip_if: "single-end input - there is no overlap to compare"
- id: D8
param: --low_complexity_filter
kind: optional_conditional
source: data
ask: "Drop low-complexity reads (homopolymer and short-repeat runs)?"
default: "off"
- id: D9
param: --thread, --split
kind: never_ask
source: data
reason: "Parallelism and output sharding; affect runtime and file layout, not the reads kept"
default: "8 threads, no split"
D2 は推測せず、ユーザーに直接確認します。ライブラリ調製法によって後続の 2 つの回答が変わるためです。D2 によって、polyA トリミングが適切かどうか(D3。3′ 末端濃縮ライブラリでは、生物学的配列ではないキャプチャテールでリードが終わります)と、長さの下限をどこに設定するか(D5。RNA-seq では適切な 36 bp の最小値でも、small RNA の解析ではリード全体が破棄されます)が決まります。D4 と D7 はどちらもペアのリードの扱いを示すため、D1 に関連します。
クイックスタート
# Paired-end adapter trimming with QC report
fastp \
-i sample_R1.fastq.gz \
-I sample_R2.fastq.gz \
-o sample_R1.trimmed.fastq.gz \
-O sample_R2.trimmed.fastq.gz \
-h sample_qc.html \
-j sample_qc.json \
--thread 8
echo "Trimmed reads in: sample_R1.trimmed.fastq.gz"
ワークフロー
ステップ 1: シングルエンドのアダプタートリミング
自動アダプター検出を使って、シングルエンド FASTQ に fastp を実行します。
# Single-end with auto adapter detection
fastp \
-i sample.fastq.gz \
-o sample.trimmed.fastq.gz \
-h sample_qc.html \
-j sample_qc.json \
--thread 8 \
--qualified_quality_phred 20 \
--length_required 36
echo "Input reads: $(zcat sample.fastq.gz | wc -l | awk '{print $1/4}')"
echo "Output reads: $(zcat sample.trimmed.fastq.gz | wc -l | awk '{print $1/4}')"
ステップ 2: ペアエンドのアダプタートリミング
オーバーラップに基づくアダプター検出と補正を使って、ペアエンド FASTQ ファイルを処理します。
# Paired-end with overlap-based adapter auto-detection
fastp \
-i sample_R1.fastq.gz \
-I sample_R2.fastq.gz \
-o sample_R1.trimmed.fastq.gz \
-O sample_R2.trimmed.fastq.gz \
-h sample_qc.html \
-j sample_qc.json \
--thread 8 \
--correction \
--detect_adapter_for_pe \
--qualified_quality_phred 20 \
--length_required 36
# Specify adapters explicitly (if auto-detection fails)
# fastp -i R1.fq.gz -I R2.fq.gz \
# --adapter_sequence AGATCGGAAGAGCACACGTCTGAACTCCAGTCA \
# --adapter_sequence_r2 AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGT \
# -o R1.out.fq.gz -O R2.out.fq.gz
ステップ 3: 品質フィルタリングとリード長のトリミング
より厳格または緩やかなフィルタリングのために、品質と長さのしきい値を設定します。
# Strict quality filtering (e.g., for variant calling)
fastp \
-i sample_R1.fastq.gz \
-I sample_R2.fastq.gz \
-o sample_R1.filtered.fastq.gz \
-O sample_R2.filtered.fastq.gz \
-h sample_qc.html \
-j sample_qc.json \
--thread 8 \
--qualified_quality_phred 25 \
--unqualified_percent_limit 20 \
--length_required 50 \
--max_len1 150 \
--max_len2 150 \
--low_complexity_filter \
--complexity_threshold 30
echo "Filtering complete. Check sample_qc.html for pass/fail rates."
ステップ 4: RNA-seq の polyA テール除去
アライメント前に、3′ 末端濃縮 RNA-seq プロトコルから polyA テールを除去します。
# Remove polyA tails (QuantSeq 3′ mRNA-seq)
fastp \
-i quantseq_R1.fastq.gz \
-o quantseq_R1.trimmed.fastq.gz \
-h quantseq_qc.html \
-j quantseq_qc.json \
--thread 8 \
--trim_poly_x \
--poly_x_min_len 10 \
--qualified_quality_phred 20 \
--length_required 25
# For Smart-seq2 paired-end with polyA
fastp \
-i smartseq_R1.fastq.gz \
-I smartseq_R2.fastq.gz \
-o smartseq_R1.trimmed.fastq.gz \
-O smartseq_R2.trimmed.fastq.gz \
--trim_poly_x --poly_x_min_len 10 \
--thread 8 \
-h smartseq_qc.html -j smartseq_qc.json
ステップ 5: パイプライン監視用 QC レポート JSON の解析
fastp の JSON 出力から主要な QC 指標を抽出し、自動品質ゲートに使用します。
import json
from pathlib import Path
def parse_fastp_json(json_path: str) -> dict:
with open(json_path) as f:
data = json.load(f)
before = data["summary"]["before_filtering"]
after = data["summary"]["after_filtering"]
return {
"total_reads_in": before["total_reads"],
"total_reads_out": after["total_reads"],
"pct_passed": after["total_reads"] / before["total_reads"] * 100,
"q30_rate_before": before["q30_rate"] * 100,
"q30_rate_after": after["q30_rate"] * 100,
"mean_len_before": before["read1_mean_length"],
"mean_len_after": after["read1_mean_length"],
"adapter_trimmed": data["filtering_result"]["adapter_trimmed"],
}
metrics = parse_fastp_json("sample_qc.json")
for key, val in metrics.items():
print(f"{key:25s}: {val:.1f}" if isinstance(val, float) else f"{key:25s}: {val:,}")
# Quality gate: fail if < 70% reads pass filter
if metrics["pct_passed"] < 70:
print("WARNING: Low pass rate — check raw data quality")
ステップ 6: バッチ前処理パイプライン
サンプルごとの QC サマリーを作成しながら、複数のサンプルを順に処理します。
#!/bin/bash
# Batch paired-end preprocessing for multiple samples
SAMPLES=(ctrl_1 ctrl_2 treat_1 treat_2)
DATA="data"
OUT="trimmed"
QC="qc/fastp"
THREADS=8
mkdir -p "$OUT" "$QC"
for sample in "${SAMPLES[@]}"; do
echo "=== Processing $sample ==="
fastp \
-i "$DATA/${sample}_R1.fastq.gz" \
-I "$DATA/${sample}_R2.fastq.gz" \
-o "$OUT/${sample}_R1.fastq.gz" \
-O "$OUT/${sample}_R2.fastq.gz" \
-h "$QC/${sample}.html" \
-j "$QC/${sample}.json" \
--thread $THREADS \
--correction \
--detect_adapter_for_pe \
--qualified_quality_phred 20 \
--length_required 36 \
2>&1 | grep -E "Read[12]|Filtering|Adapter|passed"
done
# Aggregate QC metrics
python3 - << 'EOF'
import json, pandas as pd
from pathlib import Path
rows = []
for jf in sorted(Path("qc/fastp").glob("*.json")):
with open(jf) as f: data = json.load(f)
after = data["summary"]["after_filtering"]
before = data["summary"]["before_filtering"]
rows.append({
"sample": jf.stem,
"reads_in": before["total_reads"],
"reads_out": after["total_reads"],
"pct_passed": round(after["total_reads"]/before["total_reads"]*100, 1),
"q30_after": round(after["q30_rate"]*100, 1),
})
df = pd.DataFrame(rows)
print(df.to_string(index=False))
df.to_csv("fastp_summary.tsv", sep="\t", index=False)
EOF
# Run MultiQC to aggregate all fastp JSON reports
multiqc qc/fastp/ -o qc/ -n fastp_multiqc_report
主なパラメーター
| パラメーター | デフォルト | 範囲/オプション | 効果 |
|---|---|---|---|
-i / -I | 必須 | file path | 入力 FASTQ(ペアエンドの場合は R1 と R2) |
-o / -O | 必須 | file path | トリミング後の出力 FASTQ(R1 と R2) |
-h / -j | — | file path | HTML および JSON の QC レポート出力先 |
--thread | 3 | 1–16 | CPU スレッド数。8 が適切なバランスです |
--qualified_quality_phred | 15 | 0–40 | 最小塩基品質(Phred)。20 はエラー率 1% に相当します |
--length_required | 15 | 1–1000 | トリミング後の最小リード長。これより短いリードは破棄します |
--correction | オフ | flag | PE のオーバーラップ領域のミスマッチを修正します |
--detect_adapter_for_pe | オフ | flag | PE データでオーバーラップに基づくアダプターの自動検出を有効にします |
--adapter_sequence | 自動 | string | R1 アダプターを明示的に指定します。自動検出より優先されます |
--trim_poly_x | オフ | flag | polyX(polyA/polyT)テールをトリミングします。3′ 濃縮 RNA-seq に使用します |
--low_complexity_filter | オフ | flag | 複雑度の低いリード(デフォルトでは複雑度 30% 未満)をフィルタリングします |
--split | オフ | integer | 出力を方向ごとに N 個のファイルに分割します(並列処理用) |
よく使うレシピ
レシピ 1:fastp を Snakemake パイプラインに統合する
# Snakefile — fastp trimming rule
configfile: "config.yaml"
SAMPLES = config["samples"]
rule fastp_pe:
input:
r1 = "data/{sample}_R1.fastq.gz",
r2 = "data/{sample}_R2.fastq.gz"
output:
r1 = "trimmed/{sample}_R1.fastq.gz",
r2 = "trimmed/{sample}_R2.fastq.gz",
html = "qc/{sample}_fastp.html",
json = "qc/{sample}_fastp.json"
threads: 8
shell:
"""
fastp -i {input.r1} -I {input.r2} \
-o {output.r1} -O {output.r2} \
-h {output.html} -j {output.json} \
--thread {threads} \
--correction --detect_adapter_for_pe \
--qualified_quality_phred 20 \
--length_required 36
"""
レシピ 2:Python で fastp の JSON レポートを集約する
import json
import pandas as pd
from pathlib import Path
qc_dir = Path("qc/fastp")
records = []
for jf in sorted(qc_dir.glob("*.json")):
with open(jf) as f:
d = json.load(f)
b = d["summary"]["before_filtering"]
a = d["summary"]["after_filtering"]
records.append({
"sample": jf.stem.replace("_fastp", ""),
"reads_in_M": b["total_reads"] / 1e6,
"reads_out_M": a["total_reads"] / 1e6,
"pct_passed": a["total_reads"] / b["total_reads"] * 100,
"q30_pct": a["q30_rate"] * 100,
"mean_len_bp": a["read1_mean_length"],
"adapter_pct": d["filtering_result"]["adapter_trimmed"] / b["total_reads"] * 100,
})
df = pd.DataFrame(records).round(2)
print(df.to_string(index=False))
# Flag low-quality samples
low_q = df[df["pct_passed"] < 80]
if not low_q.empty:
print(f"\nSamples with < 80% reads passing: {list(low_q['sample'])}")
出力されるファイル
| 出力 | 形式 | 説明 |
|---|---|---|
*_R1.trimmed.fastq.gz | FASTQ.gz | トリミング済みの R1 リード(アダプターと低品質塩基を除去) |
*_R2.trimmed.fastq.gz | FASTQ.gz | トリミング済みの R2 リード(ペアエンドのみ) |
*.html | HTML | 塩基ごとの品質、GC 含量、アダプターのプロットを含むインタラクティブな QC レポート |
*.json | JSON | 自動化および MultiQC による解析用の、機械可読な QC メトリクス |
fastp.log | テキスト | 合格/不合格リード数とフィルタリング統計を含む stderr の概要 |
トラブルシューティング
| 問題 | 原因 | 解決策 |
|---|---|---|
| SE モードでアダプターが検出されない | SE リードではアダプターの明示的な指定、または --adapter_sequence が必要です | --detect_adapter_for_pe は PE の場合にのみ使用します。SE ではアダプターを指定します:--adapter_sequence AGATCGGAAGAGC |
| アダプター含有率が非常に高い(> 50%) | インサートが短い(small RNA、miRNA)、またはライブラリー調製の品質が低い | ライブラリープロトコルを確認します。--overlap_len_require 10 を使用してオーバーラップの感度を調整します |
| フィルタリングされるリードが多すぎる(合格率 < 60%) | 品質しきい値が厳しすぎる、またはシーケンシングの品質が低い | --qualified_quality_phred を 15 に緩和します。--length_required を 25 に下げます |
| JSON 出力にフィールドがない | 古い fastp バージョン | conda update fastp でアップグレードするか、GitHub から最新のバイナリーをダウンロードします |
| MultiQC が fastp JSON を解析しない | JSON ファイルがスキャン対象のディレクトリーにない | multiqc . ではなく multiqc qc/ を実行します。ls qc/*.json で JSON ファイルが存在することを確認します |
| 出力 FASTQ が空 | すべてのリードがフィルタリングされた(入力が誤っている、またはしきい値が極端) | zcat sample.fq.gz | head -8 で入力 FASTQ を確認します。まず --low_complexity_filter を指定せずに実行します |
| 大きなファイルで処理が遅い | スレッド数が少ない | --thread を 8–12 に増やします。入力が高速ストレージ(SSD)上にあることを確認します |
| polyA が除去されない | --trim_poly_x が設定されていない | 3′ 濃縮プロトコルでは --trim_poly_x --poly_x_min_len 10 を追加します |
参考資料
- fastp GitHub:OpenGene/fastp — ソースコード、変更履歴、使用ガイド
- Chen S ほか(2018)「fastp: an ultra-fast all-in-one FASTQ preprocessor」— Bioinformatics 34(17):i884-i890。DOI:10.1093/bioinformatics/bty560
- fastp ドキュメント — 全パラメーターのリファレンスとレシピ
- MultiQC fastp モジュール — サンプル間で fastp の JSON レポートを集約する方法