pipeline-cutandrun
Execute CUT&RUN processing pipeline from FASTQ to peaks and signal tracks. Child of pipeline-guide. Provides Nextflow execution with Docker and cloud deployment. Use when processing CUT&RUN or CUT&Tag data, an alternative to ChIP-seq with lower background. Trigger on: CUT&RUN pip
Install
npx skills add https://github.com/ammawla/encode-toolkit/tree/main/skills/pipeline-cutandrun
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install ammawla-encode-toolkit@llmmart
git clone https://github.com/ammawla/encode-toolkit.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole ammawla/encode-toolkit collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
ENCODE CUT&RUN Pipeline: FASTQ to Peaks and Signal Tracks
When to Use
- User wants to run a CUT&RUN or CUT&Tag processing pipeline from FASTQ to peaks
- User asks about "CUT&RUN pipeline", "CUT&Tag", "SEACR", "spike-in normalization", or "targeted chromatin"
- User needs to process CUT&RUN/CUT&Tag data with spike-in calibration and SEACR peak calling
- Example queries: "process my CUT&RUN FASTQs", "run SEACR on CUT&Tag data", "normalize CUT&RUN with spike-in controls"
Execute the CUT&RUN/CUT&Tag processing pipeline for targeted chromatin profiling, producing peak calls with SEACR and spike-in normalized signal tracks.
Pipeline Overview
FASTQ
|-> FastQC (raw reads)
+-> Trim Galore -> Bowtie2 (genome) -> {sample}.sorted.bam
|
|-> unmapped read pairs -> Bowtie2 (spike-in) -> counts -> scale_factors.txt
| |
+-> filter (MAPQ 10, proper pairs) -> Picard MarkDuplicates |
(removed) -> blacklist filter -> {sample}.filtered.bam |
|-> fragment BED -> fragment bedGraph -> SEACR peaks |
|-> MACS2 peaks (with --peak_caller macs2|both) |
|-> FRiP vs every peak set -> {sample}.frip_mqc.tsv |
+-> bamCoverage -> {sample}.normalized.bw <-- factor ---+
Not run by this workflow
- Peak-level filtering:
--blacklistis applied to the BAM only. Peak files are never filtered afterwards, and there is no separate suspect-list input. Pass a pre-merged blacklist + suspect-list BED as--blacklist, or filter the peak files yourself. - Spike-in scaling of the SEACR input: only the bigWig is scaled
(
bamCoverage --scaleFactor). The fragment bedGraph given to SEACR is unscaled.
ENCODE Repository
- ENCODE does not publish an official CUT&RUN pipeline. This workflow follows the published CUT&RUN/CUT&Tag processing protocol (Bowtie2, fragment bedGraphs, SEACR) and applies ENCODE conventions for filtering, blacklisting, and QC.
- Container: built from
scripts/Dockerfilein this skill (docker build -t encode-toolkit/pipeline-cutandrun:1.0.0 scripts/); override with--container - This skill: Nextflow DSL2 reimplementation for portability
Core Tools and Versions
Versions are those installed by scripts/Dockerfile, which is what the
workflow runs.
| Tool | Version | Purpose | Citation |
|---|---|---|---|
| Bowtie2 | 2.5.4 | Alignment (genome + spike-in) | Langmead & Salzberg 2012 |
| SEACR | 1.3 | Peak calling (CUT&RUN-specific) | Meers et al. 2019 |
| MACS2 | 2.2.9.1 | Alternative peak caller | Zhang et al. 2008 |
| Picard | 3.1.1 | Duplicate marking and removal | Broad Institute |
| samtools | 1.19 | BAM operations | Li et al. 2009 |
| bedtools | 2.31.0 | Genomic arithmetic | Quinlan & Hall 2010 |
| deepTools | 3.5.5 | Signal track generation | Ramirez et al. 2016 |
| Trim Galore | 0.6.10 | Adapter trimming | Krueger (Babraham) |
| FastQC | 0.12.1 | Read quality | Andrews (Babraham) |
| MultiQC | 1.21 | Aggregated QC | Ewels et al. 2016 |
The conda alternative (cutandrun-env.yml) pins the same version of every tool
in the table above, but installs no SEACR (only r-base): SEACR is not a conda
package, so on that route SEACR_1.3.sh and SEACR_1.3.R must be fetched
separately from the SEACR repository.
Key Literature
Skene & Henikoff 2017 - "An efficient targeted nuclease strategy for high-resolution mapping of DNA binding sites" (eLife, ~1,500 citations) DOI: 10.7554/eLife.21856
Meers et al. 2019 - "Peak calling by Sparse Enrichment Analysis for CUT&RUN chromatin profiling" (Epigenetics & Chromatin, ~800 citations) DOI: 10.1186/s13072-019-0287-4
Kaya-Okur et al. 2019 - "CUT&Tag for efficient epigenomic profiling of small samples and single cells" (Nature Communications, ~1,200 citations) DOI: 10.1038/s41467-019-09982-5
Nordin et al. 2023 - "The CUT&RUN suspect list of problematic regions" (Genome Biology) DOI: 10.1186/s13059-023-02960-3
Amemiya et al. 2019 - "The ENCODE Blacklist" (Scientific Reports, ~1,372 citations) DOI: 10.1038/s41598-019-45839-z
Execution
Quick Start (Local)
nextflow run scripts/main.nf \
-profile local \
--reads '/data/fastq/*_R{1,2}.fastq.gz' \
--bowtie2_index '/ref/bowtie2_index/genome' \
--spikein_index '/ref/bowtie2_ecoli/ecoli' \
--chrom_sizes '/ref/hg38.chrom.sizes' \
--blacklist '/ref/hg38-blacklist.v2.bed' \
--outdir results/ \
-resume
SLURM HPC
nextflow run scripts/main.nf \
-profile slurm \
--container /path/to/pipeline-cutandrun.sif \
--reads '/data/fastq/*_R{1,2}.fastq.gz' \
--bowtie2_index '/ref/bowtie2_index/genome' \
--spikein_index '/ref/bowtie2_ecoli/ecoli' \
--chrom_sizes '/ref/hg38.chrom.sizes' \
--blacklist '/ref/hg38-blacklist.v2.bed' \
--outdir results/ \
-resume
Cloud (GCP / AWS)
# Google Cloud Batch
nextflow run scripts/main.nf -profile gcp \
--container us-docker.pkg.dev/<project>/<repo>/pipeline-cutandrun:1.0.0 \
--gcp_project <project> \
--gcp_workdir gs://<bucket>/work \
--reads 'gs://<bucket>/fastq/*_R{1,2}.fastq.gz' \
--bowtie2_index gs://<bucket>/ref/bowtie2_index/genome \
--spikein_index gs://<bucket>/ref/bowtie2_ecoli/ecoli \
--chrom_sizes gs://<bucket>/ref/hg38.chrom.sizes \
--blacklist gs://<bucket>/ref/hg38-blacklist.v2.bed \
--outdir gs://<bucket>/results
# AWS Batch
nextflow run scripts/main.nf -profile aws \
--container <account>.dkr.ecr.<region>.amazonaws.com/pipeline-cutandrun:1.0.0 \
--aws_queue <job-queue> \
--aws_workdir s3://<bucket>/work \
--reads 's3://<bucket>/fastq/*_R{1,2}.fastq.gz' \
--bowtie2_index s3://<bucket>/ref/bowtie2_index/genome \
--spikein_index s3://<bucket>/ref/bowtie2_ecoli/ecoli \
--chrom_sizes s3://<bucket>/ref/hg38.chrom.sizes \
--blacklist s3://<bucket>/ref/hg38-blacklist.v2.bed \
--outdir s3://<bucket>/results
--outdir only sets where results are published; Google Batch and AWS Batch
stage every task through the work directory, and the workflow stops with an
error if it or the project/queue is missing.
Resource Requirements
| Step | CPUs | RAM | Time (per sample) |
|---|---|---|---|
| Bowtie2 align (genome) | 8 | 8 GB | 30-60 min |
| Bowtie2 align (spike-in) | 4 | 4 GB | 10-20 min |
| Filter/dedup | 4 | 8 GB | 15-30 min |
| SEACR peaks | 2 | 4 GB | 10-20 min |
| Signal tracks | 4 | 8 GB | 15-30 min |
| Total | 8 | 8 GB | 1.5-3 hours |
The RAM column is each step's first-attempt request. These processes ask for
that much memory per attempt, so a task killed for exceeding it is retried with
more (at most two retries, capped by --max_memory). Failures with any other
exit status stop the run.
Pipeline Parameters
| Parameter | Default | Description |
|---|---|---|
--reads |
required | Glob pattern to paired FASTQ files |
--bowtie2_index |
required | Bowtie2 genome index prefix (every file starting with this prefix is staged) |
--spikein_index |
null |
Bowtie2 spike-in index prefix (E. coli by convention). When given, signal tracks are spike-in calibrated |
--chrom_sizes |
required | Chromosome sizes file |
--blacklist |
required | Blacklist BED applied to the BAM. Pass a pre-merged blacklist + CUT&RUN suspect list here if you want both |
--outdir |
./results |
Output directory |
--seacr_mode |
stringent |
SEACR mode: stringent, relaxed, or both |
--seacr_norm |
norm |
SEACR normalization to the control: norm or non. Only used with --control; without a control the workflow always passes non |
--seacr_threshold |
0.01 |
Top fraction of signal kept by SEACR when no --control is given |
--control |
null |
IgG control BAM, already filtered and deduplicated. Converted to a fragment bedGraph for SEACR and passed as -c to MACS2 |
--macs2_gsize |
hs |
MACS2 effective genome size (hs, mm, or a number) |
--peak_caller |
seacr |
Peak caller: seacr, macs2, or both |
--skip_spikein |
false |
Skip spike-in calibration; signal tracks are then RPKM-normalized |
Infrastructure parameters (nextflow.config)
| Parameter | Default | Description |
|---|---|---|
--container |
encode-toolkit/pipeline-cutandrun:1.0.0 |
Image built from scripts/Dockerfile. Pass a registry image for gcp/aws, or a .sif file for slurm |
--max_cpus, --max_memory, --max_time |
16, 16.GB, 12.h |
Upper bounds applied to every process |
--slurm_queue, --slurm_account |
normal, none |
SLURM partition and account |
--gcp_project, --gcp_workdir |
none (both required for -profile gcp) |
Google Cloud project and gs:// work directory |
--gcp_location, --gcp_disk |
us-central1, 200.GB |
Google Batch region and per-task disk |
--aws_queue, --aws_workdir |
none (both required for -profile aws) |
AWS Batch job queue and s3:// work directory |
--aws_region, --aws_cli_path |
us-east-1, /home/ec2-user/miniconda/bin/aws |
AWS region, and the AWS CLI path inside the Batch AMI |
Output Files
results/
fastqc/ # Raw read quality
trim_galore/ # Trimmed reads, trimming reports,
# and FastQC of the trimmed reads
alignment/
{sample}.filtered.bam # Quality-filtered, deduplicated, blacklist-filtered
{sample}.filtered.bam.bai
{sample}.dup_metrics.txt # Picard MarkDuplicates metrics
{sample}.flagstat.txt # samtools flagstat on the filtered BAM
spikein/ # Only with --spikein_index
{sample}.spikein_counts.txt # sample, spike-in read count
scale_factors.txt # One file for the run: sample, spikein_count, scale_factor
peaks/
{sample}.seacr.stringent.bed # SEACR stringent peaks
{sample}.seacr.relaxed.bed # With --seacr_mode relaxed or both
{sample}.macs2_peaks.narrowPeak # With --peak_caller macs2 or both
signal/
{sample}.normalized.bw # Spike-in scaled, or RPKM without spike-in
{sample}.fragments.bed # Fragment BED (same chromosome, <1 kb)
qc/
{sample}.fragment_sizes.txt
{sample}.frip_mqc.tsv # FRiP, one row per peak set called for the sample
multiqc/
multiqc_report.html
pipeline_info/
timeline.html
report.html
trace.txt
The fragment bedGraph that SEACR consumes is an intermediate and is not
published; the published signal/{sample}.fragments.bed is the BED it is
built from.
QC Thresholds
This is the only QC threshold table for this skill; the reference files point back to it.
| Metric | Pass | Warning | Fail | Computed from |
|---|---|---|---|---|
| Mapping rate (genome) | >80% | 60-80% | <60% | Bowtie2 log (in multiqc_report.html) |
| Spike-in reads | 1-10% of total | 0.1-1% or 10-30% | <0.1% or >30% | spikein/{sample}.spikein_counts.txt |
| Duplication rate | <20% | 20-40% | >40% | alignment/{sample}.dup_metrics.txt |
| FRiP (peaks) | >10% | 5-10% | <5% | qc/{sample}.frip_mqc.tsv (also a MultiQC table) |
| Peak count | >5,000 | 1,000-5,000 | <1,000 | peaks/{sample}.seacr.*.bed |
| Fragment size | Nucleosomal pattern | Irregular | No pattern | qc/{sample}.fragment_sizes.txt |
Fragment Size Distribution
CUT&RUN produces a characteristic nucleosomal ladder:
- <120 bp: Sub-nucleosomal (TF binding)
- ~150 bp: Mononucleosomal (histone marks)
- ~300 bp: Dinucleosomal
- Absence of nucleosomal pattern suggests protocol issues
Spike-in Normalization
Spike-in normalization is CRITICAL for CUT&RUN quantitative comparison.
How It Works
-
- coli DNA is carried over from pA-MNase/pA-Tn5 production
- Each sample has a different amount of spike-in reads
- Samples with more target cleavage have fewer spike-in reads (proportionally)
- Scale factor = smallest non-zero spike-in count across samples / this sample's count
Scale Factor Calculation
With three samples whose spike-in counts are 200,000, 400,000 and 100,000, the minimum is 100,000:
Sample A: 200,000 spike-in reads -> scale = 100,000 / 200,000 = 0.5
Sample B: 400,000 spike-in reads -> scale = 100,000 / 400,000 = 0.25
Sample C: 100,000 spike-in reads -> scale = 100,000 / 100,000 = 1.0 (minimum)
Higher spike-in counts = less target enrichment = lower scale factor.
All samples are written to one spikein/scale_factors.txt (columns: sample,
spike-in count, scale factor). A sample with no spike-in reads cannot be
calibrated and is left unscaled (factor 1). The factor is applied only to the
bigWig via bamCoverage --scaleFactor; the fragment bedGraph SEACR reads is
unscaled.
SEACR vs MACS2
| Feature | SEACR | MACS2 |
|---|---|---|
| Designed for | CUT&RUN/CUT&Tag | ChIP-seq |
| Background model | Sparse enrichment | Dynamic Poisson |
| Control required | Optional (IgG) | Recommended |
| Low background | Handles well | May overcall |
| Stringent mode | Very conservative | Via q-value |
| ENCODE recommendation | Primary for CUT&RUN | Alternative |
SEACR is specifically designed for the sparse, low-background signal profile of CUT&RUN data. MACS2 may overcall peaks due to the low background.
Critical Pitfalls
Spike-in Calibration is CRITICAL
Without spike-in normalization, quantitative comparisons between samples are
unreliable. The amount of pA-MNase (or pA-Tn5) varies between experiments,
and spike-in reads provide the internal calibration standard. Without
--spikein_index (or with --skip_spikein) the bigWigs fall back to RPKM,
which is not quantitatively comparable across samples.
IgG Control vs No-Antibody Control
- IgG control: Non-specific antibody, captures background binding
- No-antibody: No antibody, captures MNase accessibility background
- IgG is preferred but not always available
- SEACR can work without a control: it then uses
--seacr_threshold(default 0.01, the top 1% of signal) and, as SEACR v1.3 requires with a numeric threshold, thenonnormalization mode
SEACR Stringent vs Relaxed Mode
- Stringent: Returns only the most enriched peaks (fewer, higher confidence)
- Relaxed: Returns a broader set including weaker peaks
- For initial analysis, use stringent mode (the default)
- For comprehensive catalogs, use
--seacr_mode bothand filter downstream
CUT&RUN Suspect List (Nordin 2023)
The workflow applies --blacklist to the BAM only; it never filters the peak
files and takes no separate suspect list. To use the CUT&RUN suspect list
(Nordin et al. 2023), which identifies regions with artifactual signal
specific to CUT&RUN/CUT&Tag protocols, either pass a merged BED as
--blacklist or filter the peaks afterwards yourself:
# Download suspect list
wget https://github.com/Boyle-Lab/Blacklist/raw/master/lists/CUTandRUN.suspectlist.hg38.bed.gz
# Option 1: merge once and pass as --blacklist (filters the BAM)
zcat CUTandRUN.suspectlist.hg38.bed.gz | cat hg38-blacklist.v2.bed - \
| sort -k1,1 -k2,2n | bedtools merge > combined_blacklist.bed
# Option 2: filter the published peaks afterwards (manual)
bedtools intersect \
-a results/peaks/sample.seacr.stringent.bed \
-b combined_blacklist.bed \
-v \
> sample_peaks_filtered.bed
CUT&RUN vs CUT&Tag
Both protocols are supported by this pipeline. Differences:
- CUT&RUN: Uses pA-MNase, E. coli spike-in from MNase production
- CUT&Tag: Uses pA-Tn5, E. coli spike-in from Tn5 production
- CUT&Tag has higher background from Tn5 insertion preference
- CUT&Tag may work better for histone marks; CUT&RUN for TFs
Provenance Integration
After pipeline completion, log all outputs:
encode_log_derived_file(
file_path="/results/peaks/sample1.seacr.stringent.bed",
source_accessions=["ENCSR...", "ENCFF..."],
description="CUT&RUN peaks from ENCODE CUT&RUN pipeline",
file_type="CUT&RUN_peaks",
tool_used="Bowtie2 2.5.4 + SEACR 1.3",
parameters="stringent mode, threshold 0.01 non, BAM blacklist-filtered (peaks unfiltered)"
)
Reference Files
Detailed step-by-step documentation is provided in the references/ directory:
01-qc-trimming.md-- Read QC and adapter trimming for CUT&RUN02-bowtie2-alignment.md-- Bowtie2 alignment to genome and spike-in03-filtering-spikein.md-- Filtering, dedup, and spike-in normalization04-seacr-peaks.md-- SEACR peak calling and MACS2 alternative05-qc-metrics.md-- Fragment sizes, FRiP, spike-in QC
Walkthrough: Processing ENCODE CUT&RUN from FASTQ to Peaks
Goal: Process CUT&RUN/CUT&Tag FASTQ files through the ENCODE-compatible pipeline to generate peak calls with spike-in normalization. Context: CUT&RUN uses targeted MNase digestion (lower background than ChIP-seq) but requires different peak calling (SEACR instead of MACS2) and spike-in normalization for quantitative comparisons.
Step 1: Find CUT&RUN experiment
encode_search_experiments(assay_title="CUT&RUN", organism="Homo sapiens")
Expected output:
{
"results": [
{"accession": "ENCSR900CUR", "assay_title": "CUT&RUN", "target": "H3K27me3", "biosample_summary": "K562", "assembly": ["GRCh38"], "status": "released"}
],
"total": 35,
"limit": 25,
"offset": 0,
"has_more": true,
"next_offset": 25
}
Step 2: List FASTQ files
encode_list_files(experiment_accession="ENCSR900CUR", file_format="fastq")
Expected output (a JSON array of file records; fields abridged):
[
{"accession": "ENCFF900CR1", "file_format": "fastq", "output_type": "reads", "biological_replicates": [1], "file_size": 839252000, "file_size_human": "800.4 MB", "status": "released"},
{"accession": "ENCFF901CR2", "file_format": "fastq", "output_type": "reads", "biological_replicates": [1], "file_size": 891394000, "file_size_human": "850.1 MB", "status": "released"}
]
Interpretation: CUT&RUN yields smaller files than ChIP-seq (~800MB vs ~2.5GB) due to lower background.
Step 3: Name the files so a read-pair glob can find them
ENCODE FASTQs are named by accession, so the two mates of a pair share no
prefix, and the workflow matches file pairs with a {1,2} glob. Which mate a
file is comes from its page on encodeproject.org (paired_end 1 or 2, and
paired_with naming the other accession), not from any tool here. Link the
files into the shape the glob expects:
mkdir -p fastq
ln -s "$PWD/ENCFF900CR1.fastq.gz" fastq/ENCSR900CUR_R1.fastq.gz
ln -s "$PWD/ENCFF901CR2.fastq.gz" fastq/ENCSR900CUR_R2.fastq.gz
Step 4: Run the CUT&RUN pipeline
nextflow run scripts/main.nf \
-profile local \
--reads 'fastq/ENCSR900CUR_R{1,2}.fastq.gz' \
--bowtie2_index '/ref/bowtie2_index/genome' \
--spikein_index '/ref/bowtie2_ecoli/ecoli' \
--chrom_sizes '/ref/hg38.chrom.sizes' \
--blacklist '/ref/hg38-blacklist.v2.bed' \
--peak_caller seacr \
--outdir results/ \
-resume
Key pipeline steps:
- FastQC on the raw reads, then adapter trimming (Trim Galore,
--nextera) - Bowtie2 alignment (
--very-sensitive --no-mixed --no-discordant --dovetail -I 10 -X 700) - Spike-in alignment of the read pairs that did not map to the genome
- Scale factor per sample (minimum spike-in count / sample count)
- Filter (MAPQ 10, proper pairs), remove duplicates with Picard, remove blacklist regions
- SEACR peak calling from the fragment bedGraph (stringent by default)
- Signal bigWig with
bamCoverage, scaled by the spike-in factor - FRiP of the filtered BAM against every peak set called for the sample,
written to
qc/{sample}.frip_mqc.tsv
Step 5: Validate output quality
Use the QC threshold table above with alignment/{sample}.dup_metrics.txt,
spikein/{sample}.spikein_counts.txt, qc/{sample}.fragment_sizes.txt and
qc/{sample}.frip_mqc.tsv.
Key difference from ChIP-seq: CUT&RUN has inherently lower background, so peak callers like MACS2 overfit. Use SEACR (Meers et al. 2019) instead.
Step 6: Compare with ChIP-seq for the same target
encode_search_experiments(assay_title="Histone ChIP-seq", biosample_term_name="K562", target="H3K27me3", organism="Homo sapiens")
Interpretation: CUT&RUN typically identifies fewer but higher-confidence peaks than ChIP-seq. Concordant peaks between both methods are the highest confidence.
Integration with downstream skills
- SEACR peaks feed into -> histone-aggregation for cross-experiment comparison
- Spike-in normalized signals feed into -> visualization-workflow
- Peak regions feed into -> regulatory-elements for chromatin state classification
- QC uses different thresholds than ChIP-seq -> quality-assessment (see suspect list)
- Pipeline provenance logged by -> data-provenance
Code Examples
1. Survey CUT&RUN/CUT&Tag availability
encode_get_facets(assay_title="CUT&RUN", organism="Homo sapiens")
Expected output:
{
"target.label": [
{"term": "H3K27me3", "count": 15},
{"term": "H3K4me3", "count": 12},
{"term": "H3K27ac", "count": 8},
{"term": "CTCF", "count": 5}
]
}
2. Find matching ChIP-seq for comparison
encode_search_experiments(assay_title="Histone ChIP-seq", biosample_term_name="K562", target="H3K27me3", organism="Homo sapiens")
Expected output:
{
"results": [
{"accession": "ENCSR000CHI", "assay_title": "Histone ChIP-seq", "target": "H3K27me3", "biosample_summary": "K562", "assembly": ["GRCh38"]}
],
"total": 5,
"limit": 25,
"offset": 0,
"has_more": false,
"next_offset": null
}
3. Track CUT&RUN experiments
encode_track_experiment(accession="ENCSR900CUR", notes="K562 H3K27me3 CUT&RUN - SEACR peaks for comparison with ChIP-seq")
Expected output:
{
"tracking": {
"accession": "ENCSR900CUR",
"action": "tracked"
},
"publications_found": 0,
"publications": [],
"pipelines_found": 0,
"pipelines": []
}
Integration
| This skill produces... | Feed into... | Purpose |
|---|---|---|
| SEACR peaks | histone-aggregation | Cross-experiment comparison (note: different caller than ChIP-seq) |
| Spike-in normalized signal | visualization-workflow | Quantitatively comparable browser tracks |
| Peak regions | regulatory-elements | Chromatin state classification |
| CUT&RUN-specific QC | quality-assessment | Validate with CUT&RUN-appropriate thresholds |
| Peak coordinates | motif-analysis | TF motif discovery at CUT&RUN peaks |
| Pipeline parameters | data-provenance | Record SEACR/spike-in normalization details |
| Peak files | variant-annotation | Identify variants in CUT&RUN peaks |
| Comparison with ChIP-seq | compare-biosamples | Cross-assay concordance analysis |
Related Skills
pipeline-guide-- Parent skill with compute resource assessment and cloud setuphistone-aggregation-- Aggregate histone mark data across samplesquality-assessment-- Evaluate pipeline output quality metricsdata-provenance-- Track all pipeline inputs, outputs, and parametersdownload-encode-- Download ENCODE CUT&RUN FASTQ files for pipeline inputpublication-trust-- Verify literature claims backing analytical decisions
Presenting Results
When reporting CUT&RUN pipeline results:
- SEACR peak counts: Report peak counts for each SEACR mode that was run (default: stringent only; both with
--seacr_mode both). If MACS2 was also run, include those counts for comparison - Spike-in normalization factor: Report the scale factor and spike-in count per sample from
spikein/scale_factors.txtand the spike-in read fraction (ideal 1-10% of total reads). Explain that higher spike-in counts indicate less target enrichment - FRiP: Report it from
qc/{sample}.frip_mqc.tsv, which has one row per peak set called for the sample (SEACR stringent and/or relaxed, and/or MACS2), and judge each against the QC table (>10% pass, 5-10% warning, <5% fail). The value is the fraction of the filtered BAM's alignments that overlap a peak, so mates of a pair count separately; thePeak setcolumn names the peak file each row refers to - Signal track paths: Provide paths to the
signal/{sample}.normalized.bwfiles (spike-in scaled, or RPKM if spike-in was skipped) for genome browser visualization - Fragment size distribution: From
qc/{sample}.fragment_sizes.txt, confirm the expected nucleosomal ladder pattern and note the dominant fragment class (sub-nucleosomal for TFs, mononucleosomal for histone marks) - Key QC metrics: Present mapping rate (>80%), duplication rate (<20%), and spike-in calibration status in a summary table
- Blacklist filtering: State that
--blacklistwas applied to the BAM and that the peak files are unfiltered; note separately whether a suspect list was merged into--blacklistor applied to the peaks manually - Next steps: Suggest
peak-annotationfor gene association of peaks, orvisualization-workflowfor genome browser session generation
For the request: "$ARGUMENTS"
Files (encode-toolkit)
-
references
-
01-qc-trimming.md 2.9 KB
# QC and Trimming for CUT&RUN Data CUT&RUN produces paired-end reads with a characteristic nucleosomal fragment size distribution. Reads are typically shorter than ChIP-seq due to the MNase cleavage mechanism. ## Pre-Trimming QC with FastQC ```bash fastqc --threads 4 --outdir fastqc_raw/ sample_R1.fastq.gz sample_R2.fastq.gz ``` Key checks: - Per-base quality (expect Phred >28) - Adapter content (Nextera or Illumina universal adapter) - Insert size (CUT&RUN fragments are often <150 bp, causing adapter read-through) - Sequence duplication (moderate levels expected with low input) **Note**: CUT&RUN libraries from low cell input often show higher duplication than ChIP-seq. This is expected and not necessarily a quality issue. ## Adapter Trimming with Trim Galore CUT&RUN fragments are often shorter than read length, causing adapter read-through. Aggressive adapter trimming is important. ```bash trim_galore \ --paired \ --quality 20 \ --phred33 \ --length 20 \ --cores 4 \ --fastqc \ --nextera \ --output_dir trim_galore/ \ sample_R1.fastq.gz \ sample_R2.fastq.gz ``` ### Parameter Rationale | Parameter | Value | Reason | |-----------|-------|--------| | `--quality 20` | Phred 20 | Standard quality cutoff | | `--length 20` | 20 bp | Keep short sub-nucleosomal fragments | | `--nextera` | Flag | CUT&RUN often uses Nextera adapters (check protocol) | | `--cores 4` | 4 | Parallel processing | ### Adapter Type Selection Check which adapter was used in library preparation: - **Nextera**: Most CUT&Tag protocols (use `--nextera` flag) - **Illumina TruSeq**: Some CUT&RUN protocols (default Trim Galore detection) - If unsure, let Trim Galore auto-detect (omit `--nextera`) ## Post-Trimming Verification After trimming, verify: - >90% of reads pass quality filter - Adapter contamination removed (often 20-50% for CUT&RUN) - Read length distribution: 20-150 bp (many short reads are expected) High adapter contamination rate (>30%) is NORMAL for CUT&RUN because many fragments are shorter than the read length. ## Fragment Size Check (Post-Alignment) After alignment, verify the fragment size distribution: ```bash samtools view -f 2 -F 1804 sample.bam | \ awk '{if($9 > 0) print $9}' | \ sort -n | uniq -c | \ awk '{print $2, $1}' > fragment_sizes.txt ``` Expected CUT&RUN fragment distribution: - **TF targets**: Peak at <120 bp (sub-nucleosomal) - **Histone marks**: Strong peak at ~150 bp (mononucleosomal) - **Both**: Should show nucleosomal ladder pattern - Broad smear with no peaks suggests protocol failure ## CUT&Tag vs CUT&RUN Trimming CUT&Tag uses Tn5 transposase which adds 19 bp Mosaic End (ME) sequences. For CUT&Tag data specifically: ```bash trim_galore \ --paired \ --quality 20 \ --length 20 \ --cores 4 \ --nextera \ --fastqc \ sample_R1.fastq.gz \ sample_R2.fastq.gz ``` The `--nextera` flag is especially important for CUT&Tag since Tn5 inserts Nextera-compatible adapters. -
02-bowtie2-alignment.md 3.9 KB
# Bowtie2 Alignment for CUT&RUN (Genome + Spike-in) CUT&RUN uses Bowtie2 for alignment with specific settings optimized for the short, paired-end fragments produced by MNase or Tn5 cleavage. Two separate alignments are required: one to the target genome and one to the E. coli spike-in genome. ## Genome Index Preparation ```bash # Target genome (one-time) bowtie2-build --threads 8 genome.fa genome_index # E. coli spike-in genome (one-time) # Use E. coli K12 MG1655 (GenBank: U00096.3) bowtie2-build --threads 4 ecoli_K12.fa ecoli_index ``` ## Target Genome Alignment ```bash bowtie2 \ --very-sensitive \ --no-mixed \ --no-discordant \ --dovetail \ --phred33 \ -I 10 -X 700 \ --threads 8 \ -x genome_index \ -1 sample_R1_val_1.fq.gz \ -2 sample_R2_val_2.fq.gz \ 2> sample_bowtie2.log \ | samtools view -@ 4 -bS - \ | samtools sort -@ 4 -o sample_sorted.bam samtools index sample_sorted.bam ``` ### Bowtie2 Parameters for CUT&RUN | Parameter | Value | Reason | |-----------|-------|--------| | `--very-sensitive` | Preset | Maximum sensitivity for short fragments | | `--no-mixed` | Flag | Both mates must align | | `--no-discordant` | Flag | Mates must be properly paired | | `--dovetail` | Flag | Allow dovetail alignments (overlapping PE reads) | | `-I 10` | 10 bp | Minimum insert size (very short fragments exist) | | `-X 700` | 700 bp | Maximum insert size | **Critical**: The `--dovetail` flag is essential because CUT&RUN fragments are often shorter than read length, causing R1 and R2 to extend past each other (dovetailing). ## Spike-in Alignment Align reads that did NOT map to the target genome to the E. coli spike-in: ```bash # Extract unmapped reads from genome alignment samtools view -b -f 12 -F 256 sample_sorted.bam \ | samtools sort -@ 4 -n -o unmapped_sorted.bam bedtools bamtofastq -i unmapped_sorted.bam \ -fq unmapped_R1.fq -fq2 unmapped_R2.fq # Align to E. coli bowtie2 \ --very-sensitive \ --no-mixed \ --no-discordant \ --dovetail \ --phred33 \ -I 10 -X 700 \ --threads 4 \ -x ecoli_index \ -1 unmapped_R1.fq \ -2 unmapped_R2.fq \ 2> sample_spikein.log \ | samtools view -@ 2 -bS -q 10 -F 1804 -f 2 - \ | samtools sort -@ 2 -o sample_spikein.bam samtools index sample_spikein.bam ``` ### Alternative: Direct Spike-in Alignment Some workflows align ALL reads to both genomes simultaneously using a concatenated index. This is simpler but less precise: ```bash # Concatenate genomes (one-time) cat genome.fa ecoli_K12.fa > combined.fa bowtie2-build --threads 8 combined.fa combined_index # Align to combined genome bowtie2 --very-sensitive --no-mixed --no-discordant --dovetail \ -I 10 -X 700 --threads 8 \ -x combined_index \ -1 R1.fq.gz -2 R2.fq.gz \ | samtools view -bS - > combined.bam # Separate by genome samtools view -b combined.bam chr1 chr2 ... chrX chrY > genome.bam samtools view -b combined.bam ecoli_chr > spikein.bam ``` ## Spike-in Read Counts ```bash # Count spike-in reads spikein_count=$(samtools view -c -F 1804 -f 2 sample_spikein.bam) genome_count=$(samtools view -c -F 1804 -f 2 sample_sorted.bam) echo "Spike-in reads: ${spikein_count}" echo "Genome reads: ${genome_count}" echo "Spike-in fraction: $(echo "scale=4; $spikein_count / ($spikein_count + $genome_count)" | bc)" ``` Expected spike-in fraction: - **1-10%**: Optimal range for normalization - **<0.1%**: Too few spike-in reads for reliable normalization - **>30%**: Excessive spike-in; may indicate poor target enrichment ## Alignment QC ```bash # Parse Bowtie2 log for mapping rate grep "overall alignment rate" sample_bowtie2.log ``` Expected mapping rates: - **Target genome**: >80% for standard samples - **Spike-in**: spike-in reads should be 1-10% of all reads (spike-in / (spike-in + genome), as computed above) Low genome mapping rate may indicate: - Contamination (check FastQ Screen) - Wrong genome build - Very poor library quality -
03-filtering-spikein.md 5 KB
# Filtering, Deduplication, and Spike-in Normalization CUT&RUN data processing requires standard quality filtering, duplicate removal, blacklist filtering, AND spike-in normalization for quantitative analysis. ## Quality Filtering ```bash samtools view -b -h \ -q 10 \ -F 1804 \ -f 2 \ sample_sorted.bam \ | samtools sort -@ 4 -o sample_filtered.bam ``` ### Filter Parameters | Flag | Meaning | |------|---------| | `-q 10` | MAPQ >= 10 (CUT&RUN uses lower threshold than ChIP-seq) | | `-F 4` | Remove unmapped | | `-F 256` | Remove secondary | | `-F 512` | Remove QC-fail | | `-F 1024` | Remove duplicates -- a no-op here; duplicates are removed by Picard in the next step | | `-f 2` | Keep properly paired only | **Note**: MAPQ 10 instead of 30 for CUT&RUN. The lower threshold retains more signal because CUT&RUN targets can be in repetitive regions. ## Duplicate Marking ```bash picard MarkDuplicates \ INPUT=sample_filtered.bam \ OUTPUT=sample_dedup.bam \ METRICS_FILE=sample_dup_metrics.txt \ REMOVE_DUPLICATES=true \ VALIDATION_STRINGENCY=LENIENT \ ASSUME_SORTED=true samtools index sample_dedup.bam ``` CUT&RUN from low cell numbers may have higher duplication. Accept up to 40%. ## Blacklist Filtering The workflow filters the BAM against the single file given as `--blacklist` and stops there: peak files are never filtered, and there is no separate suspect-list parameter. ```bash # What the workflow runs, with --blacklist as -b bedtools intersect \ -a sample_dedup.bam \ -b hg38-blacklist.v2.bed \ -v \ > sample_final.bam samtools index sample_final.bam ``` To also exclude the CUT&RUN-specific suspect list (Nordin 2023) -- ~400 regions enriched in CUT&RUN controls that produce false positive peaks, independent of the ENCODE blacklist -- merge the two files once and pass the result as `--blacklist`: ```bash cat hg38-blacklist.v2.bed CUTandRUN.suspectlist.hg38.bed \ | sort -k1,1 -k2,2n | bedtools merge > combined_blacklist.bed ``` ## Spike-in Normalization ### Calculate Scale Factors The workflow writes one count file per sample (`spikein/{sample}.spikein_counts.txt`, columns sample and count) and then one combined `spikein/scale_factors.txt` for the whole run: ```bash # Per-sample counts, concatenated cat *.spikein_counts.txt > all_counts.txt # Scale every sample to the smallest non-zero count (factor = min / count). # A sample with no spike-in reads is left unscaled (factor 1). min_count=$(awk -F'\t' '$2 > 0 {print $2}' all_counts.txt | sort -n | head -1) awk -F'\t' -v min="${min_count:-0}" 'BEGIN {OFS="\t"} { factor = ($2 > 0 && min > 0) ? min / $2 : 1 print $1, $2, factor }' all_counts.txt > scale_factors.txt ``` ### Apply Spike-in Scaling to Signal The workflow scales the bigWig only, with deepTools: ```bash # Read scale factor for one sample scale=$(awk -F'\t' -v s="sample1" '$1==s {print $3}' scale_factors.txt) bamCoverage \ --bam sample_final.bam \ --outFileName sample_normalized.bw \ --scaleFactor ${scale} \ --binSize 10 \ --normalizeUsing None \ --extendReads \ --numberOfProcessors 4 ``` Without a spike-in index the workflow drops `--scaleFactor` and uses `--normalizeUsing RPKM` instead. ### Alternative: bedGraph route (not used by the workflow) ```bash bedtools genomecov \ -ibam sample_final.bam \ -bg \ -pc \ -scale ${scale} \ -g hg38.chrom.sizes \ | sort -k1,1 -k2,2n > sample_normalized.bedGraph bedGraphToBigWig sample_normalized.bedGraph hg38.chrom.sizes sample_normalized.bw ``` ## Generate Fragment BED File SEACR takes a fragment bedGraph, built from a fragment BED. `bedtools bamtobed -bedpe` needs mates on adjacent lines, so name-sort the BAM first -- on a coordinate-sorted BAM it warns per read that the mate does not occur next to it and emits a near-empty BED: ```bash # Name-sort first samtools sort -n -@ 2 -o namesorted.bam sample_final.bam # Keep properly paired fragments on one chromosome and shorter than 1 kb bedtools bamtobed -bedpe -i namesorted.bam \ | awk 'BEGIN {OFS="\t"} $1 == $4 && $6 - $2 < 1000 {print $1, $2, $6}' \ | sort -k1,1 -k2,2n -k3,3n \ > sample.fragments.bed # Fragment bedGraph for SEACR -- deliberately unscaled bedtools genomecov \ -i sample.fragments.bed \ -g hg38.chrom.sizes \ -bg \ > sample_fragments.bedGraph ``` The workflow does not apply the spike-in factor here: SEACR sees unscaled fragment coverage, and only the bigWig is calibrated. The BED is published as `signal/{sample}.fragments.bed`; the bedGraph is an intermediate. ## QC Statistics ```bash # Final read count echo "Final reads: $(samtools view -c sample_final.bam)" # Flagstat (the workflow publishes this as alignment/{sample}.flagstat.txt) samtools flagstat sample_final.bam > sample_flagstat.txt # Spike-in fraction; the spike-in BAM is an intermediate, so read the # published count file instead genome=$(samtools view -c -F 1804 -f 2 sample_final.bam) spikein=$(cut -f2 spikein/sample.spikein_counts.txt) echo "Spike-in fraction: $(echo "scale=4; $spikein / ($genome + $spikein)" | bc)" ``` -
04-seacr-peaks.md 5 KB
# SEACR Peak Calling for CUT&RUN SEACR (Sparse Enrichment Analysis for CUT&RUN) is specifically designed for the sparse, low-background signal profile of CUT&RUN data. It outperforms MACS2 on CUT&RUN data because it does not assume a Poisson background model. ## SEACR with IgG Control When an IgG control is available: ```bash SEACR_1.3.sh \ sample_fragments.bedGraph \ control_IgG_fragments.bedGraph \ norm \ stringent \ sample_seacr ``` ### Parameters | Argument | Value | Description | |----------|-------|-------------| | Arg 1 | sample bedGraph | Treatment signal (fragment coverage) | | Arg 2 | control bedGraph | IgG/no-antibody control signal | | Arg 3 | `norm` | Normalize control to treatment depth | | Arg 4 | `stringent` | Stringent mode (conservative peaks) | | Arg 5 | output prefix | Output file prefix | ## SEACR without Control (Top %) When no control is available, SEACR uses a numeric threshold: ```bash SEACR_1.3.sh \ sample_fragments.bedGraph \ 0.01 \ non \ stringent \ sample_seacr_noctrl ``` `non` is required here: the SEACR v1.3 README states that a numeric threshold must be paired with `non`. The v1.3 script does not error on `norm` -- it silently skips normalization -- so the mistake is invisible. The workflow always passes `non` when there is no `--control`. The `0.01` value means the top 1% of signal is used as the enrichment threshold. Adjust based on expected peak count: - `0.01` (1%): Conservative, fewer peaks - `0.05` (5%): Moderate - `0.10` (10%): Permissive, more peaks ## SEACR Stringent vs Relaxed Run both modes to compare: ```bash # Stringent: Only peaks that pass both global and local enrichment SEACR_1.3.sh sample.bedGraph control.bedGraph norm stringent sample_stringent # Relaxed: Peaks passing global enrichment threshold only SEACR_1.3.sh sample.bedGraph control.bedGraph norm relaxed sample_relaxed ``` | Mode | Description | Typical Peak Count | |------|-------------|-------------------| | Stringent | Global AND local enrichment | 5,000-20,000 | | Relaxed | Global enrichment only | 10,000-50,000 | ## SEACR Output Format SEACR v1.3 outputs a 6-column BED-like file: ``` chr1 1000 2000 500.5 8.2 chr1:1450-1480 ``` Columns: 1. Chromosome 2. Peak start 3. Peak end 4. Total signal in the peak (AUC) 5. Max signal in the peak 6. Region of maximum signal, as `chr:start-end` The workflow names these files `{sample}.seacr.stringent.bed` and, with `--seacr_mode relaxed` or `both`, `{sample}.seacr.relaxed.bed`, published to `peaks/`. ## Alternative: MACS2 Peak Calling MACS2 can be used as an alternative or validation: ```bash macs2 callpeak \ -t sample_final.bam \ -c control_IgG.bam \ -f BAMPE \ -g hs \ -n sample_macs2 \ --nomodel \ --keep-dup all \ -q 0.05 \ --outdir macs2_peaks/ ``` ### MACS2 Parameters for CUT&RUN | Parameter | Value | Reason | |-----------|-------|--------| | `-f BAMPE` | Paired-end | Use fragment information | | `--nomodel` | Skip model | CUT&RUN fragments don't follow ChIP model | | `--keep-dup all` | Keep all | Duplicates already removed | | `-q 0.05` | FDR 0.05 | Standard threshold | **Caution**: MACS2 may overcall peaks on CUT&RUN data due to the low background. Compare with SEACR results and use the intersection for high-confidence peaks. ## Blacklist + Suspect List Filtering (manual, not run by this workflow) The workflow applies `--blacklist` to the BAM only and never filters peak files. To filter the published peaks against both the blacklist and the CUT&RUN suspect list, run this yourself: ```bash bedtools intersect \ -a results/peaks/sample.seacr.stringent.bed \ -b hg38-blacklist.v2.bed CUTandRUN.suspectlist.hg38.bed \ -v \ > sample_peaks_filtered.bed ``` ## Peak Overlap Between Callers When using both SEACR and MACS2, assess concordance: ```bash # Convert SEACR to 3-column BED cut -f1-3 results/peaks/sample.seacr.stringent.bed > seacr_peaks.bed cut -f1-3 results/peaks/sample.macs2_peaks.narrowPeak > macs2_peaks.bed # Overlap bedtools intersect -a seacr_peaks.bed -b macs2_peaks.bed -u | wc -l total_seacr=$(wc -l < seacr_peaks.bed) total_macs2=$(wc -l < macs2_peaks.bed) echo "SEACR peaks: $total_seacr" echo "MACS2 peaks: $total_macs2" ``` Typical overlap: 60-80% of SEACR peaks overlap MACS2 peaks. High-confidence set: intersection of both callers. ## FRiP Calculation The FRIP process runs this for every peak set called for a sample and writes the results to `qc/{sample}.frip_mqc.tsv`: ```bash total_reads=$(samtools view -c results/alignment/sample.filtered.bam) reads_in_peaks=$(bedtools intersect \ -u \ -a results/alignment/sample.filtered.bam \ -b results/peaks/sample.seacr.stringent.bed \ | samtools view -c -) awk -v a="$reads_in_peaks" -v b="$total_reads" 'BEGIN { printf "FRiP: %.4f\n", a / b }' ``` Both counts are alignments, with no flag filter, so mates count separately. Judge the result against the QC table in `SKILL.md`; see `05-qc-metrics.md` for the published file's columns. -
05-qc-metrics.md 4.6 KB
# CUT&RUN QC Metrics Quality assessment for CUT&RUN data includes standard alignment metrics, CUT&RUN-specific fragment analysis, spike-in validation, and peak quality. Pass/warn/fail thresholds live in one place: the QC table in `SKILL.md`. The commands below show how to derive each value, including the ones the workflow does not compute (spike-in fraction, peak statistics). ## Fragment Size Distribution The fragment size distribution is the most informative CUT&RUN QC metric: ```bash # Extract fragment sizes from properly paired reads samtools view -f 2 -F 1804 sample_final.bam | \ awk '{if($9 > 0 && $9 < 1000) print $9}' | \ sort -n | uniq -c | \ awk '{print $2, $1}' > fragment_sizes.txt ``` The workflow runs exactly this and publishes `qc/{sample}.fragment_sizes.txt`. ### Expected Patterns by Target | Target Type | Fragment Pattern | Example | |-------------|-----------------|---------| | TF (CTCF, etc.) | Peak <120 bp, some at 150 bp | Sharp sub-nucleosomal | | Active histone (H3K4me3) | Strong 150 bp peak | Mononucleosomal | | Repressive histone (H3K27me3) | 150 bp + 300 bp | Mono + dinucleosomal | | IgG control | Flat distribution | No enrichment pattern | ### Red Flags in Fragment Distribution - No nucleosomal periodicity: Protocol may have failed - Only large fragments (>300 bp): Over-digestion or poor tagmentation - Spike at exact read length: Adapter trimming incomplete - Identical to IgG: No target enrichment ## Spike-in QC ### Spike-in Fraction The spike-in BAM is an intermediate; the published per-sample count file is `spikein/{sample}.spikein_counts.txt` (columns sample and count): ```bash genome=$(samtools view -c -F 1804 -f 2 results/alignment/sample.filtered.bam) spikein=$(cut -f2 results/spikein/sample.spikein_counts.txt) fraction=$(echo "scale=4; $spikein / ($genome + $spikein)" | bc) echo "Spike-in fraction: $fraction" ``` Interpretation of the fraction (thresholds: see the QC table in `SKILL.md`): too little spike-in makes the normalization imprecise, too much indicates poor target enrichment. ### Spike-in Consistency Across Samples For reliable normalization, spike-in counts should vary across samples (reflecting different amounts of target material), but not be zero. The workflow already collects them: ```bash sort -k2 -n results/spikein/scale_factors.txt ``` Columns: sample, spike-in count, scale factor. ## Alignment Statistics The workflow publishes `alignment/{sample}.flagstat.txt` and `alignment/{sample}.dup_metrics.txt`, and the Bowtie2 logs reach `multiqc/multiqc_report.html`. To recompute: ```bash samtools flagstat results/alignment/sample.filtered.bam > flagstat.txt ``` Mapping rate, properly paired fraction and duplication rate are judged against the QC table in `SKILL.md`. ## FRiP (Fraction of Reads in Peaks) The FRIP process computes this and publishes `qc/{sample}.frip_mqc.tsv`, one row per peak set called for the sample (SEACR stringent and/or relaxed, and/or MACS2). Columns: `Peak set` (the peak file), `FRiP`, `reads_in_peaks`, `total_reads`. MultiQC shows the same table as "Fraction of reads in peaks". This is what it runs for each peak set: ```bash total=$(samtools view -c results/alignment/sample.filtered.bam) in_peaks=$(bedtools intersect \ -u \ -a results/alignment/sample.filtered.bam \ -b results/peaks/sample.seacr.stringent.bed \ | samtools view -c -) awk -v a="$in_peaks" -v b="$total" 'BEGIN { printf "FRiP: %.4f\n", a / b }' ``` Both counts are alignments of the filtered BAM with no further flag filter, so the two mates of a fragment count separately. Counting differently (for example with `-F 1804 -f 2`) gives a number that does not match the published one. CUT&RUN typically has higher FRiP than ChIP-seq because of lower background. Use the FRiP row of the QC table in `SKILL.md` for the thresholds. ## Peak Count and Size ```bash # Peak statistics total_peaks=$(wc -l < results/peaks/sample.seacr.stringent.bed) echo "Total peaks: $total_peaks" # Peak size distribution awk '{print $3-$2}' results/peaks/sample.seacr.stringent.bed | \ awk '{sum+=$1; n++; a[n]=$1} END { asort(a); print "Median peak size:", a[int(n/2)]; print "Mean peak size:", sum/n; print "Min:", a[1]; print "Max:", a[n] }' ``` ## MultiQC Aggregation ```bash multiqc \ --title "CUT&RUN Pipeline QC" \ --filename multiqc_report \ --outdir multiqc/ \ fastqc/ trim_galore/ alignment/ qc/ ``` ## Summary QC Table Generate a per-sample summary: ```bash echo -e "Sample\tReads\tMap_Rate\tDedup_Rate\tSpikein_Frac\tPeaks\tFRiP\tFrag_Peak" echo -e "${SAMPLE}\t${TOTAL}\t${MAP_RATE}\t${DUP_RATE}\t${SPIKEIN}\t${PEAKS}\t${FRIP}\t${FRAG}" ``` -
literature.md 10.9 KB
# CUT&RUN Pipeline — Literature References **Last updated:** 2026-03-07 **Purpose:** Reference catalog for the pipeline-cutandrun skill — papers defining CUT&RUN and CUT&Tag methods, SEACR peak calling, spike-in normalization, and the CUT&RUN suspect list for artifact filtering. --- ## CUT&RUN / CUT&Tag Method Development --- ### Skene & Henikoff 2017 — CUT&RUN: targeted nuclease strategy - **Citation:** Skene PJ, Henikoff S. An efficient targeted nuclease strategy for high-resolution mapping of DNA binding sites. eLife, 6:e21856, 2017. - **DOI:** [10.7554/eLife.21856](https://doi.org/10.7554/eLife.21856) - **PMID:** 28079019 | **PMC:** PMC5310842 - **Citations:** ~1,500 - **Key findings:** Introduced Cleavage Under Targets and Release Using Nuclease (CUT&RUN), which tethers protein A-Micrococcal Nuclease (pA-MNase) to an antibody bound to a target protein in situ, then activates cleavage by calcium addition. Released chromatin fragments diffuse out of the nucleus and are collected from the supernatant, eliminating the need for chromatin solubilization or immunoprecipitation. Produces extremely low background compared to ChIP-seq because only targeted fragments are released, while bulk chromatin remains in the nucleus. Requires as few as 100 cells and generates high-quality profiles for both histone marks and transcription factors with minimal sequencing depth (~5M reads vs 20-40M for ChIP-seq). The E. coli DNA carried over from pA-MNase production serves as an internal spike-in for normalization. --- ### Kaya-Okur et al. 2019 — CUT&Tag: efficient epigenomic profiling - **Citation:** Kaya-Okur HS, Wu SJ, Codomo CA, Pledger ES, Bryson TD, Henikoff JG, Ahmad K, Henikoff S. CUT&Tag for efficient epigenomic profiling of small samples and single cells. Nature Communications, 10(1):1930, 2019. - **DOI:** [10.1038/s41467-019-09982-5](https://doi.org/10.1038/s41467-019-09982-5) - **PMID:** 31036827 | **PMC:** PMC6488672 - **Citations:** ~1,200 - **Key findings:** Introduced Cleavage Under Targets and Tagmentation (CUT&Tag), which replaces pA-MNase with protein A-Tn5 transposase (pA-Tn5). After antibody tethering, Tn5 simultaneously fragments and tags target chromatin with sequencing adapters. Key advantages over CUT&RUN: streamlined single-tube workflow, compatible with single-cell applications, and no separate library preparation step needed. However, CUT&Tag has higher background than CUT&RUN due to Tn5 insertion preferences in accessible chromatin. Both methods are supported by this pipeline with the same alignment and peak calling workflow, differing only in spike-in source (E. coli from Tn5 vs MNase production). --- ### Skene & Henikoff 2018 — CUT&RUN protocol optimization - **Citation:** Skene PJ, Henikoff JG, Henikoff S. Targeted in situ genome-wide profiling with high efficiency for low cell numbers. Nature Protocols, 13(5):1006-1019, 2018. - **DOI:** [10.1038/nprot.2018.015](https://doi.org/10.1038/nprot.2018.015) - **PMID:** 29651053 - **Citations:** ~500 - **Key findings:** Detailed step-by-step CUT&RUN protocol with optimization guidelines for different targets (histone marks vs TFs). Established the standard experimental parameters: ConA bead binding for cell immobilization, 0°C calcium-activated cleavage for 30 minutes, fragment release at 37°C, and library preparation with NEBNext reagents. Provided troubleshooting guidance for common issues including low yield, high background, and incomplete cleavage. This protocol forms the basis for most published CUT&RUN experiments and informs the QC expectations in this pipeline. --- ## Peak Calling --- ### Meers et al. 2019 — SEACR: peak calling for CUT&RUN - **Citation:** Meers MP, Tenenbaum D, Henikoff S. Peak calling by Sparse Enrichment Analysis for CUT&RUN chromatin profiling. Epigenetics & Chromatin, 12(1):42, 2019. - **DOI:** [10.1186/s13072-019-0287-4](https://doi.org/10.1186/s13072-019-0287-4) - **PMID:** 31300027 | **PMC:** PMC6626385 - **Citations:** ~800 - **Key findings:** Introduced SEACR (Sparse Enrichment Analysis for CUT&RUN), a peak caller specifically designed for the sparse, low-background signal profile of CUT&RUN data. Unlike MACS2 (which models background as a Poisson distribution), SEACR uses the empirical distribution of signal in control (IgG) or target data to identify enriched regions without parametric assumptions. Offers two modes: stringent (peaks must exceed both the global threshold and a local enrichment test) and relaxed (global threshold only). When no IgG control is available, SEACR uses the top 1% of target signal as a threshold. Benchmarking showed SEACR produces fewer false positives than MACS2 on CUT&RUN data, particularly in regions with low but genuine enrichment. --- ## Quality Control --- ### Nordin et al. 2023 — CUT&RUN suspect list - **Citation:** Nordin A, Zambanini G, Pagella P, Bhatt DK, Bjork P, Nilsson J, Mead P, Boyle AP. The CUT&RUN suspect list of problematic regions of the genome. Genome Biology, 24:185, 2023. - **DOI:** [10.1186/s13059-023-02960-3](https://doi.org/10.1186/s13059-023-02960-3) - **PMID:** 37580722 | **PMC:** PMC10424377 - **Citations:** ~50 - **Key findings:** Identified genomic regions that produce artifactual signal in CUT&RUN and CUT&Tag experiments, distinct from the standard ENCODE blacklist. These "suspect" regions include areas with high MNase/Tn5 accessibility, specific repeat families, and regions prone to antibody-independent cleavage. The suspect list should be applied in addition to the ENCODE blacklist v2 (Amemiya et al. 2019) when filtering CUT&RUN/CUT&Tag peaks. Without suspect list filtering, up to 20% of called peaks may be artifacts, particularly for targets with moderate enrichment. This workflow applies only the single BED given as `--blacklist`, to the BAM; pass a merged blacklist + suspect list there, or filter the peaks manually. --- ### Meers et al. 2019 — Spike-in normalization for CUT&RUN/CUT&Tag - **Citation:** Meers MP, Bryson TD, Henikoff JG, Henikoff S. Improved CUT&RUN chromatin profiling tools. eLife, 8:e46314, 2019. - **DOI:** [10.7554/eLife.46314](https://doi.org/10.7554/eLife.46314) - **PMID:** 31232687 | **PMC:** PMC6632061 - **Citations:** ~400 - **Key findings:** Established the spike-in calibration framework for quantitative CUT&RUN. E. coli DNA carried over from pA-MNase production provides an internal standard: the ratio of spike-in reads between samples inversely correlates with target enrichment efficiency. Scale factors computed from spike-in counts enable quantitative comparison of signal intensity across samples and conditions. Demonstrated that spike-in normalization is essential for detecting global changes in histone modifications (e.g., drug treatments that globally increase or decrease a mark), which would be invisible with standard library-size normalization. This calibration approach is implemented in the pipeline's spike-in normalization step. --- ## Supplementary Tools (Non-CUT&RUN-Specific) See pipeline-chipseq/references/literature.md for detailed descriptions of shared tools, and pipeline-atacseq/references/literature.md for Bowtie2. --- ### Langmead & Salzberg 2012 — Bowtie 2 - **DOI:** [10.1038/nmeth.1923](https://doi.org/10.1038/nmeth.1923) | **PMID:** 22388286 | **Citations:** ~47,300 - **CUT&RUN role:** Alignment of CUT&RUN/CUT&Tag reads to both the target genome and the E. coli spike-in genome. Bowtie2 is preferred over BWA-MEM for CUT&RUN because the short fragments typical of CUT&RUN (~150 bp mononucleosomal, <120 bp sub-nucleosomal) are well-suited to Bowtie2's alignment algorithm. Run with --very-sensitive and --dovetail flags. --- ### Zhang et al. 2008 — MACS2 - **DOI:** [10.1186/gb-2008-9-9-r137](https://doi.org/10.1186/gb-2008-9-9-r137) | **PMID:** 18798982 | **Citations:** ~7,000 - **CUT&RUN role:** Alternative peak caller for CUT&RUN data. MACS2 can be used instead of or alongside SEACR, but tends to overcall peaks due to CUT&RUN's low background. When using MACS2 on CUT&RUN data, use --nomodel and set appropriate --shift/--extsize parameters. Useful for comparison with ChIP-seq results processed with the same peak caller. --- ### Li et al. 2009 — SAMtools - **DOI:** [10.1093/bioinformatics/btp352](https://doi.org/10.1093/bioinformatics/btp352) | **PMID:** 19505943 | **Citations:** ~53,700 - **CUT&RUN role:** BAM sorting, filtering, indexing, and alignment statistics. --- ### Broad Institute — Picard MarkDuplicates - **URL:** [https://broadinstitute.github.io/picard/](https://broadinstitute.github.io/picard/) - **CUT&RUN role:** PCR duplicate marking. CUT&RUN typically has lower duplication rates than ChIP-seq because it requires less input material and fewer PCR cycles. Duplication rates >20% suggest overamplification. --- ### Quinlan & Hall 2010 — BEDTools - **DOI:** [10.1093/bioinformatics/btq033](https://doi.org/10.1093/bioinformatics/btq033) | **PMID:** 20110278 | **Citations:** ~12,000 - **CUT&RUN role:** Used by the workflow to filter the BAM against `--blacklist`, to build the fragment BED and bedGraph, and to count reads in peaks for FRiP (`bedtools intersect -u`); used manually for peak filtering, which the workflow does not run. --- ### Ramírez et al. 2016 — deepTools2 - **DOI:** [10.1093/nar/gkw257](https://doi.org/10.1093/nar/gkw257) | **PMID:** 27079975 | **Citations:** ~6,100 - **CUT&RUN role:** Generates spike-in normalized signal tracks (bigWig) using bamCoverage with the --scaleFactor parameter computed from spike-in read counts. Also used for fingerprint plots and heatmaps. --- ### Amemiya et al. 2019 — ENCODE Blacklist - **DOI:** [10.1038/s41598-019-45839-z](https://doi.org/10.1038/s41598-019-45839-z) | **PMID:** 31249361 | **Citations:** ~1,372 - **CUT&RUN role:** The file normally passed as `--blacklist`, which the workflow applies to the BAM. Both filters are worth applying: the blacklist addresses general sequencing/alignment artifacts while the CUT&RUN suspect list (Nordin 2023) addresses CUT&RUN-specific enzyme cleavage artifacts. Merge the two into one BED and pass it as `--blacklist`, or filter the peaks manually. --- ### Ewels et al. 2016 — MultiQC - **DOI:** [10.1093/bioinformatics/btw354](https://doi.org/10.1093/bioinformatics/btw354) | **PMID:** 27312411 | **Citations:** ~6,800 - **CUT&RUN role:** Aggregates QC metrics from FastQC, Bowtie2, Picard, SEACR, and spike-in statistics into a unified HTML report. --- ### Andrews 2010 — FastQC - **URL:** [https://www.bioinformatics.babraham.ac.uk/projects/fastqc/](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) - **CUT&RUN role:** Raw read quality assessment. CUT&RUN libraries typically show high-quality bases and characteristic nucleosomal fragment sizes. --- ### Martin 2011 — Cutadapt (basis for Trim Galore) - **DOI:** [10.14806/ej.17.1.200](https://doi.org/10.14806/ej.17.1.200) | **Citations:** ~13,000 - **CUT&RUN role:** Adapter trimming. CUT&RUN sub-nucleosomal fragments frequently read through into adapters, making trimming important for accurate alignment.
-
-
scripts
-
Dockerfile 2.9 KB · in bundle
-
main.nf 16.1 KB · in bundle
-
nextflow.config 4.3 KB · in bundle
-
-
SKILL.md 25.3 KB
--- name: pipeline-cutandrun description: "Execute CUT&RUN processing pipeline from FASTQ to peaks and signal tracks. Child of pipeline-guide. Provides Nextflow execution with Docker and cloud deployment. Use when processing CUT&RUN or CUT&Tag data, an alternative to ChIP-seq with lower background. Trigger on: CUT&RUN pipeline, CUT&Tag, SEACR, Henikoff, targeted chromatin, pA-MNase, process CUT&RUN." --- # ENCODE CUT&RUN Pipeline: FASTQ to Peaks and Signal Tracks ## When to Use - User wants to run a CUT&RUN or CUT&Tag processing pipeline from FASTQ to peaks - User asks about "CUT&RUN pipeline", "CUT&Tag", "SEACR", "spike-in normalization", or "targeted chromatin" - User needs to process CUT&RUN/CUT&Tag data with spike-in calibration and SEACR peak calling - Example queries: "process my CUT&RUN FASTQs", "run SEACR on CUT&Tag data", "normalize CUT&RUN with spike-in controls" Execute the CUT&RUN/CUT&Tag processing pipeline for targeted chromatin profiling, producing peak calls with SEACR and spike-in normalized signal tracks. ## Pipeline Overview ``` FASTQ |-> FastQC (raw reads) +-> Trim Galore -> Bowtie2 (genome) -> {sample}.sorted.bam | |-> unmapped read pairs -> Bowtie2 (spike-in) -> counts -> scale_factors.txt | | +-> filter (MAPQ 10, proper pairs) -> Picard MarkDuplicates | (removed) -> blacklist filter -> {sample}.filtered.bam | |-> fragment BED -> fragment bedGraph -> SEACR peaks | |-> MACS2 peaks (with --peak_caller macs2|both) | |-> FRiP vs every peak set -> {sample}.frip_mqc.tsv | +-> bamCoverage -> {sample}.normalized.bw <-- factor ---+ ``` ### Not run by this workflow - **Peak-level filtering**: `--blacklist` is applied to the BAM only. Peak files are never filtered afterwards, and there is no separate suspect-list input. Pass a pre-merged blacklist + suspect-list BED as `--blacklist`, or filter the peak files yourself. - **Spike-in scaling of the SEACR input**: only the bigWig is scaled (`bamCoverage --scaleFactor`). The fragment bedGraph given to SEACR is unscaled. ### ENCODE Repository - ENCODE does not publish an official CUT&RUN pipeline. This workflow follows the published CUT&RUN/CUT&Tag processing protocol (Bowtie2, fragment bedGraphs, SEACR) and applies ENCODE conventions for filtering, blacklisting, and QC. - **Container**: built from `scripts/Dockerfile` in this skill (`docker build -t encode-toolkit/pipeline-cutandrun:1.0.0 scripts/`); override with `--container` - **This skill**: Nextflow DSL2 reimplementation for portability ## Core Tools and Versions Versions are those installed by `scripts/Dockerfile`, which is what the workflow runs. | Tool | Version | Purpose | Citation | |------|---------|---------|----------| | Bowtie2 | 2.5.4 | Alignment (genome + spike-in) | Langmead & Salzberg 2012 | | SEACR | 1.3 | Peak calling (CUT&RUN-specific) | Meers et al. 2019 | | MACS2 | 2.2.9.1 | Alternative peak caller | Zhang et al. 2008 | | Picard | 3.1.1 | Duplicate marking and removal | Broad Institute | | samtools | 1.19 | BAM operations | Li et al. 2009 | | bedtools | 2.31.0 | Genomic arithmetic | Quinlan & Hall 2010 | | deepTools | 3.5.5 | Signal track generation | Ramirez et al. 2016 | | Trim Galore | 0.6.10 | Adapter trimming | Krueger (Babraham) | | FastQC | 0.12.1 | Read quality | Andrews (Babraham) | | MultiQC | 1.21 | Aggregated QC | Ewels et al. 2016 | The conda alternative (`cutandrun-env.yml`) pins the same version of every tool in the table above, but installs no SEACR (only `r-base`): SEACR is not a conda package, so on that route `SEACR_1.3.sh` and `SEACR_1.3.R` must be fetched separately from the SEACR repository. ## Key Literature 1. **Skene & Henikoff 2017** - "An efficient targeted nuclease strategy for high-resolution mapping of DNA binding sites" (eLife, ~1,500 citations) DOI: 10.7554/eLife.21856 2. **Meers et al. 2019** - "Peak calling by Sparse Enrichment Analysis for CUT&RUN chromatin profiling" (Epigenetics & Chromatin, ~800 citations) DOI: 10.1186/s13072-019-0287-4 3. **Kaya-Okur et al. 2019** - "CUT&Tag for efficient epigenomic profiling of small samples and single cells" (Nature Communications, ~1,200 citations) DOI: 10.1038/s41467-019-09982-5 4. **Nordin et al. 2023** - "The CUT&RUN suspect list of problematic regions" (Genome Biology) DOI: 10.1186/s13059-023-02960-3 5. **Amemiya et al. 2019** - "The ENCODE Blacklist" (Scientific Reports, ~1,372 citations) DOI: 10.1038/s41598-019-45839-z ## Execution ### Quick Start (Local) ```bash nextflow run scripts/main.nf \ -profile local \ --reads '/data/fastq/*_R{1,2}.fastq.gz' \ --bowtie2_index '/ref/bowtie2_index/genome' \ --spikein_index '/ref/bowtie2_ecoli/ecoli' \ --chrom_sizes '/ref/hg38.chrom.sizes' \ --blacklist '/ref/hg38-blacklist.v2.bed' \ --outdir results/ \ -resume ``` ### SLURM HPC ```bash nextflow run scripts/main.nf \ -profile slurm \ --container /path/to/pipeline-cutandrun.sif \ --reads '/data/fastq/*_R{1,2}.fastq.gz' \ --bowtie2_index '/ref/bowtie2_index/genome' \ --spikein_index '/ref/bowtie2_ecoli/ecoli' \ --chrom_sizes '/ref/hg38.chrom.sizes' \ --blacklist '/ref/hg38-blacklist.v2.bed' \ --outdir results/ \ -resume ``` ### Cloud (GCP / AWS) ```bash # Google Cloud Batch nextflow run scripts/main.nf -profile gcp \ --container us-docker.pkg.dev/<project>/<repo>/pipeline-cutandrun:1.0.0 \ --gcp_project <project> \ --gcp_workdir gs://<bucket>/work \ --reads 'gs://<bucket>/fastq/*_R{1,2}.fastq.gz' \ --bowtie2_index gs://<bucket>/ref/bowtie2_index/genome \ --spikein_index gs://<bucket>/ref/bowtie2_ecoli/ecoli \ --chrom_sizes gs://<bucket>/ref/hg38.chrom.sizes \ --blacklist gs://<bucket>/ref/hg38-blacklist.v2.bed \ --outdir gs://<bucket>/results # AWS Batch nextflow run scripts/main.nf -profile aws \ --container <account>.dkr.ecr.<region>.amazonaws.com/pipeline-cutandrun:1.0.0 \ --aws_queue <job-queue> \ --aws_workdir s3://<bucket>/work \ --reads 's3://<bucket>/fastq/*_R{1,2}.fastq.gz' \ --bowtie2_index s3://<bucket>/ref/bowtie2_index/genome \ --spikein_index s3://<bucket>/ref/bowtie2_ecoli/ecoli \ --chrom_sizes s3://<bucket>/ref/hg38.chrom.sizes \ --blacklist s3://<bucket>/ref/hg38-blacklist.v2.bed \ --outdir s3://<bucket>/results ``` `--outdir` only sets where results are published; Google Batch and AWS Batch stage every task through the work directory, and the workflow stops with an error if it or the project/queue is missing. ## Resource Requirements | Step | CPUs | RAM | Time (per sample) | |------|------|-----|-------------------| | Bowtie2 align (genome) | 8 | 8 GB | 30-60 min | | Bowtie2 align (spike-in) | 4 | 4 GB | 10-20 min | | Filter/dedup | 4 | 8 GB | 15-30 min | | SEACR peaks | 2 | 4 GB | 10-20 min | | Signal tracks | 4 | 8 GB | 15-30 min | | **Total** | **8** | **8 GB** | **1.5-3 hours** | The RAM column is each step's first-attempt request. These processes ask for that much memory per attempt, so a task killed for exceeding it is retried with more (at most two retries, capped by `--max_memory`). Failures with any other exit status stop the run. ## Pipeline Parameters | Parameter | Default | Description | |-----------|---------|-------------| | `--reads` | required | Glob pattern to paired FASTQ files | | `--bowtie2_index` | required | Bowtie2 genome index prefix (every file starting with this prefix is staged) | | `--spikein_index` | `null` | Bowtie2 spike-in index prefix (E. coli by convention). When given, signal tracks are spike-in calibrated | | `--chrom_sizes` | required | Chromosome sizes file | | `--blacklist` | required | Blacklist BED applied to the BAM. Pass a pre-merged blacklist + CUT&RUN suspect list here if you want both | | `--outdir` | `./results` | Output directory | | `--seacr_mode` | `stringent` | SEACR mode: `stringent`, `relaxed`, or `both` | | `--seacr_norm` | `norm` | SEACR normalization to the control: `norm` or `non`. Only used with `--control`; without a control the workflow always passes `non` | | `--seacr_threshold` | `0.01` | Top fraction of signal kept by SEACR when no `--control` is given | | `--control` | `null` | IgG control BAM, already filtered and deduplicated. Converted to a fragment bedGraph for SEACR and passed as `-c` to MACS2 | | `--macs2_gsize` | `hs` | MACS2 effective genome size (`hs`, `mm`, or a number) | | `--peak_caller` | `seacr` | Peak caller: `seacr`, `macs2`, or `both` | | `--skip_spikein` | `false` | Skip spike-in calibration; signal tracks are then RPKM-normalized | ### Infrastructure parameters (`nextflow.config`) | Parameter | Default | Description | |-----------|---------|-------------| | `--container` | `encode-toolkit/pipeline-cutandrun:1.0.0` | Image built from `scripts/Dockerfile`. Pass a registry image for `gcp`/`aws`, or a `.sif` file for `slurm` | | `--max_cpus`, `--max_memory`, `--max_time` | `16`, `16.GB`, `12.h` | Upper bounds applied to every process | | `--slurm_queue`, `--slurm_account` | `normal`, none | SLURM partition and account | | `--gcp_project`, `--gcp_workdir` | none (both required for `-profile gcp`) | Google Cloud project and `gs://` work directory | | `--gcp_location`, `--gcp_disk` | `us-central1`, `200.GB` | Google Batch region and per-task disk | | `--aws_queue`, `--aws_workdir` | none (both required for `-profile aws`) | AWS Batch job queue and `s3://` work directory | | `--aws_region`, `--aws_cli_path` | `us-east-1`, `/home/ec2-user/miniconda/bin/aws` | AWS region, and the AWS CLI path inside the Batch AMI | ## Output Files ``` results/ fastqc/ # Raw read quality trim_galore/ # Trimmed reads, trimming reports, # and FastQC of the trimmed reads alignment/ {sample}.filtered.bam # Quality-filtered, deduplicated, blacklist-filtered {sample}.filtered.bam.bai {sample}.dup_metrics.txt # Picard MarkDuplicates metrics {sample}.flagstat.txt # samtools flagstat on the filtered BAM spikein/ # Only with --spikein_index {sample}.spikein_counts.txt # sample, spike-in read count scale_factors.txt # One file for the run: sample, spikein_count, scale_factor peaks/ {sample}.seacr.stringent.bed # SEACR stringent peaks {sample}.seacr.relaxed.bed # With --seacr_mode relaxed or both {sample}.macs2_peaks.narrowPeak # With --peak_caller macs2 or both signal/ {sample}.normalized.bw # Spike-in scaled, or RPKM without spike-in {sample}.fragments.bed # Fragment BED (same chromosome, <1 kb) qc/ {sample}.fragment_sizes.txt {sample}.frip_mqc.tsv # FRiP, one row per peak set called for the sample multiqc/ multiqc_report.html pipeline_info/ timeline.html report.html trace.txt ``` The fragment bedGraph that SEACR consumes is an intermediate and is not published; the published `signal/{sample}.fragments.bed` is the BED it is built from. ## QC Thresholds This is the only QC threshold table for this skill; the reference files point back to it. | Metric | Pass | Warning | Fail | Computed from | |--------|------|---------|------|---------------| | Mapping rate (genome) | >80% | 60-80% | <60% | Bowtie2 log (in `multiqc_report.html`) | | Spike-in reads | 1-10% of total | 0.1-1% or 10-30% | <0.1% or >30% | `spikein/{sample}.spikein_counts.txt` | | Duplication rate | <20% | 20-40% | >40% | `alignment/{sample}.dup_metrics.txt` | | FRiP (peaks) | >10% | 5-10% | <5% | `qc/{sample}.frip_mqc.tsv` (also a MultiQC table) | | Peak count | >5,000 | 1,000-5,000 | <1,000 | `peaks/{sample}.seacr.*.bed` | | Fragment size | Nucleosomal pattern | Irregular | No pattern | `qc/{sample}.fragment_sizes.txt` | ### Fragment Size Distribution CUT&RUN produces a characteristic nucleosomal ladder: - **<120 bp**: Sub-nucleosomal (TF binding) - **~150 bp**: Mononucleosomal (histone marks) - **~300 bp**: Dinucleosomal - Absence of nucleosomal pattern suggests protocol issues ## Spike-in Normalization Spike-in normalization is CRITICAL for CUT&RUN quantitative comparison. ### How It Works 1. E. coli DNA is carried over from pA-MNase/pA-Tn5 production 2. Each sample has a different amount of spike-in reads 3. Samples with more target cleavage have fewer spike-in reads (proportionally) 4. Scale factor = smallest non-zero spike-in count across samples / this sample's count ### Scale Factor Calculation With three samples whose spike-in counts are 200,000, 400,000 and 100,000, the minimum is 100,000: ``` Sample A: 200,000 spike-in reads -> scale = 100,000 / 200,000 = 0.5 Sample B: 400,000 spike-in reads -> scale = 100,000 / 400,000 = 0.25 Sample C: 100,000 spike-in reads -> scale = 100,000 / 100,000 = 1.0 (minimum) ``` Higher spike-in counts = less target enrichment = lower scale factor. All samples are written to one `spikein/scale_factors.txt` (columns: sample, spike-in count, scale factor). A sample with no spike-in reads cannot be calibrated and is left unscaled (factor 1). The factor is applied only to the bigWig via `bamCoverage --scaleFactor`; the fragment bedGraph SEACR reads is unscaled. ## SEACR vs MACS2 | Feature | SEACR | MACS2 | |---------|-------|-------| | Designed for | CUT&RUN/CUT&Tag | ChIP-seq | | Background model | Sparse enrichment | Dynamic Poisson | | Control required | Optional (IgG) | Recommended | | Low background | Handles well | May overcall | | Stringent mode | Very conservative | Via q-value | | ENCODE recommendation | Primary for CUT&RUN | Alternative | SEACR is specifically designed for the sparse, low-background signal profile of CUT&RUN data. MACS2 may overcall peaks due to the low background. ## Critical Pitfalls ### Spike-in Calibration is CRITICAL Without spike-in normalization, quantitative comparisons between samples are unreliable. The amount of pA-MNase (or pA-Tn5) varies between experiments, and spike-in reads provide the internal calibration standard. Without `--spikein_index` (or with `--skip_spikein`) the bigWigs fall back to RPKM, which is not quantitatively comparable across samples. ### IgG Control vs No-Antibody Control - **IgG control**: Non-specific antibody, captures background binding - **No-antibody**: No antibody, captures MNase accessibility background - IgG is preferred but not always available - SEACR can work without a control: it then uses `--seacr_threshold` (default 0.01, the top 1% of signal) and, as SEACR v1.3 requires with a numeric threshold, the `non` normalization mode ### SEACR Stringent vs Relaxed Mode - **Stringent**: Returns only the most enriched peaks (fewer, higher confidence) - **Relaxed**: Returns a broader set including weaker peaks - For initial analysis, use stringent mode (the default) - For comprehensive catalogs, use `--seacr_mode both` and filter downstream ### CUT&RUN Suspect List (Nordin 2023) The workflow applies `--blacklist` to the BAM only; it never filters the peak files and takes no separate suspect list. To use the CUT&RUN suspect list (Nordin et al. 2023), which identifies regions with artifactual signal specific to CUT&RUN/CUT&Tag protocols, either pass a merged BED as `--blacklist` or filter the peaks afterwards yourself: ```bash # Download suspect list wget https://github.com/Boyle-Lab/Blacklist/raw/master/lists/CUTandRUN.suspectlist.hg38.bed.gz # Option 1: merge once and pass as --blacklist (filters the BAM) zcat CUTandRUN.suspectlist.hg38.bed.gz | cat hg38-blacklist.v2.bed - \ | sort -k1,1 -k2,2n | bedtools merge > combined_blacklist.bed # Option 2: filter the published peaks afterwards (manual) bedtools intersect \ -a results/peaks/sample.seacr.stringent.bed \ -b combined_blacklist.bed \ -v \ > sample_peaks_filtered.bed ``` ### CUT&RUN vs CUT&Tag Both protocols are supported by this pipeline. Differences: - **CUT&RUN**: Uses pA-MNase, E. coli spike-in from MNase production - **CUT&Tag**: Uses pA-Tn5, E. coli spike-in from Tn5 production - CUT&Tag has higher background from Tn5 insertion preference - CUT&Tag may work better for histone marks; CUT&RUN for TFs ## Provenance Integration After pipeline completion, log all outputs: ```python encode_log_derived_file( file_path="/results/peaks/sample1.seacr.stringent.bed", source_accessions=["ENCSR...", "ENCFF..."], description="CUT&RUN peaks from ENCODE CUT&RUN pipeline", file_type="CUT&RUN_peaks", tool_used="Bowtie2 2.5.4 + SEACR 1.3", parameters="stringent mode, threshold 0.01 non, BAM blacklist-filtered (peaks unfiltered)" ) ``` ## Reference Files Detailed step-by-step documentation is provided in the `references/` directory: 1. `01-qc-trimming.md` -- Read QC and adapter trimming for CUT&RUN 2. `02-bowtie2-alignment.md` -- Bowtie2 alignment to genome and spike-in 3. `03-filtering-spikein.md` -- Filtering, dedup, and spike-in normalization 4. `04-seacr-peaks.md` -- SEACR peak calling and MACS2 alternative 5. `05-qc-metrics.md` -- Fragment sizes, FRiP, spike-in QC ## Walkthrough: Processing ENCODE CUT&RUN from FASTQ to Peaks **Goal**: Process CUT&RUN/CUT&Tag FASTQ files through the ENCODE-compatible pipeline to generate peak calls with spike-in normalization. **Context**: CUT&RUN uses targeted MNase digestion (lower background than ChIP-seq) but requires different peak calling (SEACR instead of MACS2) and spike-in normalization for quantitative comparisons. ### Step 1: Find CUT&RUN experiment ``` encode_search_experiments(assay_title="CUT&RUN", organism="Homo sapiens") ``` Expected output: ```json { "results": [ {"accession": "ENCSR900CUR", "assay_title": "CUT&RUN", "target": "H3K27me3", "biosample_summary": "K562", "assembly": ["GRCh38"], "status": "released"} ], "total": 35, "limit": 25, "offset": 0, "has_more": true, "next_offset": 25 } ``` ### Step 2: List FASTQ files ``` encode_list_files(experiment_accession="ENCSR900CUR", file_format="fastq") ``` Expected output (a JSON array of file records; fields abridged): ```json [ {"accession": "ENCFF900CR1", "file_format": "fastq", "output_type": "reads", "biological_replicates": [1], "file_size": 839252000, "file_size_human": "800.4 MB", "status": "released"}, {"accession": "ENCFF901CR2", "file_format": "fastq", "output_type": "reads", "biological_replicates": [1], "file_size": 891394000, "file_size_human": "850.1 MB", "status": "released"} ] ``` **Interpretation**: CUT&RUN yields smaller files than ChIP-seq (~800MB vs ~2.5GB) due to lower background. ### Step 3: Name the files so a read-pair glob can find them ENCODE FASTQs are named by accession, so the two mates of a pair share no prefix, and the workflow matches file pairs with a `{1,2}` glob. Which mate a file is comes from its page on encodeproject.org (`paired_end` 1 or 2, and `paired_with` naming the other accession), not from any tool here. Link the files into the shape the glob expects: ```bash mkdir -p fastq ln -s "$PWD/ENCFF900CR1.fastq.gz" fastq/ENCSR900CUR_R1.fastq.gz ln -s "$PWD/ENCFF901CR2.fastq.gz" fastq/ENCSR900CUR_R2.fastq.gz ``` ### Step 4: Run the CUT&RUN pipeline ```bash nextflow run scripts/main.nf \ -profile local \ --reads 'fastq/ENCSR900CUR_R{1,2}.fastq.gz' \ --bowtie2_index '/ref/bowtie2_index/genome' \ --spikein_index '/ref/bowtie2_ecoli/ecoli' \ --chrom_sizes '/ref/hg38.chrom.sizes' \ --blacklist '/ref/hg38-blacklist.v2.bed' \ --peak_caller seacr \ --outdir results/ \ -resume ``` Key pipeline steps: 1. FastQC on the raw reads, then adapter trimming (Trim Galore, `--nextera`) 2. Bowtie2 alignment (`--very-sensitive --no-mixed --no-discordant --dovetail -I 10 -X 700`) 3. Spike-in alignment of the read pairs that did not map to the genome 4. Scale factor per sample (minimum spike-in count / sample count) 5. Filter (MAPQ 10, proper pairs), remove duplicates with Picard, remove blacklist regions 6. SEACR peak calling from the fragment bedGraph (stringent by default) 7. Signal bigWig with `bamCoverage`, scaled by the spike-in factor 8. FRiP of the filtered BAM against every peak set called for the sample, written to `qc/{sample}.frip_mqc.tsv` ### Step 5: Validate output quality Use the QC threshold table above with `alignment/{sample}.dup_metrics.txt`, `spikein/{sample}.spikein_counts.txt`, `qc/{sample}.fragment_sizes.txt` and `qc/{sample}.frip_mqc.tsv`. **Key difference from ChIP-seq**: CUT&RUN has inherently lower background, so peak callers like MACS2 overfit. Use SEACR (Meers et al. 2019) instead. ### Step 6: Compare with ChIP-seq for the same target ``` encode_search_experiments(assay_title="Histone ChIP-seq", biosample_term_name="K562", target="H3K27me3", organism="Homo sapiens") ``` **Interpretation**: CUT&RUN typically identifies fewer but higher-confidence peaks than ChIP-seq. Concordant peaks between both methods are the highest confidence. ### Integration with downstream skills - SEACR peaks feed into -> **histone-aggregation** for cross-experiment comparison - Spike-in normalized signals feed into -> **visualization-workflow** - Peak regions feed into -> **regulatory-elements** for chromatin state classification - QC uses different thresholds than ChIP-seq -> **quality-assessment** (see suspect list) - Pipeline provenance logged by -> **data-provenance** ## Code Examples ### 1. Survey CUT&RUN/CUT&Tag availability ``` encode_get_facets(assay_title="CUT&RUN", organism="Homo sapiens") ``` Expected output: ```json { "target.label": [ {"term": "H3K27me3", "count": 15}, {"term": "H3K4me3", "count": 12}, {"term": "H3K27ac", "count": 8}, {"term": "CTCF", "count": 5} ] } ``` ### 2. Find matching ChIP-seq for comparison ``` encode_search_experiments(assay_title="Histone ChIP-seq", biosample_term_name="K562", target="H3K27me3", organism="Homo sapiens") ``` Expected output: ```json { "results": [ {"accession": "ENCSR000CHI", "assay_title": "Histone ChIP-seq", "target": "H3K27me3", "biosample_summary": "K562", "assembly": ["GRCh38"]} ], "total": 5, "limit": 25, "offset": 0, "has_more": false, "next_offset": null } ``` ### 3. Track CUT&RUN experiments ``` encode_track_experiment(accession="ENCSR900CUR", notes="K562 H3K27me3 CUT&RUN - SEACR peaks for comparison with ChIP-seq") ``` Expected output: ```json { "tracking": { "accession": "ENCSR900CUR", "action": "tracked" }, "publications_found": 0, "publications": [], "pipelines_found": 0, "pipelines": [] } ``` ## Integration | This skill produces... | Feed into... | Purpose | |---|---|---| | SEACR peaks | **histone-aggregation** | Cross-experiment comparison (note: different caller than ChIP-seq) | | Spike-in normalized signal | **visualization-workflow** | Quantitatively comparable browser tracks | | Peak regions | **regulatory-elements** | Chromatin state classification | | CUT&RUN-specific QC | **quality-assessment** | Validate with CUT&RUN-appropriate thresholds | | Peak coordinates | **motif-analysis** | TF motif discovery at CUT&RUN peaks | | Pipeline parameters | **data-provenance** | Record SEACR/spike-in normalization details | | Peak files | **variant-annotation** | Identify variants in CUT&RUN peaks | | Comparison with ChIP-seq | **compare-biosamples** | Cross-assay concordance analysis | ## Related Skills - `pipeline-guide` -- Parent skill with compute resource assessment and cloud setup - `histone-aggregation` -- Aggregate histone mark data across samples - `quality-assessment` -- Evaluate pipeline output quality metrics - `data-provenance` -- Track all pipeline inputs, outputs, and parameters - `download-encode` -- Download ENCODE CUT&RUN FASTQ files for pipeline input - `publication-trust` -- Verify literature claims backing analytical decisions ## Presenting Results When reporting CUT&RUN pipeline results: - **SEACR peak counts**: Report peak counts for each SEACR mode that was run (default: stringent only; both with `--seacr_mode both`). If MACS2 was also run, include those counts for comparison - **Spike-in normalization factor**: Report the scale factor and spike-in count per sample from `spikein/scale_factors.txt` and the spike-in read fraction (ideal 1-10% of total reads). Explain that higher spike-in counts indicate less target enrichment - **FRiP**: Report it from `qc/{sample}.frip_mqc.tsv`, which has one row per peak set called for the sample (SEACR stringent and/or relaxed, and/or MACS2), and judge each against the QC table (>10% pass, 5-10% warning, <5% fail). The value is the fraction of the filtered BAM's alignments that overlap a peak, so mates of a pair count separately; the `Peak set` column names the peak file each row refers to - **Signal track paths**: Provide paths to the `signal/{sample}.normalized.bw` files (spike-in scaled, or RPKM if spike-in was skipped) for genome browser visualization - **Fragment size distribution**: From `qc/{sample}.fragment_sizes.txt`, confirm the expected nucleosomal ladder pattern and note the dominant fragment class (sub-nucleosomal for TFs, mononucleosomal for histone marks) - **Key QC metrics**: Present mapping rate (>80%), duplication rate (<20%), and spike-in calibration status in a summary table - **Blacklist filtering**: State that `--blacklist` was applied to the BAM and that the peak files are unfiltered; note separately whether a suspect list was merged into `--blacklist` or applied to the peaks manually - **Next steps**: Suggest `peak-annotation` for gene association of peaks, or `visualization-workflow` for genome browser session generation ## For the request: "$ARGUMENTS"
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.