Athena enrichment

suMEDS can fill missing code metadata from an OHDSI Athena vocabulary downloaded as CSV files or loaded into PostgreSQL. Enrichment is optional and uses no patient-level fields.

Resolved fields

For each valid Athena match, suMEDS adds or fills:

Column Type Source
description string concept.concept_name
parent_codes list[string] all valid ancestors through the root (default)
child_codes list[string] valid descendants up to child_depth (optional)
sibling_codes list[string] valid direct children of every ancestor, excluding self (optional)
vocabulary_id string concept.vocabulary_id
concept_id int64 numeric OMOP concept identifier
concept_code string vocabulary-local code
domain_id string OMOP domain
standard_concept string S, C, or null

Existing relationship lists are merged without duplicates. Parent references using VOCABULARY/CONCEPT_CODE are normalized to VOCABULARY//CONCEPT_CODE. By default, a parent reference used to resolve the matched concept itself is removed; retain it with --no-exclude-self-parent-code or exclude_self_parent_code: false. Newly added codes must resolve to a valid row in the same Athena CONCEPT source. Invalid, missing, self-referential, and cyclic hierarchy rows are ignored. Unmatched concepts pass through unchanged. Please check the Athena search portal to confirm.

Parent expansion includes every positive min_levels_of_separation through the root and is enabled by default. Disable it with --no-parent-codes or parent_codes: false. Child and sibling expansion are opt-in. Children include transitive descendants through child_depth (default 3); siblings are the direct children of each valid ancestor, excluding the matched concept itself.

Code parsing

The original MEDS code is never changed. These layouts are supported:

VOCABULARY//CODE//...
VOCABULARY//VOCABULARY_VERSION//CODE

Three-part codes are ambiguous. suMEDS first looks up the second component, which preserves codes ending in markers such as //start and //end. It tries the third component only when the second component has no valid match. If neither matches, the first non-null existing parent_codes reference is tried as VOCABULARY/CODE or VOCABULARY//CODE. This supports metadata such as the MIMIC-IV demo, whose event codes are local while parent references identify Athena concepts. Malformed and unmatched codes pass through unchanged.

Local Athena files

Point to an Athena download directory containing at least the original tab-delimited CONCEPT.csv and CONCEPT_ANCESTOR.csv files:

uv run suMEDS /data/MEDS -o summary.parquet \
  --athena-csv /vocabularies/athena \
  --child-codes --child-depth 3 --sibling-codes

Polars projects only the required columns. Header matching is case-insensitive.

PostgreSQL

The PostgreSQL source requires psql on PATH and concept plus concept_ancestor in the connection's search path. Requests are sent in one CSV COPY batch rather than one query per code.

PGPASSWORD=... uv run suMEDS /data/MEDS -o summary.parquet \
  --athena-postgres postgresql://postgres@127.0.0.1:5432/omop \
  --child-codes --child-depth 3 --sibling-codes

psql inherits the current process environment. Supply the password as the standard libpq variable PGPASSWORD, or use PGPASSFILE/~/.pgpass. POSTGRES_PASSWORD configures the Docker container but is not read by psql. The demo notebook safely copies an existing POSTGRES_PASSWORD environment value to PGPASSWORD without displaying it. Restart the notebook kernel if the environment was changed after Jupyter started.

Standalone enrichment

Enrich an existing MEDS metadata table or suMEDS output without scanning event data:

uv run suMEDS-enrich /data/MEDS/metadata/codes.parquet \
  -o codes-enriched.parquet --athena-csv /vocabularies/athena

Parquet, CSV, JSON, JSONL, and NDJSON are supported. Input and output must be different paths, and the destination is replaced atomically. The CLI displays a tqdm phase-progress bar followed by row and unique-code match counts plus before/after coverage for descriptions, relationship codes, concept IDs, vocabulary, domain, and standard-concept fields.

Interactive demo

Open examples/athena_enrichment_demo.ipynb for a hands-on walkthrough using individual codes and the included MIMIC-IV demo metadata. The notebook supports either source and keeps the full summary step opt-in.

Example output

$ uv run suMEDS-enrich summary.parquet --athena-postgres postgresql://postgres@127.0.0.1:5432/omop -o summary_enriched.parquet
Calculating coverage: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████| 4/4 [02:38<00:00, 39.59s/stage]

Enrichment report
  Rows processed:             118,088
  Unique codes:               118,088
  Athena matches added:      65,358 rows, 65,358 unique codes
  Rows with concept ID:       65,367 (55.4%)
  Rows without Athena match:  52,721 (44.6%)
  Metadata coverage (present before -> after):
    Descriptions                     9 ->     65,367 (55.4%) (+65,358 filled)
    Parent-code lists                9 ->     61,021 (51.7%) (+61,012 filled)
    Vocabulary IDs                   9 ->     65,367 (55.4%) (+65,358 filled)
    OMOP concept IDs                 9 ->     65,367 (55.4%) (+65,358 filled)
    Concept codes                    0 ->     65,366 (55.4%) (+65,366 filled)
    Domains                          0 ->     65,366 (55.4%) (+65,366 filled)
    Standard-concept flags           0 ->     61,169 (51.8%) (+61,169 filled)

Privacy ordering

Integrated summary enrichment runs after rare-code masking. PostgreSQL receives only released code strings and the configured rare label; masked source codes are not queried or restored. Standalone enrichment has no privacy filtering and should be applied only to an already approved table when release controls are required.