Skip to content

OncoKB for structural variants: per gene pair and tumour type (K) - #219

Open
alisman wants to merge 1 commit into
masterfrom
session/mut-annotation-oncokb-sv
Open

alisman wants to merge 1 commit into
masterfrom
session/mut-annotation-oncokb-sv

Conversation

@alisman

@alisman alisman commented Nov 15, 2026

Copy link
Copy Markdown
Contributor

Summary

A new annotation source, oncokb_sv, asks OncoKB about each structural variant the way the portal's Structural Variants tab does (generateAnnotateStructuralVariantQuery). Each query is keyed by:

  • the site 1 and site 2 genes;
  • OncoKB's SV type: FUSION for two genes, otherwise the class when it is exactly one of OncoKB's six types, else UNKNOWN;
  • the sample's tumour type, by the same rule the mutation table uses.

The answers are stored in annotation.oncokb_sv (migration 005, already run on the warehouse), licensed like annotation.oncokb.

The SV table's Annotation column now reads the pair's call for the sample's tumour type. It falls back to the partners' gene-level Fusion calls only for a study whose structural variants aren't synced. Two pieces are now shared:

  • one tumour-type CTE builder (sampleTumorTypeCte) for the mutation and SV tables;
  • one pair of tumour-type subqueries for the two sync sources.

Out of scope: the oncoprint, OQL DRIVER and plot driver axes keep the gene-level call. Their rows in genomic_event_derived don't name the partner, so joining them to the pair calls is a later PR, with tumour type null as the portal's oncoprint asks. The Mutations tab's fusions (E) come next and read this store.

Legacy reference

cbioportal-frontend e9d70fb:

  • OncoKbUtils.ts 246-317: deriveStructuralVariantType, generateAnnotateStructuralVariantQuery.
  • OncoKbUtils.ts 89-100: generateQueryStructuralVariantId.
  • StoreUtils.ts 861-867 and 1049-1060: only curated partners are asked; POST /annotate/structuralVariants.
  • ResultsViewPageStore.ts 5967-5990: tumour type per sample.
  • StoreUtils.ts 2016-2062: driver oncogenicities.

Spec (invariant 14)

Tests were written from this table by a separate agent, before the code, and seen to fail.

The rule, case by case

Y — the query for one structural variant (generateAnnotateStructuralVariantQuery, OKU 284-317; deriveStructuralVariantType, OKU 246-281)

# Input Expected Source
Y1 site1 and site2 entrez both set, different genes geneA = site1, geneB = site2, type FUSION, functionalFusion true OKU 263-280, 299-316
Y2 site1 = site2 (same gene, both set) two genes counted: FUSION, functionalFusion true, geneA = geneB OKU 263-266 (two pushes)
Y3 only site1 entrez set; class one of DELETION, TRANSLOCATION, DUPLICATION, INSERTION, INVERSION, FUSION (exact case) geneA = geneB = site1, type = class, functionalFusion false OKU 249-276, 306-311
Y4 only site2 entrez set geneA = geneB = site2 OKU 301-303
Y5 one gene; class "DEL", "Deletion", "NA", "BREAKENDS", empty type UNKNOWN (case-sensitive match) OKU 273-276
Y6 one gene, class FUSION type FUSION, functionalFusion false OKU 273
Y7 the gene count for the type uses the Hugo symbols, the genes sent use entrez ids a SV with both entrez set but one blank symbol is typed from its class OKU 260-263 vs 299-303
Y8 neither gene curated by OncoKB not asked SU 861-866
Y9 one partner curated asked SU 861-866 (||)
Y10 two SVs with the same id (site1 entrez, site2 entrez, type, tumour type) one query OKU 89-100, SU 867 uniqBy id

T — tumour type

