bio-chipseq-qc

SkillAI & models

Assesses ChIP-seq quality across antibody specificity, fragmentation, enrichment, replicate concordance, and library complexity. Computes FRiP, NSC/RSC (phantompeakqualtools), library complexity (NRF/PBC1/PBC2), deepTools plotFingerprint (JS distance, AUC, synthetic JS), ChIPQC, IDR with ENCODE Nself/Nt rules, and detects hyper-ChIPable artifacts. Use when validating an antibody, diagnosing failed peak calls, deciding whether to proceed with downstream analysis, grading against ENCODE thresholds, or auditing replicate concordance.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the bio-chipseq-qc skill

What this skill tells your AI

The instructions your AI receives, as published by pku-yuangroup/openai4s in skills/bioskills/bio-chip-seq-chipseq-qc/SKILL.md and read by ahel’s review.

Version Compatibility

Reference examples tested with: deepTools 3.5+, phantompeakqualtools 1.2.2+, ChIPQC 1.42+, IDR 2.0.4+, samtools 1.19+, bedtools 2.31+, pysam 0.22+, pybedtools 0.9+, MACS2 2.2.9+, MACS3 3.0.4+.

Verify versions before relying on numerical thresholds — phantompeakqualtools has known R-version compatibility issues with R ≥ 4.0 (use kundajelab fork or pin to R 3.6).

ChIP-seq Quality Control

"Should I trust this ChIP-seq experiment?" -> Validate antibody, fragmentation, enrichment, replicate concordance, library complexity, and absence of hyper-ChIPable artifacts before committing to downstream peak calling and differential analysis.

  • CLI: Rscript run_spp.R -c=chip.bam -out=cc.txt (NSC/RSC), plotFingerprint -b chip.bam input.bam (enrichment shape), idr --samples rep1.np rep2.np (replicate IDR)
  • R: ChIPQC package (Carroll & Stark; computes the full ENCODE metric battery)
  • Python: pysam + pybedtools for custom FRiP and library-complexity metrics

ChIP-seq fails for many independent reasons. The QC metrics below probe distinct failure modes — passing one metric does not rescue another. Antibody failure cannot be fixed by sequencing more.

The Antibody Problem is the Real Problem

Every downstream metric is conditional on antibody specificity. "ChIP-grade" on a vendor datasheet is marketing, not validation. Run the cascade:

StepWhatWhy
1. Western blotExpected MW + KO/KD negativeConfirms the antibody hits a band of the right size and loses signal in KO
2. IP-WesternPulls down the proteinConfirms IP recovery, not just recognition
3. ChIP-qPCRKnown positive + known negative lociFirst chromatin-context test; cheap
4. ChIP-seq biological replicateTwo independent biological replicatesReproducibility check
5. KO/KD orthogonalChIP in KO/KD cellsGold-standard: signal should drop to background
6. Peptide array (histones)Epicypher SNAP-ChIP or equivalentTests modification-state specificity

Histone modification cross-reactivity is universal: H3K9me2 vs H3K9me3, H3K27me2 vs H3K27me3, and H3K4me1 vs H3K4me2 antibodies routinely show 10-30% cross-reactivity. Polyclonals vary lot-to-lot. CRISPR-knockout-validated lots from CST and Epicypher are the modern standard. Always record antibody catalog number + lot in methods.

Fragment-Size Distribution is a Free Diagnostic

The fragment-size distribution from a properly prepared ChIP BAM is itself a quality readout:

Distribution shapeInterpretation
Sharp peak at ~50-100 bp (sub-nucleosomal)Direct TF binding; expected for well-fragmented TF ChIP
Sharp peak at ~150 bp + secondary at ~300 bpMono- + di-nucleosomal; expected for histone ChIP
Bimodal at 150 + 300, no sub-nucleosomalHistone-only signal; in TF ChIP, suggests trapping / hyper-ChIPable
Broad continuum 100-1000 bpOver-sonication; biology lost; cannot be rescued
No peak structure, flatSevere over-sonication or library prep failure
# Quick diagnostic — count fragment sizes from properly-paired reads
samtools view -f 0x2 sample.bam | awk '{print $9}' | awk '$1>0' \
    | sort -n | uniq -c | awk '{print $2, $1}' > fragment_sizes.tsv

For CUT&Tag: 25-75 bp characteristic; fragments < 25 bp are Tn5 self-tagmentation noise (see cut-and-run-tag).

QC Metric Battery with ENCODE Thresholds

MetricToolTF thresholdHistone thresholdSource / rationale
FRiP (Fraction of Reads in Peaks)bedtools / pysam / featureCounts≥ 0.01 minimum, > 0.05 ideal≥ 0.05, > 0.20 ideal; > 0.15 for H3K4me3Landt 2012; ENCODE flags experiments with FRiP < 1%
NSC (Normalized Strand Cross-correlation)phantompeakqualtools> 1.05 marginal, > 1.10 ideal> 1.05Landt 2012; min = 1 (no enrichment); ratio of fragment-length CC to background
RSC (Relative Strand Cross-correlation)phantompeakqualtools> 0.8 marginal, > 1.0 ideal> 0.8Landt 2012; ratio of (fragment - background) / (phantom - background)
QualityTagphantompeakqualtools≥ 0 acceptable, 1-2 ideal≥ 0Composite based on NSC/RSC; -2 to 2 scale
NRF (Non-Redundant Fraction)unique_pos / total> 0.8> 0.8ENCODE; < 0.5 severe PCR bottleneck
PBC1 (M1 / Mdistinct)bedtools / pysam> 0.8> 0.8ENCODE; fraction of singly-occupied positions
PBC2 (M1 / M2)bedtools / pysam> 3> 3ENCODE; ratio of singletons to doubletons
JS distance (plotFingerprint)deepTools> 0.3> 0.05 (broad) to > 0.3 (narrow)Distance between cumulative signal curves IP vs Input
AUC (plotFingerprint)deepTools< 0.60.6-0.9Input = ~0.5; lower AUC = more enrichment concentrated
Synthetic JS (plotFingerprint)deepToolsShould ≈ measured JSSanity check vs simulated null
Replicate Spearman correlationdeepTools multiBamSummary / plotCorrelation> 0.8 (true reps)> 0.8 (true reps), > 0.6 (broad)Replicates should correlate more than cross-condition
Read count per replicatesamtools flagstat≥ 20M unique mapped20M (narrow histone), 40-60M (broad histone)ENCODE 2012

Practical operational rule: Compute the full battery. Reject any sample failing FRiP OR antibody validation OR fragment-size sanity check, regardless of other metrics. Failing one of NSC/RSC alone with strong FRiP can sometimes be rescued for narrow-peak biology; broad histones are more forgiving on NSC.

Hyper-ChIPable Region Detection

Teytelman 2013 (PNAS): untagged GFP, no antibody, or non-existent targets all produce "binding" signal at highly-transcribed loci (rRNA, tRNA, histone gene clusters, snoRNA hosts, mtDNA, abundant housekeeping genes). ENCODE blacklist v2 (Amemiya 2019) catches repeat-driven artifacts but NOT these hyper-ChIPable transcribed regions.

Detection:

# Top 1% input signal as cell-type-specific custom blacklist
multiBigwigSummary BED-file -b input.bw -o input_signal.npz \
    --BED genes.bed --outRawCounts input_per_gene.tsv
awk 'NR > 1' input_per_gene.tsv | sort -k4,4nr | head -n $(($(wc -l < input_per_gene.tsv) / 100)) \
    > hyper_chipable.bed

# Intersect peaks against this list; flag peaks falling in hyper-ChIPable regions
bedtools intersect -a peaks.narrowPeak -b hyper_chipable.bed -u > suspicious_peaks.bed

