workflows/merip-pipeline/SKILL.md
Orchestrates an end-to-end MeRIP-seq / m6A-seq analysis from raw FASTQ to differential m6A peak calls and metagene plots, chaining fastp adapter trimming, STAR splice-aware alignment (NO deduplication for non-UMI MeRIP), deepTools replicate-concordance + IP-enrichment QC, PreSeq saturation curves, exomePeak2 (transcript-aware, GC-bias-aware negative-binomial GLM) peak calling, optional MACS3 broad-peak cross-check, DRACH motif confirmation as a sanity check (NOT a per-peak filter), exomePeak2 differential calling via the four-BAM-vector interface (bam_ip + bam_input control; bam_treated_ip + bam_treated_input treatment), ChIPseeker annotation, and the canonical Guitar metagene with stop-codon enrichment as the biological QC anchor. Use when running a complete MeRIP analysis from raw reads, when chaining the constituent epitranscriptomics skills (merip-preprocessing -> m6a-peak-calling -> m6a-differential -> modification-visualization), or when wrapping the pipeline in Snakemake / Nextflow.
npx skillsauth add GPTomics/bioSkills bio-workflows-merip-pipelineInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Reference examples tested with: STAR 2.7.11+, samtools 1.19+, fastp 0.23+, deepTools 3.5+, PreSeq 3.2+, exomePeak2 1.14.x (Bioconductor 3.18 ONLY -- deprecated in Bioc 3.19, removed in 3.20; on current Bioc install from the Bioc 3.18 archive or use a successor), MACS3 3.0+, ChIPseeker 1.38+, Guitar 2.18+, BSgenome.Hsapiens.UCSC.hg38 1.4+, TxDb.Hsapiens.UCSC.hg38.knownGene 3.18+, HOMER 4.11+.
Before using code patterns, verify installed versions match. If versions differ:
packageVersion('<pkg>') then ?function_name to verify parameters<tool> --version then <tool> --help to confirm flagsIf code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.
exomePeak2 has NO mode= or experiment_design= argument; differential is triggered by populating bam_treated_ip + bam_treated_input. MeTPeak defaults are WINDOW_WIDTH=50, SLIDING_STEP=50, FRAGMENT_LENGTH=100. MACS3 default --keep-dup is 1 and MUST be overridden to all for non-UMI MeRIP. Guitar txTxdb= is the modern argument name (older releases used txdb=).
"Analyze my MeRIP-seq data from FASTQ to differential m6A peaks" -> Orchestrate read alignment (STAR splice-aware to GENOME), IP-enrichment QC (deepTools plotFingerprint, replicate Spearman, PreSeq saturation), m6A peak calling (exomePeak2 transcript-aware default, MACS3 broad as cross-check), DRACH motif sanity check (HOMER), exomePeak2 differential via the four-BAM-vector interface, ChIPseeker feature annotation, and Guitar transcript-feature metagene confirming canonical stop-codon enrichment. Defer per-skill deep treatment to epitranscriptomics/merip-preprocessing, epitranscriptomics/m6a-peak-calling, epitranscriptomics/m6a-differential, and epitranscriptomics/modification-visualization.
This is a workflow skill: it owns the chaining decisions and hand-offs, not the internals of any one step.
MeRIP-seq inverts several DNA-pipeline reflexes; the trustworthy callset is decided at these seams.
--keep-dup 1) erases the strongest m6A peaks. Keep all reads (--keep-dup all); only dedup when a UMI is present.mode=/experiment_design= argument; differential is triggered simply by populating bam_treated_ip + bam_treated_input alongside the control bam_ip + bam_input.FASTQ -> fastp trim -> STAR genome align -> samtools sort/index -> deepTools QC + PreSeq saturation
-> exomePeak2 peak calling (+ MeTPeak / MACS3 cross-check)
-> HOMER DRACH sanity check
-> exomePeak2 differential (bam_ip + bam_treated_ip)
-> ChIPseeker feature annotation
-> Guitar metagene (stop-codon QC anchor) + pyGenomeTracks browser figures
fastp \
--in1 raw/IP_R1.fastq.gz --in2 raw/IP_R2.fastq.gz \
--out1 trimmed/IP_R1.fq.gz --out2 trimmed/IP_R2.fq.gz \
--json qc/IP_fastp.json --html qc/IP_fastp.html \
--length_required 25 --detect_adapter_for_pe --thread 8
fastp \
--in1 raw/Input_R1.fastq.gz --in2 raw/Input_R2.fastq.gz \
--out1 trimmed/Input_R1.fq.gz --out2 trimmed/Input_R2.fq.gz \
--json qc/Input_fastp.json --html qc/Input_fastp.html \
--length_required 25 --detect_adapter_for_pe --thread 8
Standard non-UMI MeRIP: do NOT pass --umi. See epitranscriptomics/merip-preprocessing for the do-NOT-dedup rationale.
STAR --runMode alignReads \
--genomeDir refs/star_index \
--readFilesIn trimmed/IP_R1.fq.gz trimmed/IP_R2.fq.gz \
--readFilesCommand zcat \
--outSAMtype BAM SortedByCoordinate \
--outFilterMultimapNmax 20 \
--outSAMattributes NH HI AS nM NM MD \
--outFileNamePrefix aligned/IP_rep1_ \
--runThreadN 12
samtools index aligned/IP_rep1_Aligned.sortedByCoord.out.bam
ln -sf IP_rep1_Aligned.sortedByCoord.out.bam aligned/IP_rep1.bam # downstream QC/peak steps consume the short ${sample}_rep${n}.bam name
ln -sf IP_rep1_Aligned.sortedByCoord.out.bam.bai aligned/IP_rep1.bam.bai
Repeat for each IP and Input replicate. Align to GENOME (not transcriptome) for downstream MeRIP peak calling. Do NOT deduplicate (no UMI in standard MeRIP).
multiBamSummary bins \
--bamfiles aligned/IP_rep[0-9].bam aligned/Input_rep[0-9].bam \
--binSize 10000 --numberOfProcessors 8 \
-o qc/cov.npz
plotCorrelation --corData qc/cov.npz --corMethod spearman --skipZeros \
--whatToPlot heatmap --colorMap RdYlBu_r --plotNumbers \
-o qc/replicate_correlation.pdf
plotFingerprint \
--bamfiles aligned/IP_rep[0-9].bam aligned/Input_rep[0-9].bam \
--skipZeros --numberOfProcessors 8 \
--JSDsample aligned/Input_rep1.bam \
--outQualityMetrics qc/fingerprint_metrics.tab \
-o qc/fingerprint.pdf
preseq lc_extrap -B -o qc/IP_rep1_lc_extrap.txt aligned/IP_rep1.bam
For peak-count comparison across conditions, rarefy BAMs to a common unique-read depth informed by the saturation curve before calling peaks.
Goal: Produce a transcript-aware set of m6A peaks with FDR and IP/input fold-change from paired IP/Input genome BAM files, suitable as input to differential analysis, motif scanning, or downstream visualisation.
Approach: Build a TxDb from the matched GTF; pass paired IP/Input BAM vectors to exomePeak2() with txdb and genome (BSgenome) for GC correction; export BED12 + RDS to save_dir/.
library(exomePeak2)
library(GenomicFeatures)
library(BSgenome.Hsapiens.UCSC.hg38)
txdb <- makeTxDbFromGFF('refs/annotation.gtf', format='gtf')
result <- exomePeak2(
bam_ip = c('aligned/IP_rep1.bam', 'aligned/IP_rep2.bam', 'aligned/IP_rep3.bam'),
bam_input = c('aligned/Input_rep1.bam', 'aligned/Input_rep2.bam', 'aligned/Input_rep3.bam'),
txdb = txdb,
bsgenome = BSgenome.Hsapiens.UCSC.hg38, # bsgenome= (a BSgenome object) for GC correction; genome= would be the UCSC string 'hg38'
paired_end = TRUE,
library_type = 'unstranded',
save_dir = 'exomePeak2_output' # no experiment_name arg; output goes straight under save_dir/
)
peaks <- result
nrow(peaks) # SummarizedExomePeak has no length method (would return 1); nrow = peak count
exomePeak2() writes fixed filenames under save_dir/: Mod.bed (BED12 peaks), Mod.csv (per-peak fold-change / FDR), Mod.rds.
macs3 callpeak \
--treatment aligned/IP_rep[0-9].bam \
--control aligned/Input_rep[0-9].bam \
--format BAMPE --gsize hs \
--nomodel --extsize 150 \
--keep-dup all \
--broad --broad-cutoff 0.1 --qvalue 0.05 \
--outdir macs3_output --name m6a_run1
--keep-dup all is non-negotiable for non-UMI MeRIP (default --keep-dup 1 destroys signal at high-coverage transcripts).
findMotifsGenome.pl \
exomePeak2_output/Mod.bed \
hg38 motif_output \
-rna -size 100 -len 5,6 -p 8
Report DRACH enrichment on the peak set as a sanity check (P-value < 1e-50 expected). NEVER post-hoc filter individual peaks by DRACH.
Goal: Identify m6A peaks that change between control and treatment conditions, with per-peak log2FC + FDR, using exomePeak2's integrated peak-calling + differential interface.
Approach: Populate bam_ip + bam_input with the control arm and bam_treated_ip + bam_treated_input with the treatment arm; populating the treated arms triggers differential mode (there is NO mode= argument). Apply effect-size + FDR filters downstream.
library(exomePeak2)
library(GenomicFeatures)
library(BSgenome.Hsapiens.UCSC.hg38)
txdb <- makeTxDbFromGFF('refs/annotation.gtf', format='gtf')
ctrl_ip <- c('aligned/ctrl_IP1.bam', 'aligned/ctrl_IP2.bam', 'aligned/ctrl_IP3.bam')
ctrl_input <- c('aligned/ctrl_Input1.bam', 'aligned/ctrl_Input2.bam', 'aligned/ctrl_Input3.bam')
treat_ip <- c('aligned/treat_IP1.bam', 'aligned/treat_IP2.bam', 'aligned/treat_IP3.bam')
treat_input <- c('aligned/treat_Input1.bam', 'aligned/treat_Input2.bam', 'aligned/treat_Input3.bam')
diff_result <- exomePeak2(
bam_ip = ctrl_ip,
bam_input = ctrl_input,
bam_treated_ip = treat_ip,
bam_treated_input = treat_input,
txdb = txdb,
bsgenome = BSgenome.Hsapiens.UCSC.hg38, # bsgenome=, not genome=
paired_end = TRUE,
library_type = 'unstranded',
peak_calling_mode = 'exon',
save_dir = 'exomePeak2_diff_output' # writes DiffMod.bed / DiffMod.csv; no experiment_name arg
)
diff_table <- Results(diff_result) # SummarizedExomePeak has no as.data.frame method; Results() returns the data.frame
# differential effect-size column is DiffModLog2FC (not log2FC)
sig <- diff_table[diff_table$padj < 0.05 & abs(diff_table$DiffModLog2FC) > 0.5, ]
nrow(sig)
exomePeak2 has NO mode= or experiment_design= argument. Populating bam_treated_ip + bam_treated_input triggers differential output. For batch / antibody-lot covariate adjustment, fall through to featureCounts-on-peaks -> DESeq2 (see epitranscriptomics/m6a-differential).
library(ChIPseeker)
library(TxDb.Hsapiens.UCSC.hg38.knownGene)
library(rtracklayer)
peaks <- import('exomePeak2_output/Mod.bed')
anno <- annotatePeak(peaks, TxDb=TxDb.Hsapiens.UCSC.hg38.knownGene, level='transcript')
plotAnnoBar(anno)
plotDistToTSS(anno)
Flag peaks within ~50 nt of TSS as m6A-or-m6Am ambiguous (antibody cross-reactivity with PCIF1-deposited cap m6Am).
library(Guitar)
library(TxDb.Hsapiens.UCSC.hg38.knownGene)
GuitarPlot(
txTxdb = TxDb.Hsapiens.UCSC.hg38.knownGene,
stBedFiles = list('exomePeak2_output/Mod.bed'),
miscOutFilePrefix = 'figures/m6a_metagene'
)
Expected pattern: peak density rises toward and peaks near the stop codon (3'UTR-proximal end of CDS). If absent, suspect IP failure or wrong antibody; do NOT proceed to downstream interpretation.
#!/usr/bin/env bash
set -euo pipefail
STAR_INDEX=$1
GTF=$2
IP_R1=$3
IP_R2=$4
INPUT_R1=$5
INPUT_R2=$6
OUTPUT_DIR=$7
mkdir -p "${OUTPUT_DIR}"/{qc,trimmed,aligned,peaks,figures}
fastp --in1 "${IP_R1}" --in2 "${IP_R2}" \
--out1 "${OUTPUT_DIR}/trimmed/IP_R1.fq.gz" --out2 "${OUTPUT_DIR}/trimmed/IP_R2.fq.gz" \
--json "${OUTPUT_DIR}/qc/IP_fastp.json" --length_required 25 --detect_adapter_for_pe --thread 8
fastp --in1 "${INPUT_R1}" --in2 "${INPUT_R2}" \
--out1 "${OUTPUT_DIR}/trimmed/Input_R1.fq.gz" --out2 "${OUTPUT_DIR}/trimmed/Input_R2.fq.gz" \
--json "${OUTPUT_DIR}/qc/Input_fastp.json" --length_required 25 --detect_adapter_for_pe --thread 8
for sample in IP Input; do
STAR --runMode alignReads --genomeDir "${STAR_INDEX}" \
--readFilesIn "${OUTPUT_DIR}/trimmed/${sample}_R1.fq.gz" "${OUTPUT_DIR}/trimmed/${sample}_R2.fq.gz" \
--readFilesCommand zcat --outSAMtype BAM SortedByCoordinate \
--outFilterMultimapNmax 20 \
--outFileNamePrefix "${OUTPUT_DIR}/aligned/${sample}_" --runThreadN 12
samtools index "${OUTPUT_DIR}/aligned/${sample}_Aligned.sortedByCoord.out.bam"
done
macs3 callpeak \
--treatment "${OUTPUT_DIR}/aligned/IP_Aligned.sortedByCoord.out.bam" \
--control "${OUTPUT_DIR}/aligned/Input_Aligned.sortedByCoord.out.bam" \
--format BAMPE --gsize hs --nomodel --extsize 150 --keep-dup all \
--broad --broad-cutoff 0.1 --qvalue 0.05 \
--outdir "${OUTPUT_DIR}/peaks" --name m6a
The full pipeline (incl. exomePeak2 peak calling, DRACH check, ChIPseeker annotation, Guitar metagene) is best orchestrated in Snakemake or Nextflow with the per-skill recipes from the four epitranscriptomics/ skills.
| Checkpoint | Expected | Action if Failed | |------------|----------|------------------| | Properly-paired rate (samtools flagstat) | >=85% | Check trimming and adapter contamination | | Replicate Spearman within condition (10 kb bins) | >=0.85 IP-IP | Inspect divergent replicate; consider exclusion | | plotFingerprint IP-vs-input JS distance | >=0.5 | Suspect failed IP if lower | | Saturation plateau depth | ~30-60M unique reads | Sequence deeper if not plateaued | | DRACH motif enrichment (HOMER, peak set) | P-value < 1e-50 | Suspect IP failure or wrong antibody | | Stop-codon enrichment in Guitar metagene | Clear 3'UTR-proximal peak | Suspect IP failure, wrong antibody, or non-m6A modification | | 5'UTR peaks fraction | Note ambiguity zone (~50 nt of TSS) | Flag as m6A-or-m6Am ambiguous; PCIF1 cross-reactivity |
| File | Description |
|------|-------------|
| exomePeak2_output/Mod.bed | exomePeak2 peak BED12 |
| exomePeak2_diff_output/DiffMod.bed | Differential peaks with log2FC + FDR |
| motif_output/ | HOMER DRACH motif enrichment report |
| figures/m6a_metagene.pdf | Guitar transcript-feature metagene (stop-codon QC anchor) |
| qc/replicate_correlation.pdf | deepTools Spearman heatmap |
| qc/fingerprint.pdf | deepTools Lorenz IP-enrichment plot |
| qc/IP_rep*_lc_extrap.txt | PreSeq saturation curves |
| Symptom | Cause | Fix |
|---------|-------|-----|
| Strongest m6A peaks (high-expression transcripts) vanish | Deduplicated non-UMI MeRIP, or MACS3 default --keep-dup 1 | Keep all reads (--keep-dup all); never dedup non-UMI MeRIP |
| exomePeak2 runs but gives no differential output | Expected a mode=/experiment_design= argument | Populate bam_treated_ip + bam_treated_input to trigger differential |
| Real non-canonical m6A sites lost | Filtered individual peaks by DRACH presence | DRACH is a peak-SET sanity check (E<1e-50), never a per-peak filter |
| Peak counts "differ" between conditions but it's depth | Compared raw peak numbers at unequal depth | Rarefy BAMs to a common unique-read depth before cross-condition counts |
| No stop-codon enrichment in the metagene | IP failure, wrong antibody, or non-m6A signal | STOP; do not interpret downstream (Guitar go/no-go) |
| 5'UTR peaks over-interpreted as m6A | Antibody cross-reacts with cap-adjacent m6Am (PCIF1) | Flag peaks within ~50 nt of TSS as m6A-or-m6Am ambiguous |
tools
End-to-end CLIP-seq pipeline from FASTQ to ENCODE-compliant binding sites, single-nucleotide crosslink maps, annotation, motifs, and (optionally) differential binding. Use when running the full Yeo lab eCLIP / iCLIP / iCLIP2 / iCLIP3 / irCLIP / PAR-CLIP analysis with SMInput control, protocol-specific UMI extraction, ENCODE STAR parameters, CLIPper or Skipper peak calling with stringent log2 FC and -log10 p thresholds, IDR rescue and self-consistency QC, and downstream motif registration with mCross or PEKA.
development
Detect, date, and contextualize whole-genome duplication (WGD / paleopolyploidy) events using wgd v2 (Chen et al 2024), KsRates (Sensalari 2022 substitution-rate-corrected Ks dating), DupGen_finder (Qiao 2019), MAPS (Li 2018 phylogenomic), POInT (Conant 2008 ordered-block), SLEDGe (2024 ML-based), Whale.jl (Bayesian DL+WGD), and synteny-anchored paranome construction. Use when identifying ancient polyploidy from Ks distributions and synteny block analysis, positioning WGD events relative to speciation, distinguishing tandem from segmental from WGD duplications, dating the 2R/3R vertebrate / fish / salmonid WGDs, building paranome and Ks-age mixture models, applying KsRates substitution-rate correction across lineages, or testing alternative biased-fractionation / dosage-balance models post-WGD.
tools
Build whole-genome alignments using Progressive Cactus (Armstrong 2020 reference-free clade-level WGA), Minigraph-Cactus (Hickey 2024 pangenome-aware), LASTZ chain/net (UCSC pipeline), MUMmer4 (Marçais 2018 pairwise), minimap2 -x asm5/10/20 (Li 2018 fast pairwise), AnchorWave (Song 2022 WGD-aware), and Mauve / progressiveMauve (bacterial). Operates the HAL toolkit (Hickey 2013) for downstream extraction including halSynteny, halLiftover, halBranchMutations, and hal2maf. Use when constructing multi-species alignments for comparative-annotation projection (TOGA), synteny detection, conservation analyses (phyloP / PhastCons), or pangenome graph construction; selecting between reference-free (Cactus) and reference-anchored (LASTZ chains/nets) approaches; tuning sensitivity for closely vs distantly related genomes; or producing HAL files for genome-wide downstream tools.
development
Detect syntenic blocks and structural rearrangements between genomes using MCScanX (Wang 2012), JCVI/MCScan (Tang 2008 Python), GENESPACE (Lovell 2022) for orthology-anchored riparian visualization, SyRI for structural variation, AnchorWave for sequence-level synteny, i-ADHoRe 3.0 for highly diverged species, SynNet for synteny networks, and ntSynt for multi-genome macrosynteny. Use when identifying collinear gene blocks across species, distinguishing macrosynteny from microsynteny, detecting inversions/translocations/duplications, anchoring orthology in WGD lineages, producing publication riparian plots, computing synteny block age via Ks (cross-references whole-genome-duplication), or running synteny-aware ortholog inference in polyploids.