# Input Expected Source
T1 Structural Variants tab (and the Mutations tab's fusions) the sample's tumour type, the same map as mutations (C's T1–T5) RVS 5967-5990 uniqueSampleKeyToTumorType
T2 the oncoprint no tumour type (cancerTypeForOncoKb(key, {}) → null) RVS 5476-5480, 5549-5555

D — what makes an SV a driver (the SV table's order and, in a later PR, the oncoprint)

# Input Expected Source
D1 OncoKB oncogenic Oncogenic / Likely Oncogenic / Resistance driver (the portal also lists Predicted Oncogenic, which OncoKB v7.7 never answers; cBioLab's mutation table uses these three) SU 2016-2031, 2062
D2 Likely Neutral, Inconclusive, Unknown, no answer not by OncoKB same

S — stored and shown

# Input Expected Source
S1 OncoKB's answer stored per (geneA, geneB, type, functionalFusion, tumour type) at the release; oncogenicity, levels, whole answer cBioLab (store)
S2 SV table Annotation column, a SV whose pair and tumour type the store holds at the pin that row's oncogenicity and highest sensitive level; drv from it (D1) legacy SV table (StructuralVariantTable.tsx 456-490)
S3 row stored at another release than the pin not read cBioLab (version pin)
S4 SV table, a SV with no stored pair row for its tumour type (study not synced) the current gene-level fallback: the stronger partner's annotation.oncokb 'Fusion' row cBioLab (as C's S4)
S5 two samples of one patient, same pair, different tumour types each row its own tumour type's call T1
S6 a SV whose pair row says Unknown while a partner's gene-level Fusion row says Oncogenic Unknown (the pair row wins; no fallback when a pair row exists) S2/S4
S7 an uncurated pair (stored with empty oncogenicity) blank annotation, not a driver, no fallback Y8

Corrections the test author made to the first draft of the spec:

  • Legacy's driver list has no "Predicted Oncogenic", and OncoKB never answers it.
  • An absent site is written "undefined" in the query id.
  • The key is site 1 / site 2 as stored, never reordered.
  • Several line citations were fixed.

Y7 has no fixture row: the warehouse has none (both Entrez ids set but one Hugo symbol blank).

Verification

Tests

  • Unit tests: packages/annotation-sync/test/oncokb-sv.test.ts, 20 tests (query, stored row, which keys are asked), plus the source-list and store tests.
  • Peer fixture: a structural-variant profile, FX-P45 to FX-P53 with 17 SVs, covering Y1–Y6, Y8–Y10, T1, S2–S7.
  • npm run check:oncokb-sv: 42/42 against the fixture DB, with SQL run rather than matched as text.
  • check:oncokb-tumor-type: 47/47.
  • The fixture's new samples moved the tracks-menu and audit hand counts. I recounted them by script from data_clinical_*.txt.
  • Full npm test with the peer env: clean. This is the planted-bug runner's unit baseline.
  • node --test test/view-snapshots*.test.ts: 61/61. The sv and mutations snapshots were re-recorded. The values are unchanged (sv still 131 rows); only the caption and method text changed, since msk_impact_2017 isn't synced.

Planted bugs. Every guard's baseline passes, and all four are caught:

Planted bug Guard Failing checks
oncokb-sv-one-gene-is-fusion oncokb-sv 6
oncokb-sv-class-case-folded oncokb-sv 2
oncokb-sv-tumour-type-ignored oncokb-sv 8
oncokb-sv-gene-level-wins oncokb-sv 2

Real sync. npm run annotate -- oncokb_sv --study acc_tcga_pan_can_atlas_2018 stored 260 keys at OncoKB v7.7, with 0 failures:

  • 209 not asked (no curated partner);
  • 24 Likely Oncogenic;
  • 26 Unknown;
  • 1 UNKNOWN-type.

Cross-check with cbioportal.org: POST /api/structural-variant/fetch for TSC2, CDK12, RAD51C, KMT2A, APC, SUFU and ALDH2 in acc returns 9 calls. They are the same 9 pairs and samples our SV view lists.

The acc SV view pinned to v7.7 shows the pair calls:

Sample Gene 1 Gene 2 Annotation
TCGA-P6-A5OF-01 GNB1 TSC2 Likely Oncogenic · Level 3B
TCGA-OR-A5J1-01 KCTD5 TSC2 Likely Oncogenic · Level 3B
TCGA-OR-A5KX-01 CDK12 LRRC37A11P Likely Oncogenic · Level 3B
TCGA-OR-A5KY-01 CHD3 RAD51C Likely Oncogenic · Level 3B
TCGA-OR-A5J1-01 KMT2A ATP5MG Likely Oncogenic
TCGA-OR-A5KY-01 ALDH2 ACTB Likely Oncogenic

These are OncoKB's tumour-suppressor fusion rule (Likely Loss-of-function), except KMT2A, which is Likely Gain-of-function. At the app's current pin (v7.5) the same rows are blank, so nothing is read across releases (S3).

I couldn't compare OncoKB icons on cbioportal.org's page: Cloudflare's bot check blocks a headless browser, and the portal's OncoKB proxy forbids programmatic use. To spot-check by eye, open https://www.cbioportal.org/results/structuralVariants?cancer_study_list=acc_tcga_pan_can_atlas_2018&case_set_id=acc_tcga_pan_can_atlas_2018_all&profileFilter=structural_variants&gene_list=TSC2%20CDK12%20RAD51C%20KMT2A&Action=Submit — the expected values are in the table above.

Not done

  • The pin. The app pins the newest release in annotation.oncokb (v7.5). oncokb_sv holds v7.7 for acc only, so the SV tab keeps the gene-level fallback until the planned re-annotation brings all OncoKB stores to one release.
  • Oncoprint, OQL DRIVER and plot drivers from pair calls: follow-up PR.
  • Fusions on the Mutations tab (E): next PR.

Preview

  • /portal/results/structuralVariants?cancer_study_list=acc_tcga_pan_can_atlas_2018&gene_list=TSC2%20CDK12

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q3ezTXeuA6xMdKduTsWw4c

@vercel

vercel Bot commented Nov 15, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
cbiolab-genie Ready Ready Preview Nov 15, 2026 3:52am UTC
cbiolab-new Ready Ready Preview Nov 15, 2026 3:52am UTC
cohort-lab Ready Ready Preview Nov 15, 2026 3:52am UTC

Request Review

A new annotation source, oncokb_sv, asks OncoKB about each structural
variant as the portal's Structural Variants tab does
(generateAnnotateStructuralVariantQuery): site 1 and site 2 genes,
OncoKB's SV type (FUSION for two genes; for one, the class when it is
exactly one of OncoKB's six types, else UNKNOWN) and the sample's tumour
type (the rule the mutation table uses). Keys with no curated partner are
stored unasked. Stored in annotation.oncokb_sv (migration 005), licensed
like annotation.oncokb.

The SV table's Annotation column reads the pair's call for the sample's
tumour type, falling back to the partners' gene-level Fusion calls only
where the store holds no row for the variant (a study not synced). The
tumour-type rule is now one CTE builder shared by the mutation and SV
tables (sampleTumorTypeCte), and one pair of subqueries shared by the two
sync sources.

Tests written from the spec table by a separate agent before the code:
unit tests for the query, the stored row and which keys are asked; a
structural-variant profile in the peer fixture (FX-P45 to FX-P53, 17 SVs)
and check:oncokb-sv (42 checks); four planted bugs, all caught. The
fixture's new samples move the tracks-menu hand counts, recounted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q3ezTXeuA6xMdKduTsWw4c

This branch was successfully deployed

1 active deployment
Preview – cohort-lab — 74d58340 Deployed Nov 15, 2026 by vercel[bot]
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