Disprove a suspicious peak: Required for any claim at rRNA loci, tRNA clusters, HIST1/2 clusters, mitochondrial DNA:

  1. Motif enrichment at peak (artifact has no enrichment)
  2. KO/KD signal loss at peak (artifact persists)
  3. Untagged-protein control ChIP shows no signal at this locus

Many "novel binding" claims at the rDNA repeat, mtDNA, and HIST1 cluster are spurious artifacts.

Computing the Battery

FRiP

total_reads=$(samtools view -c -F 260 chip.bam)
reads_in_peaks=$(bedtools intersect -a chip.bam -b peaks.narrowPeak -u | samtools view -c -)
frip=$(echo "scale=4; $reads_in_peaks / $total_reads" | bc)

NSC / RSC / fragment length (phantompeakqualtools)

Rscript run_spp.R -c=chip.bam -savp=qc/chip_cc.pdf -out=qc/chip_cc.txt
# Output columns: filename | numReads | estFragLen | corr_estFragLen |
#                 phantomPeak | corr_phantomPeak | argmin_corr | min_corr |
#                 NSC | RSC | QualityTag

Library complexity

# NRF
total=$(samtools view -c -F 260 chip.bam)
unique=$(samtools view -F 260 chip.bam | awk '{print $1, $3, $4}' | sort -u | wc -l)
nrf=$(echo "scale=4; $unique / $total" | bc)

# PBC1, PBC2 (singletons vs distinct positions vs doubletons)
samtools view -F 260 chip.bam | awk '{print $3":"$4}' | sort | uniq -c \
    | awk '{
        if ($1 == 1) m1++;
        if ($1 == 2) m2++;
        mdist++;
      } END {
        print "M1:", m1; print "M2:", m2; print "Mdistinct:", mdist;
        print "PBC1:", m1/mdist; print "PBC2:", m1/m2
      }'

deepTools plotFingerprint

plotFingerprint \
    -b chip.bam input.bam \
    --labels ChIP Input \
    -o qc/fingerprint.pdf \
    --outRawCounts qc/fingerprint_counts.tab \
    --outQualityMetrics qc/fingerprint_qc.txt
# Inspect qc/fingerprint_qc.txt: AUC, JS distance, synthetic JS, X-intercept
# Good ChIP: AUC < 0.6 (TF), JS > 0.3 (TF); Input near diagonal (AUC ~ 0.5)

Replicate Spearman correlation

multiBamSummary bins -b rep1.bam rep2.bam rep3.bam input.bam \
    --binSize 10000 -o results.npz
plotCorrelation -in results.npz --corMethod spearman \
    --whatToPlot heatmap --plotNumbers -o corr.pdf \
    --outFileCorMatrix corr_matrix.tab
# Replicates: > 0.8 (narrow), > 0.6 (broad)
# Cross-condition reps should correlate less than within-condition

ChIPQC R package

library(ChIPQC)
samples <- read.csv('samples.csv')
qc <- ChIPQC(samples, annotation = 'hg38')
ChIPQCreport(qc, reportFolder = 'ChIPQCreport')
# Generates the full ENCODE battery report per sample in one call

ChIPQC remains Bioconductor-maintained but mature; phantompeakqualtools is the canonical NSC/RSC source.

IDR and Replicate Consistency Rules

For TFs: signal-ranked IDR with Nself/Nt consistency check; see chip-seq/peak-calling for full ENCODE workflow. Key thresholds:

  • True replicate IDR threshold: 0.05
  • Pseudoreplicate IDR threshold: 0.10 (per-rep self-consistency)
  • Nself/Nt rule: max(N1self, N2self) / min(N1self, N2self) ≤ 2 AND max(Nt, max(Nself)) / min(Nt, min(Nself)) ≤ 2. Failing both ratios rejects the library.

For histones: naive overlap with ≥ 40% reciprocal overlap (ENCODE default; commonly misquoted as 50%). IDR is too conservative for histone signal dynamic range.

ENCODE 3 vs ENCODE 4 Thresholds (unchanged for most QC)

MetricENCODE 3ENCODE 4
FRiP minimum1%1% (unchanged)
NSC threshold> 1.05> 1.05 (unchanged)
RSC threshold> 0.8> 0.8 (unchanged)
NRF threshold> 0.8> 0.8 (unchanged)
Blacklistv1v2 (Amemiya 2019)
Read depth (TF)≥ 20M unique mapped≥ 20M unchanged
Read depth (broad histone)≥ 40M40-60M recommended

Most QC thresholds are stable across ENCODE versions; blacklist update is the main practical change.

Per-Tool Failure Modes

phantompeakqualtools / SPP -- R version incompatibility

Trigger: Running with R ≥ 4.0.

Mechanism: spp R package has unmaintained Boost / Rcpp dependencies; some shifts produce NaN cross-correlation values.

Symptom: NSC = NaN, RSC = NaN, or fragment length = 0 in output.

Fix: Pin to R 3.6 + spp 1.16 via conda env; OR use the kundajelab/phantompeakqualtools fork (current); OR substitute deepTools plotFingerprint for enrichment QC and macs3 predictd for fragment length.

deepTools plotFingerprint -- Wrong baseline assumption for broad marks

Trigger: Interpreting JS distance with TF threshold (> 0.3) on broad histone mark.

Mechanism: Broad marks have less concentrated signal; JS distance is naturally lower (0.05-0.15 for H3K27me3) without indicating bad ChIP.

Symptom: Reports "failed JS distance" for high-quality broad-mark ChIP.

Fix: Use mark-specific thresholds: > 0.3 for TFs and sharp histones; > 0.05 for broad histones; check AUC instead (0.6-0.9 for broad; < 0.6 for TF/sharp).

FRiP -- Computed before vs after blacklist filtering

Trigger: Calling FRiP from peak file pre- vs post-blacklist.

Mechanism: Hyper-ChIPable regions inflate "reads in peaks" because most reads at those loci are artifacts.

Symptom: FRiP looks great (>15%) but most of it is rRNA / mtDNA reads.

Fix: Apply blacklist + custom hyper-ChIPable filter BEFORE computing FRiP; or report both raw and filtered FRiP.

NRF / PBC -- Computed after deduplication

Trigger: Running NRF on a MarkDuplicates-filtered BAM.

Mechanism: Library complexity metrics measure PCR redundancy; if duplicates are already removed, NRF = 1.0 by construction (uninformative).

Symptom: NRF reports 0.99-1.0; metric is meaningless.

