| Title: | Sashimi-Style RNA-seq Coverage and Junction Visualisation |
|---|---|
| Description: | Provides tools to visualise RNA sequencing alignments as sashimi-style plots showing fragment coverage and splice junction usage across genomic regions. Alignments from BAM files are summarised into coverage tracks and junction arcs, which can be displayed alongside transcript annotations. Plots can use compressed genomic coordinates to emphasise observed or annotated features and support visual inspection of local splicing variation across samples. |
| Authors: | Lachlan Baer [aut, cre] (ORCID: <https://orcid.org/0000-0001-5213-3401>) |
| Maintainer: | Lachlan Baer <[email protected]> |
| License: | GPL-3 |
| Version: | 0.99.0 |
| Built: | 2026-11-05 11:27:48 UTC |
| Source: | https://github.com/BiocStaging/spliceTerrain |
spliceTerrain() draws sashimi-style plots for one or more BAM files
over a genomic region. Plots combine per-base fragment coverage, splice
junction arcs, optional transcript annotation, and highlighted regions.
Intronic or otherwise uninformative gaps can be compacted so the plotting
area is focused on observed or annotated features.
spliceTerrain( bam, region, annotation = NULL, junction_usage = NULL, junction_usage_label_sep = "\n", highlight = NULL, strandedness = "unstranded", min_mapq = 0, min_coverage = 0, min_junction_reads = 10, lib_size = NULL, norm_factors = NULL, normalise_to = NULL, compress_introns = TRUE, intron_width = 50, min_arrow = intron_width + 1, common_y = FALSE, arc_height = 1, arc_side = c("both", "above", "below"), arc_scale = FALSE, colours = "black", highlight_colour = scales::alpha("red", 0.2), anno_fill_by = NULL, anno_fill_colours = NULL, anno_label_by = NULL, anno_label_colour = "white", anno_label_size = 3, junc_text_size = 3, panel_heights = 1, axis_title_size = 12, axis_text_size = 9, return_ctx = FALSE, ctx = NULL, annotated_junctions = FALSE )spliceTerrain( bam, region, annotation = NULL, junction_usage = NULL, junction_usage_label_sep = "\n", highlight = NULL, strandedness = "unstranded", min_mapq = 0, min_coverage = 0, min_junction_reads = 10, lib_size = NULL, norm_factors = NULL, normalise_to = NULL, compress_introns = TRUE, intron_width = 50, min_arrow = intron_width + 1, common_y = FALSE, arc_height = 1, arc_side = c("both", "above", "below"), arc_scale = FALSE, colours = "black", highlight_colour = scales::alpha("red", 0.2), anno_fill_by = NULL, anno_fill_colours = NULL, anno_label_by = NULL, anno_label_colour = "white", anno_label_size = 3, junc_text_size = 3, panel_heights = 1, axis_title_size = 12, axis_text_size = 9, return_ctx = FALSE, ctx = NULL, annotated_junctions = FALSE )
bam |
Character vector of BAM file paths. If unnamed, sample labels are
derived from BAM basenames with the |
region |
Genomic interval to plot. May be a
GRanges, a GRangesList, or a
character string coercible to |
annotation |
Optional annotation track. Must be a GRangesList, with each list element representing one feature group such as a transcript model. Each group is drawn on its own annotation row. List element names are used as y-axis labels; if absent, default group labels are generated. Supplied names must be non-empty and unique. Annotation groups are retained in full when they overlap the plotting region and are clipped to the plotting window when drawn. All ranges in a retained group must be on the plotting seqname and share one strand. |
junction_usage |
Optional genomic interval(s) selecting junctions for
local usage percentages. Accepts the same formats as |
junction_usage_label_sep |
Character scalar inserted between junction
counts and percentages when |
highlight |
Optional interval(s) to highlight. Accepts the same formats
as |
strandedness |
Library strandedness for each BAM. Must be one of
|
min_mapq |
Integer scalar. Minimum mapping quality (MAPQ) for alignments to be imported from the BAM file. |
min_coverage |
Integer or percentage string. Minimum per-base fragment
coverage required for positions to be retained for plotting. Percentage
strings such as |
min_junction_reads |
Integer or percentage string. Minimum number of
fragments supporting a junction for it to be retained for plotting. Both
mates supporting the same junction contribute one count.
Percentage strings such as |
lib_size |
Optional numeric vector giving full-library sizes in fragment units, one per BAM file, before restriction to the plotting region. A pair or mapped singleton is one fragment; for single-end libraries, each mapped read is one fragment. When supplied, coverage and junction counts are normalised by effective library size before plotting. |
norm_factors |
Optional numeric vector of normalisation factors, one per
BAM file, such as edgeR TMM normalisation factors. Requires
|
normalise_to |
Optional numeric scalar giving the target library size
used for normalisation. If |
compress_introns |
Logical scalar. If |
intron_width |
Integer scalar. Approximate plot-space width used for
compacted gaps when |
min_arrow |
Integer scalar. Minimum annotation intron width required before drawing directional arrows. |
common_y |
Logical scalar. If |
arc_height |
Numeric scalar multiplying the default junction arc height.
|
arc_side |
Character scalar controlling where junction arcs are drawn.
Must be one of |
arc_scale |
Logical scalar. If |
colours |
Character vector of colours used for each sample's coverage
bars and junction arcs. Must be either length 1, in which case the same
colour is used for all BAMs, or the same length as |
highlight_colour |
Fill and border colour used for highlighted regions.
The default is a semi-transparent red produced with
|
anno_fill_by |
Optional character scalar naming a metadata column in
|
anno_fill_colours |
Optional vector of colours used when
|
anno_label_by |
Optional character scalar naming a metadata column in
|
anno_label_colour |
Character scalar giving the colour used for annotation labels. |
anno_label_size |
Numeric scalar giving the text size used for annotation labels. |
junc_text_size |
Numeric scalar giving the size of junction count
labels. Passed to |
panel_heights |
Numeric vector controlling relative heights of the plot panels. Must be length 1 or the number of BAM sample panels plus one additional value if an annotation panel is shown. When an annotation panel is shown, its height is specified by the final value. |
axis_title_size |
Numeric scalar giving the axis title text size used in the final plot theme. |
axis_text_size |
Numeric scalar giving the axis tick-label text size used in the final plot theme. |
return_ctx |
Logical scalar. If |
ctx |
Optional context list previously returned by
|
annotated_junctions |
Logical scalar. If |
The plot is built in three conceptual steps:
Alignments overlapping region are imported from each BAM file.
Unmapped, secondary, and supplementary alignments are ignored, and
min_mapq is applied during import.
Fragment coverage and splice junction support are summarised from
the imported alignments and filtered by min_coverage and
min_junction_reads.
If compress_introns = TRUE, a plot-space map is constructed to
compact gaps between observed or annotated genomic blocks. Coverage,
junctions, annotation, and optional overlays are then mapped into this
compacted coordinate system.
For BAMs detected as paired-end, alignments flagged as paired are imported as groups containing complete pairs or mapped singletons. A mapped read does not require a mapped mate to contribute to the plot. Each imported group is treated as one fragment. For single-end input, each read is one fragment. Coverage uses the union of each fragment's aligned blocks. Overlapping mates contribute at most one count per position. Introns and unsequenced gaps between mates are not filled. Each fragment contributes at most one count per distinct junction, even when both mates cross it; a fragment can support multiple different junctions. Independent fragments are counted separately, including those with identical coordinates. This is not PCR/UMI deduplication. Retaining singletons avoids losing their signal when mate-mapping success differs between samples.
region, junction_usage, and highlight may be supplied as
genomic ranges or as strings coercible to GRanges. If multiple
ranges are supplied for region, they must all be on the same seqname;
their span is used as the BAM query and plotting window. Optional genomic
overlays are retained when they overlap the plotting region and are clipped
to the plotting window when drawn.
junction_usage and highlight are optional selections:
junction_usage selects junctions by their intronic anchors.
Percentages use raw fragment support after import/MAPQ/strand filtering,
before min_junction_reads filtering and plotting-window exclusion.
Hidden junctions remain in the denominator, so visible percentages need not
sum to 100. A junction is counted once in the denominator even when both
anchors or multiple selection intervals match it. Different junctions from
one fragment each contribute their support; these are junction fractions,
not fractions of unique molecules across the whole selection.
highlight marks one or more genomic intervals to draw
attention to a subregion, such as an exon, splice site, or event.
Usage percentages are computed separately for each sample and are unchanged by library-size normalisation or coordinate compression. Labels are rounded to one decimal place. If no selected junction has positive support, no usage percentage is shown. The denominator is conditional on the imported data: changing the BAM query region, MAPQ threshold, or strand selection can change which evidence is available.
The arguments strandedness, min_coverage,
min_junction_reads, and colours may each be supplied either as
length 1, in which case the value is recycled across all BAMs, or as one
value per BAM.
When lib_size is supplied, coverage and junction counts are normalised
to a common effective library size before plotting. Effective library sizes
are calculated as lib_size * norm_factors, with
norm_factors = 1 when not supplied. If normalise_to = NULL,
counts are normalised to the median effective library size. Filtering
thresholds min_coverage and min_junction_reads are always
applied to raw counts before normalisation. Percentage thresholds are
calculated separately for each BAM from the maximum raw value within the
plotting region.
Strand filtering is applied after BAM import. Unstranded libraries retain
alignments from both strands. For stranded libraries, reads are interpreted
according to strandedness; when the resolved region has a
specific strand, alignments are then restricted to that strand.
When compress_introns = TRUE, the plot uses compacted coordinates
internally, but x-axis tick labels are reported as approximate genomic
coordinates.
Annotation is drawn on a separate panel beneath the sample panels. Highlighted intervals are overlaid across both sample and annotation panels when present.
For advanced workflows, return_ctx = TRUE can be used to inspect or
modify processed genomic data before plotting. The returned context is a
named list containing genomic summaries and plotting settings. Fields such as
cov, juncs, juncs_all, annotation,
junction_usage, and highlight all use genomic coordinates.
Passing the modified context through ctx rebuilds the coordinate map
and redraws the plot without reading the BAM files again.
Coverage and junctions in a returned context have already been summarised,
filtered, and normalised. Changing processing settings such as
min_mapq, min_coverage, min_junction_reads, or
lib_size does not repeat those processing steps; modify
ctx$cov or ctx$juncs directly instead. Plotting settings such
as colours, arc_side, and compress_introns may be
changed in the context before replotting.
juncs_all retains the eligible junction summaries on the plotting
chromosome before display filtering or clipping, including junctions outside
the plotting window. It is the reference for usage calculations when a
context is replotted. Filtering ctx$juncs changes only the display;
modify ctx$juncs_all if you intend to change the usage reference.
The reference must retain one row per sample/junction and its non-negative
coverage_raw counts. Changing ctx$junction_usage to another
GRanges selection recalculates percentages from this reference.
The replacement selection must overlap the plotting region and have
compatible genomic metadata.
If return_ctx = FALSE, a patchwork object containing one sample
panel per BAM file plus an optional annotation panel.
If return_ctx = TRUE, a named list containing validated settings and
processed alignment, coverage, junction, annotation, and overlay data. All
coordinate-bearing fields use genomic coordinates; plot-space data are
generated internally when the context is plotted.
The gal field contains one alignment object per BAM: a
GAlignments for single-end input or a
GAlignmentsList for paired-end input.
Paired-end list elements group the imported mates and include mapped
singleton reads.
The cov and juncs fields store fragment summaries. Their
coverage_raw columns contain unnormalised fragment counts, while
coverage contains the values used for plotting, normalised when
lib_size is supplied. The gal field retains the imported
alignments rather than collapsed coverage or junction data.
juncs_all stores the unfiltered junction reference. The
usage_fraction column in juncs contains fractions on the 0–1
scale; NA denotes an unselected junction or undefined percentage.
Fractions are recalculated from juncs_all before each plot is drawn.
In the returned plot, the x-axis is shared across panels. Tick labels are shown in genome coordinates, including when introns are compressed.
Katz Y et al. (2015). Quantitative visualization of alternative exon expression from RNA-seq data. Bioinformatics, 31(14), 2400–2402. doi:10.1093/bioinformatics/btv034.
Robinson MD and Oshlack A (2010). A scaling normalization method for differential expression analysis of RNA-seq data. Genome Biology, 11, R25. doi:10.1186/gb-2010-11-3-r25.
Zarnack K et al. (2013). Direct Competition between hnRNP C and U2AF65 Protects the Transcriptome from the Exonization of Alu Elements. Cell, 152(3), 453–466. doi:10.1016/j.cell.2012.12.023.
readGAlignments and readGAlignmentsList for reading alignments, and GRanges for representing genomic intervals.
if ( requireNamespace("RNAseqData.HNRNPC.bam.chr14", quietly = TRUE) && requireNamespace("EnsDb.Hsapiens.v75", quietly = TRUE) && requireNamespace("AnnotationFilter", quietly = TRUE) && requireNamespace("ensembldb", quietly = TRUE) ) { bams <- RNAseqData.HNRNPC.bam.chr14::RNAseqData.HNRNPC.bam.chr14_BAMFILES bams <- bams[c(7, 1)] names(bams) <- c("HNRNPC knockdown", "Control") region <- "chr14:70,233,810-70,238,690" annotation <- ensembldb::exonsBy( EnsDb.Hsapiens.v75::EnsDb.Hsapiens.v75, by = "tx", filter = AnnotationFilter::GeneIdFilter("ENSG00000100650") ) annotation <- annotation[1:3] ensembldb::seqlevelsStyle(annotation) <- "ucsc" spliceTerrain(bam = bams, region = region) spliceTerrain( bam = bams, region = region, lib_size = c(40e6, 55e6), norm_factors = c(0.95, 1.08), common_y = TRUE ) spliceTerrain( bam = bams, region = region, annotation = annotation, anno_fill_by = "group", anno_fill_colours = c( ENST00000553369 = "#66C2A5", ENST00000394366 = "#8DA0CB", ENST00000451983 = "#FC8D62" ), anno_label_by = "exon_rank", anno_label_colour = "black", junction_usage = "chr14:70234854-70234854", highlight = "chr14:70233810-70234097", arc_height = 2, arc_side = "above", arc_scale = TRUE, common_y = TRUE, colours = c("darkblue", "darkred"), highlight_colour = scales::alpha("gold", 0.25), anno_label_size = 2, panel_heights = c(2, 2, 1) ) ctx <- spliceTerrain( bam = bams, region = region, annotation = annotation, min_junction_reads = 1, panel_heights = c(2, 2, 1), return_ctx = TRUE ) ctx$juncs <- ctx$juncs[ctx$juncs$coverage >= 20] spliceTerrain(ctx = ctx) }if ( requireNamespace("RNAseqData.HNRNPC.bam.chr14", quietly = TRUE) && requireNamespace("EnsDb.Hsapiens.v75", quietly = TRUE) && requireNamespace("AnnotationFilter", quietly = TRUE) && requireNamespace("ensembldb", quietly = TRUE) ) { bams <- RNAseqData.HNRNPC.bam.chr14::RNAseqData.HNRNPC.bam.chr14_BAMFILES bams <- bams[c(7, 1)] names(bams) <- c("HNRNPC knockdown", "Control") region <- "chr14:70,233,810-70,238,690" annotation <- ensembldb::exonsBy( EnsDb.Hsapiens.v75::EnsDb.Hsapiens.v75, by = "tx", filter = AnnotationFilter::GeneIdFilter("ENSG00000100650") ) annotation <- annotation[1:3] ensembldb::seqlevelsStyle(annotation) <- "ucsc" spliceTerrain(bam = bams, region = region) spliceTerrain( bam = bams, region = region, lib_size = c(40e6, 55e6), norm_factors = c(0.95, 1.08), common_y = TRUE ) spliceTerrain( bam = bams, region = region, annotation = annotation, anno_fill_by = "group", anno_fill_colours = c( ENST00000553369 = "#66C2A5", ENST00000394366 = "#8DA0CB", ENST00000451983 = "#FC8D62" ), anno_label_by = "exon_rank", anno_label_colour = "black", junction_usage = "chr14:70234854-70234854", highlight = "chr14:70233810-70234097", arc_height = 2, arc_side = "above", arc_scale = TRUE, common_y = TRUE, colours = c("darkblue", "darkred"), highlight_colour = scales::alpha("gold", 0.25), anno_label_size = 2, panel_heights = c(2, 2, 1) ) ctx <- spliceTerrain( bam = bams, region = region, annotation = annotation, min_junction_reads = 1, panel_heights = c(2, 2, 1), return_ctx = TRUE ) ctx$juncs <- ctx$juncs[ctx$juncs$coverage >= 20] spliceTerrain(ctx = ctx) }