Skip to content

feat(cell_metrics): source RT-switching junction violins from the cell summary - #41

Merged
CarlosBlancoGo merged 1 commit into
mainfrom
feat/rts-junction-metrics-cell-summary
Jul 20, 2026
Merged

feat(cell_metrics): source RT-switching junction violins from the cell summary#41
CarlosBlancoGo merged 1 commit into
mainfrom
feat/rts-junction-metrics-cell-summary

Conversation

@CarlosBlancoGo

Copy link
Copy Markdown
Collaborator

Summary

  • Moves the two RT-switching-by-splice-junction-type violins (all junctions and
    unique junctions) out of the report's on-the-fly junctions×classification
    explosion and into real cell-summary columns, computed once during metrics —
    removing the last per-cell junction re-derivation from the report.
  • Adds 12 per-cell columns in both modes, emitted only when the junctions
    file carries the needed inputs (so the report skips a plot exactly when its
    columns are absent — same behaviour as the old runtime guards).

Details

  • cell_metrics.py
    • RTS_{Known,Novel}_{canonical,non_canonical}_junctions — RTS-flagged,
      FL-weighted numerators for the all-junction plot; denominators are the
      existing *_junctions totals.
    • unique_… + RTS_unique_… — distinct-intron counts for the unique-junction
      plot. Isoforms mode collapses the same genomic intron shared across
      transcripts via a sparse Jt @ Xp incidence (junction×transcript times
      transcript×cell presence), binarized and kept in scipy.sparse so the
      (junction, cell) product is never densified. Reads mode dedups introns per
      cell with a groupby.
    • Adds RTS_junction + genomic-coordinate columns to the otherwise-minimal
      junctions read.
  • SQANTI-sc_report.R — new build_rts_sjtype_long() derives each SJ type's
    per-cell percentage from the columns (NA when a cell has no junctions of a
    type, so it drops out of the violin); both plots are gated on their columns'
    presence. Deletes the junc_rt explosion and the now-dead junc_iso_key
    resolver.
  • Tests — 4 new (isoforms shared-intron-collapse and distinct-intron cases,
    reads-mode RTS/unique).

…l summary

Move the two RT-switching-by-splice-junction-type violins (all junctions and
unique junctions) out of the report's junctions x classification
explosion and into cell-summary columns computed once during metrics.
This removes the last per-cell junction re-derivation from the report.

Adds 12 per-cell columns in both modes, emitted only when the junctions file
carries the needed inputs, so the report skips a plot exactly when its columns
are absent:

- RTS_{Known,Novel}_{canonical,non_canonical}_junctions: RTS-flagged,
  FL-weighted numerators for the all-junction plot. Denominators are the
  existing *_junctions totals.
- unique_... and RTS_unique_...: distinct-intron counts for the unique-junction
  plot. Isoforms mode collapses the same genomic intron shared across
  transcripts via a sparse Jt @ Xp incidence (junction x transcript times
  transcript x cell presence), binarized and kept in scipy.sparse so the
  (junction, cell) product is never densified. Reads mode dedups introns per
  cell with a groupby.

cell_metrics.py also adds RTS_junction and the genomic-coordinate columns to the
otherwise-minimal junctions read (small next to the CB column that dominates the
isoforms junctions file).

SQANTI-sc_report.R gains build_rts_sjtype_long(), which derives each SJ type's
per-cell percentage from the columns (NA when a cell has no junctions of a type,
so it drops out of the violin); both plots are gated on their columns' presence.
Deletes the junc_rt explosion and the now-dead junc_iso_key resolver.
@CarlosBlancoGo
CarlosBlancoGo merged commit d16f3e7 into main Jul 20, 2026
2 checks passed
@CarlosBlancoGo
CarlosBlancoGo deleted the feat/rts-junction-metrics-cell-summary branch July 20, 2026 10:01
CarlosBlancoGo added a commit that referenced this pull request Jul 20, 2026
…cating rows (#42)

The per-cluster length-distribution violins re-derived their data by exploding the classification CB/FL lists to per-(transcript, cell) rows and then replicating each row FL times (rep(seq_len(n), times = FL)) so every read became a literal row. In isoforms mode the replicated frame is the number of reads -- the same per-read explosion that #35, #36, #40 and #41 removed elsewhere by moving metrics off the report's on-the-fly re-derivation.

Aggregate instead to per-(transcript, cluster) with weight = sum(FL), and drive the violin with the native geom_violin weight aesthetic, plus a weighted mean and a weighted five-number box summary computed from a small weighted-quantile helper. This reproduces the FL-replicated distribution exactly at a fraction of the rows: on the test set the weighted mean matches the replicated mean to full precision and the quantiles to within interpolation noise (invisible on the log-length axis); the rendered violins are indistinguishable in both modes.

The weighted-quantile helper also handles clusters/category subsets with fewer than two points (a single transcript collapses to a degenerate box) so sparse per-category panels no longer abort the whole length-by-cluster block via the outer tryCatch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant