cBioPortal logoUse case

Twenty-Four Ways to Say Radiation Therapy

A public audit of 375 cBioPortal studies went looking for how the same clinical concepts were encoded from study to study — by hand, header by header. Radiation therapy alone turned up under 24 distinct encodings: different attribute IDs, different datatypes, different value conventions, all describing the same treatment. Multiply that by every common concept — smoking status, tumor stage, vital status — and the shape of the problem is plain. The platform's cross-study query tools are excellent; the attributes they query were never designed to line up. A cohort filter that matches one study's encoding silently misses the patients recorded under the other twenty-three.

Twenty-Four Ways to Say Radiation Therapy

A public audit of 375 cBioPortal studies went looking for how the same clinical concepts were encoded from study to study — by hand, header by header. Radiation therapy alone turned up under 24 distinct encodings: different attribute IDs, different datatypes, different value conventions, all describing the same treatment. Multiply that by every common concept — smoking status, tumor stage, vital status — and the shape of the problem is plain. The platform's cross-study query tools are excellent; the attributes they query were never designed to line up. A cohort filter that matches one study's encoding silently misses the patients recorded under the other twenty-three.

Nothing in the pipeline is positioned to fix this

It is worth being precise about why the ecosystem has not already solved this, because every piece of it is doing its job.

validateData.py is the format authority, and it is good at that job: strict, mature, authoritative on whether a study is well-formed. It also validates one study at a time and never looks across two. A study where RADIATION_THERAPY is a STRING and a study where RAD_TX is a BOOLEAN both pass, because each is internally legal, and internal legality is all the validator was ever asked for.

MSK maintains a Clinical Data Dictionary — a curated list of preferred attribute definitions, exactly the artifact this problem needs. But the file-format documentation is explicit that it is advisory: curators can choose to ignore the proposed definitions. There is no authoring path for another institution to maintain its own dictionary, and no enforcement path for anyone's.

The cBioPortal team knows. Their own project proposal for clinical attribute harmonization tooling has been open since 2024, waiting for someone to build it. Until someone does, the state of the art for cross-study consistency is a person with a spreadsheet and patience.

One dictionary, audited against, generated from

The CoreModels approach is to make the dictionary real — governed, versioned, and enforced by audit rather than by goodwill.

Seed it from your best-curated study. Import that study's clinical staging headers — the four # rows and the attribute-ID row, nothing else. Each attribute becomes a governed element carrying its description and datatype, with display name and priority preserved as metadata; PATIENT_ID and SAMPLE_ID become declared identities. Because only headers are read, the seed is a schema-only artifact: cheap to produce, and free of patient data by construction.

Audit every study's headers against it. Each divergence from the dictionary becomes a named finding with a stable code. An attribute typed differently than the dictionary types it is field-type-drift, with both types stated. An attribute the dictionary has never heard of is a coverage finding — the moment RAD_TX shows up beside RADIATION_THERAPY, it is on a report instead of in the dark. A lowercase attribute ID is attribute-id-not-upper, flagged before the portal's validator fails the upload; an empty description row is attribute-no-description, counted per instrument. The audit is read-only: it names divergence and stops.

Ground the dictionary in NCIt. A governed attribute can be bound to a National Cancer Institute Thesaurus term through a two-step gate: an advisory suggestion step proposes ranked candidate terms from the public ontology lookup service, and a human confirms the binding — an Admin-gated act, never applied automatically. Once bound, "what does this attribute mean" has an answer other institutions' tools recognize, instead of a local string.

Generate new studies from the dictionary. The loop closes in the other direction: upload-ready staging-file header scaffolds are emitted from the governed definitions — all four # rows filled in, descriptions populated, UPPER_CASE attribute IDs minted from the governed labels. The twenty-fifth encoding of radiation therapy never gets written, because the next study starts from the definition the dictionary already governs.

What this is not

This is detection and governance, not auto-harmonization. The semantic-similarity mapping the harmonization proposal asks for — software that decides on its own that RAD_TX and RADIATION_THERAPY are the same concept — is not claimed here. A human decides which encoding is canonical; the machinery makes that decision visible, auditable, and enforceable from then on. Twenty-four encodings do not collapse into one on import. They show up as findings against one governed definition, which is the honest version of progress.

And it is headers only, deliberately. Values, OncoTree codes, and sample counts live in data rows the import never reads — no claim is made about any of them, and no patient data ever leaves the site. The privacy property and the scope limit are the same fact.

The import, audit, and generate mechanics are the standard connector flow, covered end to end in the cBioPortal quickstart that ships with CoreModels.