Skip to content

Local extensions to the status vocabulary

openmed.clinical.status_vocab ships deterministic cue tables for three SDOH domains: substance use, employment, and living situation. Adding a fourth domain does not require bundling new terminology into the package or changing its defaults. load_status_vocab(path) loads and validates any vocabulary from an explicit local path, so a contributor-owned domain can live entirely outside the repository.

This page walks through examples/custom_status_vocabulary.py, which adds a synthetic "mobility" domain and demonstrates the fail-closed checks a local vocabulary should pass before it is trusted.

Load a local vocabulary

from openmed.clinical import load_status_vocab

payload = load_status_vocab("custom_status_vocab.yaml")
mobility = payload["vocabularies"]["mobility"]

load_status_vocab enforces the same structure as the bundled tables: a schema_version, provenance.source and an advisory provenance.disclaimer mentioning "clinical decision", a defaults.unknown_status, and for each vocabulary a priority order, a statuses mapping with cues, a current_statuses list, and axis_overrides for negated and historical_current. A vocabulary missing its advisory disclaimer is rejected:

try:
    load_status_vocab("invalid_provenance.yaml")
except ValueError as error:
    print(error)  # "... requires an advisory disclaimer"

Guard against duplicate cues

Matching resolves ties by priority order, so a cue accidentally listed under two statuses would be ambiguous. load_status_vocab rejects cues that collide after the same Unicode, case, and whitespace normalization used for matching. The error identifies the conflicting statuses and cue positions without echoing the cue text:

load_status_vocab("duplicate_cues.yaml")
# ValueError: mobility vocabulary lists one normalized cue under two statuses

Normalize against the local domain

The bundled normalize_substance_status, normalize_employment_status, and normalize_living_status helpers always load the packaged vocabulary, so they cannot target a locally extended domain. The example re-implements the same deterministic, case-insensitive substring match documented on openmed.clinical.status_vocab as normalize_mobility_status(), so the pattern is copy-pasteable without depending on that module's private helpers:

from examples.custom_status_vocabulary import normalize_mobility_status

normalize_mobility_status("uses a cane", mobility)  # "assisted"
normalize_mobility_status("uses a cane", mobility, negated=True)  # "never"
normalize_mobility_status(
    "walks independently", mobility, temporality="historical"
)  # "former"

Scope

This example is offline and synthetic: every cue is a generic English phrase authored for this walkthrough, not a bundled or restricted terminology. It demonstrates local validation and normalization only; it does not recommend a clinical decision from a normalized status, and it does not change any package default. See tests/unit/examples/test_custom_status_vocabulary.py for the runnable checks behind this page.