alternative-splicing/sashimi-plots/SKILL.md
Creates sashimi-style plots showing RNA-seq read coverage and splice junction counts using ggsashimi (general-purpose, condition-grouped overlays), rmats2sashimiplot (rMATS-output-aware), MAJIQ-VOILA (LSV posteriors interactive HTML), leafviz (leafcutter clusters Shiny), Jutils (tool-agnostic heatmaps and sashimi for rMATS/leafcutter/MntJULiP/MAJIQ output), or pyGenomeTracks (multi-track publication figures). Tool choice depends on the upstream differential-splicing tool's output format and the publication vs interactive use case. Use when visualizing specific splicing events, validating differential splicing calls, or producing publication-quality figures.
npx skillsauth add GPTomics/bioSkills bio-sashimi-plotsInstall 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: ggsashimi 1.1+, rmats2sashimiplot 3.0+, MAJIQ 3.0+, leafcutter 0.2.9+, pyGenomeTracks 3.8+, ggplot2 3.5+, pandas 2.2+
Before using code patterns, verify installed versions match. If versions differ:
pip show <package> then help(module.function) to check signatures<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.
Visualize RNA-seq coverage tracks with splice junction arcs labeled by read count. Sashimi plots originated with MISO (Katz 2010 Nat Methods); modern tools differ in input handling, group aggregation logic, and customization. Tool choice is not interchangeable — some tools work only with specific upstream output formats.
| Tool | Best for | Input | Strengths | Fails when |
|------|----------|-------|-----------|------------|
| ggsashimi | Publication-quality grouped overlays from any BAM | BAMs + region | --overlay aggregates samples within a group; clean PDFs | No native rMATS/MAJIQ integration; need to extract coords manually |
| rmats2sashimiplot | One-line plot from rMATS output | rMATS event file + BAMs | No manual coord extraction | rMATS-specific; doesn't handle leafcutter or MAJIQ |
| MAJIQ-VOILA | Interactive LSV browsing with posterior PSI distributions | MAJIQ build + psi/deltapsi | Splice-graph topology; LSV-aware; posterior violins | Static figures; non-academic license |
| leafviz | Cluster-level interactive browsing with NMD annotation | leafcutter differential output | Filter table + sashimi-like plots; NMD-aware | leafcutter-specific |
| Jutils | Unified output across rMATS, leafcutter, MntJULiP, MAJIQ | Tool-specific differential output | Heatmaps, Venn, sashimi tool-agnostically | Output less polished than ggsashimi |
| pyGenomeTracks | Multi-track publication figures (RNA-seq + ChIP/ATAC) | BigWig + BED + GTF | Combine RNA with chromatin tracks | Not splicing-specific; configure tracks manually |
| IGV (interactive) | Quick ad-hoc inspection | BAM + region | Scrollable, instant | Not for publication figures |
| MISO sashimi | Historical | MISO output | Original sashimi format | MISO unmaintained; no longer recommended |
| Goal | Recommended tool |
|------|-------------------|
| Validate a specific rMATS hit | rmats2sashimiplot (one-line) or ggsashimi (custom) |
| Validate a leafcutter cluster | leafviz (interactive) or ggsashimi with cluster coordinates |
| Validate a MAJIQ LSV (complex topology) | MAJIQ-VOILA (only tool that shows full LSV graph) |
| Publication-quality two-condition comparison | ggsashimi -O 3 -A mean_j for grouped overlay |
| Multi-track figure (RNA-seq + H3K4me3 + ATAC) | pyGenomeTracks |
| Quick ad-hoc browsing during development | IGV sashimi |
| Tool-agnostic batch heatmap of significant events | Jutils |
| Interactive cohort-level filtering of leafcutter results | leafviz Shiny |
Goal: Generate publication-quality sashimi plot for a region with samples grouped by condition and per-sample tracks aggregated.
Approach: Define samples + groups + colors in a TSV (no header), then call ggsashimi with coordinates, GTF, and visual flags.
import subprocess
import pandas as pd
# ggsashimi input: col1 = sample id, col2 = BAM path, col3 = group (for -O/-C overlay/color)
groups = pd.DataFrame({
'sample_id': ['ctrl1', 'ctrl2', 'ctrl3', 'trt1', 'trt2', 'trt3'],
'bam': ['ctrl1.bam', 'ctrl2.bam', 'ctrl3.bam', 'trt1.bam', 'trt2.bam', 'trt3.bam'],
'group': ['Control', 'Control', 'Control', 'Treatment', 'Treatment', 'Treatment']
})
groups.to_csv('sashimi_groups.tsv', sep='\t', index=False, header=False)
subprocess.run([
'ggsashimi.py',
'-b', 'sashimi_groups.tsv',
'-c', 'chr17:43094000-43125000',
'-o', 'BRCA1_sashimi',
'-M', '10',
'--alpha', '0.25',
'--height', '3',
'--width', '10',
'--shrink',
'--fix-y-scale',
'--ann-height', '4',
'-g', 'gencode_v45.gtf',
'--base-size', '14',
'-O', '3',
'-A', 'mean_j',
'-F', 'pdf'
], check=True)
Key ggsashimi flags (Garrido-Martin 2018 PLoS Comput Biol):
--overlay 3 (or -O 3): aggregate multiple samples within a group into a single overlay track with summary statistics — its signature feature-A mean_j: junction aggregation method (mean, median, mean_j accounts for sample-wise normalization); use mean_j for biological replicates--shrink: rescale long introns (>2x flanking exons) for compact display--fix-y-scale: identical y-axis across groups (essential for visual comparison)--alpha 0.25: transparency for per-sample coverage in overlay mode-M 10: minimum junction reads to display (lower = noisier; 5-10 typical; raise to 20+ for crowded plots)--ann-height: gene annotation track height-F pdf: output format (pdf, png, svg, eps)Goal: Auto-generate sashimi plots for all significant rMATS differential events.
Approach: Parse SE.MATS.JC.txt, expand coordinates to flanking exons + 500nt context, iterate ggsashimi.
import subprocess
import pandas as pd
from pathlib import Path
diff = pd.read_csv('rmats_output/SE.MATS.JC.txt', sep='\t')
sig = diff[(diff['FDR'] < 0.05) & (diff['IncLevelDifference'].abs() > 0.10)]
Path('sashimi_plots').mkdir(exist_ok=True)
for idx, ev in sig.head(25).iterrows():
region = f'{ev["chr"]}:{ev["upstreamES"] - 500}-{ev["downstreamEE"] + 500}'
safe_name = f'{ev["geneSymbol"]}_{ev["chr"]}_{ev["upstreamES"]}'
subprocess.run([
'ggsashimi.py',
'-b', 'sashimi_groups.tsv',
'-c', region,
'-o', f'sashimi_plots/{safe_name}',
'-M', '5',
'--shrink',
'--fix-y-scale',
'-O', '3',
'-A', 'mean_j',
'-g', 'annotation.gtf',
'-F', 'pdf'
], check=True)
For MXE events, plot from upstreamES of exon 1 to downstreamEE of exon 2 to show both alternative exons in the same figure.
Goal: Plot directly from rMATS event coordinates without manual region calculation.
Approach: Pass rMATS event file + BAM lists + event type; rmats2sashimiplot extracts coordinates and produces per-event PDFs.
rmats2sashimiplot \
--b1 ctrl1.bam,ctrl2.bam,ctrl3.bam \
--b2 trt1.bam,trt2.bam,trt3.bam \
-t SE \
-e rmats_output/SE.MATS.JC.txt \
--l1 Control \
--l2 Treatment \
-o sashimi_rmats \
--exon_s 1 \
--intron_s 5 \
--color '#1f77b4,#ff7f0e' \
--group-info group_def.txt
--exon_s 1 --intron_s 5 shrinks intron-to-exon visual ratio 5:1 (introns drawn 1/5 their actual length). The --group-info flag (newer versions) allows custom replicate groupings.
Goal: Browse LSV posterior PSI distributions interactively with splice-graph topology.
Approach: Run voila on MAJIQ output to generate self-contained HTML.
# MAJIQ V3 (June 2025+) uses Zarr-format splicegraph (V2's .sql is deprecated)
voila view -p 5000 -j 8 build/splicegraph.zarr psi_output/sample.psi.voila -o voila_psi_html
voila view -p 5000 -j 8 build/splicegraph.zarr deltapsi_output/group1_group2.deltapsi.voila -o voila_dpsi_html
VOILA shows:
The only tool that visualizes complex multi-junction LSVs intuitively. For events that don't fit canonical SE/A5SS/A3SS, VOILA is the visualization of choice.
Goal: Browse leafcutter clusters with intron-level effects, sashimi-like plots, and NMD annotation.
Approach: Prepare leafviz input from leafcutter differential output, then launch Shiny.
prepare_results.R \
-o leafviz \
-m groups.txt \
leafcutter_perind_numers.counts.gz \
ds_results_cluster_significance.txt \
ds_results_effect_sizes.txt \
annotation_codes
library(leafviz)
run_leafviz('leafviz.RData')
Standalone alternative: jackhump/leafviz GitHub repo for the lightweight installable subset. Useful for cohort-level interactive filtering.
Goal: Visualize differential splicing output uniformly across rMATS, leafcutter, MntJULiP, and MAJIQ.
Approach: Convert tool output to Jutils' standard format, then plot.
python3 jutils.py convert-results --rmats-dir rmats_output/ --out-dir jutils_out/
python3 jutils.py heatmap --tsv-file jutils_out/rmats.tsv --meta-file meta.tsv --q-value 0.05
python3 jutils.py sashimi --tsv-file jutils_out/rmats.tsv --meta-file meta.tsv \
--gtf annotation.gtf --coordinate chr1:1000-2000 --bam-list bam_list.tsv
python3 jutils.py venn-diagram --tsv-file-list jutils_out/rmats.tsv,jutils_out/leafcutter.tsv
(Yang 2021 Bioinformatics) Useful when comparing multiple tools' outputs across publications or doing meta-analysis.
Goal: Combine splicing with chromatin or coverage tracks for publication figures.
Approach: Define tracks in an INI file (genes, BAM, BigWig, BED), then run pyGenomeTracks --tracks tracks.ini --region ... -o figure.pdf.
[gene_models]
file = annotation.gtf
height = 3
title = GENCODE v45
fontsize = 10
file_type = gtf
[ctrl_coverage]
file = ctrl_merged.bw
title = Control
color = #1f77b4
height = 3
file_type = bigwig
[trt_coverage]
file = trt_merged.bw
title = Treatment
color = #ff7f0e
height = 3
file_type = bigwig
[junctions]
file = junctions.bedpe
title = Junctions
height = 2
file_type = links
links_type = arcs
The junctions.bedpe file must be in BEDPE format (6 columns: chr1 start1 end1 chr2 start2 end2 [+ optional score]). Convert from regtools .bed12 junctions:
# Convert regtools junctions BED12 to BEDPE for pyGenomeTracks.
# regtools BED12 column 11 is blockSizes (anchor_left, anchor_right);
# column 12 is blockStarts (0, intron_length + anchor_left).
# Intron start = chromStart + anchor_left = $2 + a[1]
# Intron end = chromStart + blockStarts[2] = $2 + b[2]
awk 'BEGIN{OFS="\t"} {split($11,a,","); split($12,b,","); s=$2+a[1]; e=$2+b[2]; print $1, s, s+1, $1, e-1, e, $5}' \
regtools_junctions.bed > junctions.bedpe
pyGenomeTracks --tracks tracks.ini --region chr17:43094000-43125000 -o figure.pdf
| Visual element | What it represents |
|----------------|--------------------|
| Filled coverage track | Read coverage at each genomic position (depth-normalized in -A mode) |
| Arc / curve between exons | Junction-spanning reads; arc connects donor to acceptor |
| Number on arc | Count of junction-spanning reads (raw, not normalized, unless -A set) |
| Arc thickness | Often proportional to read count (tool-dependent) |
| Gene model below | Exons (boxes) and introns (lines) from GTF |
| Multiple parallel tracks | Per-sample (default) or per-group (with -O) |
Junction count interpretation: the number on an arc is the absolute count of reads whose CIGAR string contained an N operation matching that intron coordinate. Higher = more usage. Compare counts on inclusion vs skipping arcs to estimate PSI visually.
Color convention: by convention, control = blue (#1f77b4), treatment = orange (#ff7f0e); always document. Use ColorBrewer or matplotlib defaults for >2 groups.
Trigger: Stranded RNA-seq library plotted without strand specification.
Mechanism: ggsashimi reads BAM strand from CIGAR + flag; without strand info, antisense junctions appear as artifacts.
Symptom: Implausible junctions in regions with overlapping antisense genes; "noise" arcs at unexpected locations.
Fix: Set library strandedness with -s MATE2_SENSE (dUTP/TruSeq reverse-stranded PE; use -s MATE1_SENSE for forward, -s SENSE/ANTISENSE for single-end); verify orientation with RSeQC infer_experiment.py. Alternatively, pre-filter BAM by strand with samtools view -f 16 / -F 16.
Trigger: Older versions or non-default rMATS output.
Mechanism: rmats2sashimiplot expects 1-based coordinates from rMATS' .MATS.JC.txt; rMATS outputs 0-based half-open in some columns.
Symptom: Plot region shifted by 1 nt; arcs misaligned with gene model.
Fix: Verify rmats2sashimiplot version matches rMATS-turbo output convention; use ggsashimi for cleaner control.
Trigger: Loading large VOILA HTML in browser (cohort with hundreds of LSVs).
Mechanism: VOILA HTML embeds all LSV data; large cohorts produce >100 MB HTMLs.
Symptom: Browser unresponsive on opening; "page unresponsive" warnings.
Fix: Filter LSVs in MAJIQ before voila step (--changing-pvalue-threshold 0.95 and --changing-between-group-dpsi-threshold 0.2); split into per-gene HTMLs.
Trigger: Using leafviz with annotation_codes from different GENCODE version than leafcutter clusters.
Mechanism: annotation_codes encodes intron-to-event-class mapping per GTF version.
Symptom: Many clusters show as "unannotated" despite being in canonical GTF.
Fix: Generate annotation_codes from the same GENCODE version used in differential analysis.
| Visual goal | ggsashimi flag |
|-------------|-----------------|
| Reduce intron whitespace | --shrink |
| Identical y-axis across groups | --fix-y-scale |
| Per-group overlay aggregation | -O 3 -A mean_j |
| Larger figure | --width 12 --height 4 |
| Bigger fonts | --base-size 16 |
| Vector output | -F pdf or -F svg |
| Custom palette | Edit colors in groups TSV |
| Filter junction noise | -M 10 (raise to 20+) |
| Transparency | --alpha 0.25 |
| Restrict to protein-coding | pre-filter the GTF (awk '$0 ~ /protein_coding/'); ggsashimi has no feature-filter flag |
| Tip | Rationale |
|-----|-----------|
| Use --shrink for genes with large introns | Keeps exons visible (TTN, brain genes with multi-kb introns) |
| --fix-y-scale for cross-group comparisons | Otherwise auto-rescaling visually exaggerates differences |
| Aggregate replicates with -O 3 -A mean_j | Reduces clutter; per-sample variance still shown via alpha |
| Limit to 3-4 groups per figure | More becomes hard to read |
| Include 200-500 nt flanking exons | Show full splicing context |
| For MXE events, plot both alternative exons | Otherwise only half of the event is visible |
| Check accessibility colors | Use ColorBrewer-safe palettes for color-blind readers |
| Always include a legend | Sashimi figures without legends are uninformative for non-experts |
| Specify output format explicitly | PDF for publication; PNG for slides; SVG for editing |
| Error | Cause | Solution |
|-------|-------|----------|
| ggsashimi: 'samtools' not found | samtools not in PATH | Install via conda; which samtools to verify |
| ggsashimi: empty plot | Region has no reads or wrong chromosome name | Check BAM with samtools view sample.bam chr1:100-200; chrom name match (chr1 vs 1) |
| rmats2sashimiplot: KeyError 'IJC_SAMPLE_1' | Old rmats2sashimiplot with new rMATS output | Update both to matching versions |
| voila: out of memory | Large LSV cohort | Filter by deltapsi threshold before voila |
| pyGenomeTracks: ini parse error | Missing closing bracket or invalid track type | Validate INI syntax; check pyGenomeTracks --listTracks for supported types |
| leafviz: missing exon file | annotation_codes path wrong | Re-run prepare_results.R with correct paths |
| Issue | Cause | Solution |
|-------|-------|----------|
| No junctions shown | Default -M 10 too strict | Lower to -M 3 or -M 5 |
| Plot too crowded | Many samples without aggregation | Use -O 3 to overlay groups |
| Annotation missing or wrong gene | GTF lacks gene_name attribute or wrong build | Verify GTF version vs BAM reference; pre-filter the GTF to the relevant features |
| Memory issues on large regions | >100 kb regions with many samples | Plot smaller windows or pre-extract reads with samtools view |
| Y-axis dominated by one peak | Outlier sample | Use -A mean_j to aggregate; or filter outlier |
development
Installs 425 bioinformatics skills covering sequence analysis, RNA-seq, single-cell, variant calling, metagenomics, structural biology, and 56 more categories. Use when setting up bioinformatics capabilities or when a bioinformatics task requires specialized skills not yet installed.
testing
Chains a somatic (tumor-normal) SNV/indel and structural-variant pipeline end to end with GATK Mutect2 (or Strelka2), wiring the somatic-specific machinery - panel-of-normals and gnomAD germline-resource priors, GetPileupSummaries/CalculateContamination, and LearnReadOrientationModel FFPE/oxoG orientation-bias filtering fed into FilterMutectCalls. Use when calling somatic mutations from a tumor-normal pair (or tumor-only with PoN caveats), deciding which artifact filter removes which class of false positive, reasoning about VAF/purity/ploidy and clonal-vs-subclonal detection, adding somatic SV/CNV or TMB/MSI/signatures, or routing variants to AMP/ASCO/CAP tier and oncogenicity interpretation (never germline ACMG).
development
End-to-end pooled and single-cell CRISPR screen analysis from FASTQ to hit genes. Orchestrates library design QC, guide counting, six-stage screen QC (plasmid Gini, replicate Pearson, CEGv2 PR-AUC, copy-number artifact), method-appropriate hit calling across MAGeCK RRA/MLE, BAGEL2, drugZ, JACKS, and Chronos, cancer-cell-line copy-number correction (CRISPRcleanR / Chronos), batch correction for multi-batch screens, and the specialized branches for combinatorial paralog screens, single-cell Perturb-seq, base-editor variant-function screens, prime-editor screens, and in vivo bottleneck-aware screens. Use when analyzing any pooled CRISPR screen end-to-end, matching the hit-calling method to the experimental design, integrating copy-number correction into the pipeline, or branching the workflow for single-cell, combinatorial, base-editor, prime-editor, or in vivo variants.
development
Transcribe DNA to RNA and translate to protein using Biopython, with NCBI codon-table selection, CDS validation, and six-frame ORF finding. Use when converting a CDS or ORF to its amino-acid sequence, selecting a non-standard (mitochondrial, bacterial, ciliate) genetic code, validating a coding sequence, or scanning all reading frames.