Fix: Compute NRF / PBC1 / PBC2 on the PRE-deduplication BAM. ENCODE-compliant pipeline: filter -> MarkDuplicates (don't remove) -> compute NRF -> filter out duplicates -> call peaks.

IDR -- Wrong rank column

Trigger: Sorting narrowPeak by signalValue (column 7) for IDR.

Mechanism: MACS signalValue scales with pile-up intensity which differs between libraries of different depth; rank correlation breaks.

Symptom: IDR returns 0 reproducible peaks despite good replicate Spearman correlation.

Fix: Sort by p-value (-k8,8nr), pass --rank p.value to IDR. ENCODE convention.

ChIPQC -- Default annotation mismatch

Trigger: Using annotation = 'hg19' on hg38-aligned data.

Mechanism: ChIPQC computes feature-context enrichment from the specified annotation; mismatch silently corrupts enrichment metrics.

Symptom: Promoter / 5'UTR / 3'UTR enrichments look wrong; replicate report metrics drift.

Fix: Match annotation to the genome the BAMs were aligned to; for custom genomes pass a TxDb object explicitly.

Reconciliation: When Metrics Disagree

PatternLikely causeAction
Good FRiP, bad NSCHigh background but real enrichmentAcceptable for broad marks; for TFs, check phantompeakqualtools fragment length is reasonable
Good NSC, bad FRiPStrong cross-correlation signal but few peaks pass q-valueLibrary shallow OR peak caller threshold too strict; try -p 1e-2
Good FRiP and NSC, bad replicate correlationReal biology + replicate-specific batch effectCheck sample swap; check sequencing batch; consider PCA
Good Rep1, bad Rep2One replicate failedDrop Rep2 + repeat; do NOT average metrics
All metrics failAntibody or fragmentation failureRe-validate antibody (KO/KD); inspect fragment-size distribution; do not proceed
FRiP excellent at rRNA/mtDNAHyper-ChIPable artifact dominanceBuild custom blacklist; recompute

Operational rule for proceeding with downstream analysis: Require (1) antibody validated, (2) fragment-size distribution sane, (3) FRiP, NSC, RSC pass ENCODE thresholds, (4) Nself/Nt rule satisfied for TFs OR naive overlap concordance for histones, (5) hyper-ChIPable artifacts identified and either filtered or flagged.

Common Errors

Error / symptomCauseSolution
Sequence chrM not found (multi-tool)chrM removed from BAM but kept in genome FASTAMatch chromosome naming convention; consistently include or exclude chrM
phantompeakqualtools hangs / OOMDefault tag chunking on deep librariesSubsample to 15-25M reads (samtools view -s) before running
plotFingerprint blank or near-diagonalInput control mislabeled as ChIPVerify sample labels; AUC ~ 0.5 = Input-like signal
IDR runs but Nself ratio always > 2One pseudoreplicate dominates due to seedUse sufficiently different seeds (-s 1.5 and -s 2.5)
ChIPQC report missing peakssamples.csv path columns wrongVerify bamReads / Peaks paths; ChIPQC fails silently on missing files
Replicate Spearman > 0.95Technical (not biological) replicatesTreat as one sample; do not report as biological replicates

References

  • Landt SG et al 2012 Genome Res 22:1813 (ENCODE/modENCODE QC guidelines, IDR Nself rule)
  • Kharchenko PV et al 2008 Nat Biotechnol 26:1351 (SPP, NSC/RSC framework)
  • Li Q et al 2011 Ann Appl Stat 5:1752 (IDR)
  • Marinov GK et al 2014 G3 4:209 (large-scale ChIP-seq QC comparison)
  • Teytelman L et al 2013 PNAS 110:18602 (hyper-ChIPable regions)
  • Amemiya HM et al 2019 Sci Rep 9:9354 (ENCODE blacklist v2)
  • Ramírez F et al 2016 Nucleic Acids Res 44:W160 (deepTools)
  • Carroll TS et al 2014 Front Genet 5:75 (ChIPQC framework)
  • Diaz A et al 2012 Stat Appl Genet Mol Biol 11:Article 9 (SES normalization / fingerprint-style QC)
  • Park PJ 2009 Nat Rev Genet 10:669 (foundational review)
  • Rothbart SB et al 2015 Mol Cell 59:502 (histone antibody specificity database)

Related Skills

  • chip-seq/peak-calling - Use QC metrics to decide whether to proceed with peak calling
  • chip-seq/cut-and-run-tag - CUT&RUN/CUT&Tag QC differs (spike-in % aligned, fragment-size signatures)
  • chip-seq/spike-in-normalization - QC for spike-in carryover and Drosophila read depth
  • chip-seq/differential-binding - Replicate concordance required before differential testing
  • atac-seq/atac-qc - Parallel QC for ATAC-seq (no input control, different thresholds)
  • alignment-files/bam-statistics - General BAM-level QC
  • alignment-files/duplicate-handling - MarkDuplicates before NRF computation

Signals

GitHub stars
409
Forks
48
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
bio-chipseq-qc-pku-yuangroup
Source
github.com/pku-yuangroup/openai4s