Skip to content

OncoPrint Tabular download and order file as the portal writes them (ONC-DL-3, ONC-DL-4) - #220

Open
alisman wants to merge 1 commit into
masterfrom
session/oncoprint-tabular
Open

alisman wants to merge 1 commit into
masterfrom
session/oncoprint-tabular

Conversation

@alisman

@alisman alisman commented Nov 15, 2026

Copy link
Copy Markdown
Contributor

Item 2d of the OncoPrint parity work, without Open in Oncoprinter, which is now marked for after the initial release.

What changes

The Tabular download has the portal's rows (tabularDownload.ts getTabularDownloadData):

Group Rows
CLINICAL one per clinical track, by display name (Diagnosis Age, not AGE); the mutation spectrum one per substitution, Mutation spectrum (C>A)
CNA, MUTATIONS, MRNA, PROTEIN, STRUCTURAL_VARIANT every gene in every group, empty where it has nothing of that kind (we load no mRNA or protein calls, so those rows are empty, as in the portal for a query without them)
HEATMAP <alteration type> <datatype> HEATMAP MRNA_EXPRESSION Z-SCORE, HEATMAP GENERIC_ASSAY LIMIT-VALUE, rows by gene or entity
  • A mutation cell is the one class drawn: drivers first, then truncating > splice > inframe > promoter > missense > other. It uses the portal's words: "Truncating mutation (putative driver)", "Missense Mutation (putative passenger)", no suffix with annotation off, and never one on Promoter.
  • A cell that was not profiled is empty.
  • The columns are as drawn. The page builds the file in the browser from its sort and Show unaltered.
  • The server, the CLI and the Python package write the same file over the contract's columns, minus the unaltered ones when the display hides them.
  • File names are the portal's: PATIENT_DATA_oncoprint.tsv / SAMPLE_DATA_oncoprint.tsv.
  • The order file is the portal's too. Its first line is Patient order in the Oncoprint is: and it is saved as OncoPrintPatients.txt / OncoPrintSamples.txt.

The engine now carries:

  • each clinical attribute's display name, from clinical_attribute_meta (the first study's, when studies name it differently; AGE has 14 names in the warehouse);
  • each heatmap profile's alteration type and datatype, from genetic_profile.

Federation shares carry both as optional fields, so an older peer still reads. The Python port gets the same writer, and also the mutation-spectrum row, which its engine did not build before.

Deliberate divergences (PORTAL-PARITY)

  • Where the portal writes its internal codes, we write readable text:
    • splice_rec becomes "Splice Mutation (putative driver)";
    • amp_rec becomes "Amplification (putative driver)";
    • sv / sv_rec become "Structural Variant" / "Structural Variant (putative driver)".
  • A merged row is named as drawn (RAS). The portal names it by its genes (KRAS / NRAS) whatever its label.
  • Across studies, column ids are <study>_<id>, so they stay unique.
  • Numbers are written at float32's 7 significant digits.
  • The VAF heatmap rows are typed HEATMAP MUTATION_EXTENDED VAF; the portal has no VAF heatmap.
  • Derived-event rows come last, typed DERIVED.

How it was checked

  1. Case table from the legacy source: 31 rows, citing tabularDownload.ts, ResultsViewOncoprint.tsx and DataUtils.ts.
  2. Tests written from the table by a separate agent that never saw the implementation: test/oncoprint-tabular-portal.test.ts and python/tests/test_tabular_portal.py, which includes a byte-for-byte TypeScript/Python conformance test. They failed against the old writer.
  3. Warehouse shapes:
    • 15 alteration type × datatype pairs;
    • 19,299 of 19,504 attributes have a display name that differs from the id;
    • no clinical value or display name holds a tab or newline.
  4. SQL run against the fixture study: the display-name and profile-kind queries, 78/78 checks.
  5. Planted bugs: 13, all caught (one was missed at first, and a test was added for the server's Show-unaltered path), plus 4 by hand in the Python writer.
  6. Against cbioportal.org: brca_tcga_pan_can_atlas_2018, ERBB2 TP53 PIK3CA with Diagnosis Age, Subtype and an ERBB2 mRNA z-score heatmap. The page's download was compared cell by cell with the portal's download over our 123 ERBB2-amplified patients. Every shared row and cell agrees except:
    • the raw codes listed above;
    • two driver calls (a PIK3CA missense and a TP53 fusion) where the portal's live OncoKB differs from our pinned v7.5.

Not run: scripts/gate.sh (CI runs the full gate).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q3ezTZRWoR5xpTndPddHAe

…ONC-DL-3, ONC-DL-4)

The Tabular download now has the portal's rows (tabularDownload.ts getTabularDownloadData):
- CLINICAL rows named by display name (the mutation spectrum one row per substitution,
  "Mutation spectrum (C>A)");
- then each gene's CNA, MUTATIONS, MRNA, PROTEIN and STRUCTURAL_VARIANT rows, every gene in every
  group;
- then a group per heatmap profile kind, "HEATMAP MRNA_EXPRESSION Z-SCORE", rows named by gene
  or entity.

A mutation cell is the one class drawn, in the portal's words ("Truncating mutation (putative
driver)", "(putative passenger)" with annotation on, no suffix off, Promoter never); a cell not
profiled is empty. The page builds the file in the browser from the columns as drawn (its sort,
Show unaltered), as PATIENT_DATA_oncoprint.tsv / SAMPLE_DATA_oncoprint.tsv; the server, CLI and
Python write the same file over the contract's columns, less the unaltered ones when the display
hides them. The order file reads "Patient order in the Oncoprint is:", OncoPrintPatients.txt.

The engine carries each clinical attribute's display name (clinical_attribute_meta, the first
study's) and each heatmap profile's alteration type and datatype (genetic_profile), through
federation shares too (optional fields, so an older peer still reads). The Python port gains the
same writer, and the mutation spectrum row it did not build before.

Ours alone, documented in PORTAL-PARITY: readable text where the portal writes its internal codes
(splice_rec, amp_rec, sv_rec); a merged row named as drawn; study-qualified ids across studies.
Open in Oncoprinter is marked for after the initial release.

Verified: a case table from the legacy source; tests written from it by a separate agent, seen
failing against the old writer; the display-name and profile-kind SQL run against the fixture
study (78/78); 13 planted bugs, all caught, and 4 in the Python writer by hand. On
brca_tcga_pan_can_atlas_2018 (ERBB2 amp, 123 patients) the page's file was compared cell by cell
with cbioportal.org's download: every shared cell agrees except the raw codes above and two
driver calls where the portal's live OncoKB differs from the pinned v7.5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q3ezTZRWoR5xpTndPddHAe
@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:37am UTC
cbiolab-new Ready Ready Preview Nov 15, 2026 3:37am UTC
cohort-lab Ready Ready Preview Nov 15, 2026 3:37am UTC

Request Review

This branch was successfully deployed

1 active deployment
Preview – cohort-lab — 104c9d14 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