Skip to content

Proteomics: add preranked GSEA as a threshold-free complement to ORA enrichment #3942

Description

@ejaeger42

Summary

Proteomics term enrichment is ORA-only today — enrichmentAnalysis calls g:Profiler's
g:GOSt (src/analysis/enrichment.ts) on the thresholded significant-gene hit list, split by
direction. ORA is set-based and threshold-sensitive: a protein counts fully in or fully out once
it crosses the significance cut, so a handful of borderline proteins can move a whole term. Propose
adding preranked GSEA as a complementary, threshold-free enrichment method.

Why (evidence from a real client analysis)

On the Cytokinetics DMD/WT data we compared enrichment built from two DE paths (Spectronaut
"candidates" vs our recomputed "report" path). The two hit lists agree ~90% (κ=0.90), and pathway
conclusions agree — except for four DMD-relevant terms (interstitial matrix, elastic fibres,
growth factor activity; regulation of calcium ion transport) that were significant in one path and
not the other. The flip was driven entirely by ~a handful of boundary proteins crossing the DE cut,
amplified by ORA's all-or-nothing counting.

A one-off preranked GSEA (gseapy, ranking = log2FC) on the same data, run on both paths:

  • NES concordance between the two paths: Spearman 0.965 across 4,131 gene sets (vs ORA, where
    the four terms flipped). The path-dependence essentially disappears.
  • The four flip terms become path-robust: e.g. elastic fibres NES −1.44 vs −1.45, growth factor
    activity −1.52 vs −1.53, calcium transport +1.49 vs +1.59 — near-identical either way, directions
    consistent with ORA.
  • Bonus finding: under GSEA those terms are sub-significant (FDR 0.14–0.42), i.e. ORA's
    significance for them in the report path was partly a threshold artifact. GSEA is both
    path-robust and less prone to overstating marginal terms.

Repro: ~/Downloads/ck/analysis_scripts/gsea_concordance.py (analysis deliverables, not in-repo).

Proposal

Add preranked GSEA alongside ORA (complement, not replace):

  • Engine: server-side script — fgsea (R, matches the existing limma/DEqMS/VSN R-script +
    client-fallback pattern) or gseapy/blitzgsea (Python). g:Profiler's API can't do preranked GSEA.
  • Input: the full ranked DE result (all proteins, signed metric — log2FC or sign·−log10p), not a
    hit list. Needs tie/missing handling and a gene-set DB (MSigDB / GO / KEGG / Reactome).
  • Output schema: Term, ES, NES, NOM p, FDR, leading-edge genes, Direction (sign of NES).
  • Viewers — largely already built. The Phase 19 enrichment aids map almost 1:1 onto GSEA output:
    signed NES ↔ the directionality bar, and leading-edge is native to GSEA (the current leading-edge
    drill-down is an ORA-intersection approximation of exactly this). Much of the UI investment is reusable.

Implications / effort

  • Heavier compute than ORA's instant hypergeometric (permutation-based) → server call, not client.
  • New dependency (fgsea or gseapy) + gene-set DB handling + result schema + viewer wiring + tests.
  • De-risked by the existing R-script infrastructure and the Phase 19 viewers.
  • Positioning: keep ORA for fast, interactive "what's in my hit list"; GSEA for robust, threshold-free
    conclusions. Offer both; flag when they disagree.

Open questions

  • fgsea (R) vs gseapy/blitzgsea (Python) — which fits the deploy story best?
  • Ranking metric default (log2FC vs signed −log10p vs moderated-t) and how to expose it.
  • Gene-set source/versioning and organism handling (reuse the enrichment organism setting).

Sibling to #3930 (imputer-default rethink) — both are method-quality improvements surfaced by the
Cytokinetics report-path validation.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions