Body Model Anatomy Variants
Gender-affirming and post-surgical anatomy variants for the 3D body model.
Status: design (not yet implemented). Companion to the 3D body-model + SNOMED region system (
web/packages/medical-kit/src/body-model-3d/). This doc is for the session/owner handling the base anatomy gap; it layers cleanly on top of that work.
Problem
The model today has two base meshes (male, female) and sex-specific organ sets
(male: prostate/testes; female: uterus/ovaries/breasts). Real patients aren’t always
one of those two fixed sets:
- Gender-affirming anatomy — trans women (MTF), trans men (FTM), non-binary, and intersex patients have anatomy that mixes/alters the base sets (e.g., a trans man post-mastectomy + hysterectomy with a neophallus).
- Post-surgical states (any patient) — post-mastectomy, post-hysterectomy, nephrectomy, amputation, colostomy/ileostomy, orchiectomy, etc. A region may be absent, altered, or reconstructed, and there may be new structures (neo-organs, stomas) that don’t exist on either base mesh.
Hard-coding more “models” doesn’t scale. Instead, model anatomy as a profile that layers region-level overrides + additions on top of a base mesh.
Core rule (non-negotiable)
Anatomy ≠ gender identity. This profile describes what tissue/organs are physically present for clinical care (dosing, screening, exam, imaging). It is decoupled from gender identity, pronouns, legal sex, and the “MTF/FTM” labels — those live in the demographic/identity record, never inferred from anatomy and never the other way around. The presets below are starting points a clinician edits, not assumptions applied from an identity field. (See also the platform’s inclusivity / patient-dignity stance.)
Data model
type RegionStatus = 'present' | 'absent' | 'altered' | 'reconstructed';
interface AnatomyRegionState {
regionId: string; // key in COORDINATE_SETS
status: RegionStatus;
/** SNOMED procedure/finding that explains the state (e.g. mastectomy 172043006). */
procedureSnomedCode?: string;
note?: string; // free text, e.g. "TRAM flap 2023"
}
interface AnatomyAddition {
/** New structure not on the base mesh — neo-organ, stoma, flap, expander. */
id: string;
label: string; labelTh?: string;
snomedCode?: string; // body-structure SCTID where one exists
/** Anchor: reuse an existing region position, or an explicit 3D point. */
anchorRegionId?: string;
position?: [number, number, number];
kind: 'neo-organ' | 'stoma' | 'reconstruction' | 'device';
}
interface AnatomyProfile {
baseModel: BodyModelId; // 'male' | 'female' (which mesh to render)
overrides: AnatomyRegionState[]; // change status of base regions
additions: AnatomyAddition[]; // add structures the base mesh lacks
}
The profile is per-patient (Supabase anatomy_profiles row keyed by patient, or an
encounter-scoped snapshot). It is read-only to the viewer.
Rendering contract (additive to BodyModelViewer)
BodyModelViewer gains an optional anatomyProfile?: AnatomyProfile prop. Resolution:
- Render the
baseModelmesh. - Start from
COORDINATE_SETS[baseModel]; applyoverrides:absent→ hide the region’s marker/overlay; if a diagnosis/device targets it, surface a “region absent” affordance rather than a silent drop.altered/reconstructed→ render the marker with a small status badge (e.g. ⚑) and expose theprocedureSnomedCode+ note in the popup.present→ unchanged.
- Append
additionsas extra regions (reuse the icon-overlay path; neo-organs/stomas get their own SCTID + label, grounded exactly like the existing region set).
No change to the grounding guarantee — every state references a real region id or a real SCTID; nothing is invented at render time.
Presets (clinician-editable starting points)
| Preset | Base | Overrides | Additions |
|---|---|---|---|
| Trans woman (MTF), post-op | male | testes absent (orchiectomy), prostate present* |
breast-L/R (augmentation), neovagina (vaginoplasty) |
| Trans man (FTM), post-op | female | breast-L/R absent/reconstructed (chest reconstruction), uterus absent (hyst), ovaries absent (oophorectomy) |
neophallus (phalloplasty/metoidioplasty) |
| Non-binary / partial | either | any subset of the above | any subset |
| Intersex | either | per individual | per individual |
| Post-mastectomy | any | breast absent (or reconstructed + implant/flap addition) |
optional reconstruction |
| Amputation | any | limb region(s) absent |
optional stump/prosthesis marker |
| Ostomy | any | — | stoma addition (colostomy/ileostomy/urostomy) |
* prostate is typically retained in MTF surgery — flagged because it remains a screening target; this is exactly why anatomy must be tracked independently of identity.
SNOMED anchors (look up exact active SCTIDs from the RF2 release at build time)
- Neo-organs/structures: neovagina, reconstructed breast, constructed phallus,
colostomy stoma, ileostomy stoma, urostomy stoma all have SNOMED body-structure or
morphologic concepts — resolve via the same
import-snomed-terminology.mjsflow used for the region pack (add codes toCODES, regenerateanatomy.seed.ts). - Procedure context: mastectomy, hysterectomy, oophorectomy, orchiectomy, vaginoplasty,
phalloplasty, amputation — SNOMED procedure concepts stored on
procedureSnomedCode.
(Do not hand-write SCTIDs — pull them from the release like every other region, so they’re guaranteed active.)
Why this fits the existing system
- The base-mesh choice reuses the existing
bodyModelregistry. - Overrides/additions reuse
COORDINATE_SETS+ the icon-overlay renderer + the grounding guard — no new rendering pipeline. - It is purely additive: a patient with no profile renders exactly as today.
Open questions for the implementing session
- Storage: dedicated
anatomy_profilestable vs an extension on the patient/encounter read model? (Leaning: its own table, encounter can snapshot.) - Authoring UI: a small editor (toggle region status, add structures from a SNOMED picker) — likely a new admin/clinical surface.
- How absent regions interact with diagnosis/device tagging (block? warn? allow with a flag) — needs a clinical decision.
- Pediatric/teen meshes (scaffolded) get the same profile treatment once calibrated.