Skip to content

feat(meds): OMOP → MEDS conversion for ML-native EHR encoders - #1

Merged
bschilder merged 1 commit into
mainfrom
feat/meds-conversion
Apr 21, 2026
Merged

feat(meds): OMOP → MEDS conversion for ML-native EHR encoders#1
bschilder merged 1 commit into
mainfrom
feat/meds-conversion

Conversation

@bschilder

Copy link
Copy Markdown
Owner

Summary

Adds synthlab.meds, a thin wrapper over the community meds_etl package so SynthLab output (Synthea → OMOP CDM) can feed directly into MEDS-native foundation models like SMB-v1 and MOTOR.

Pipeline

SyntheaRunner.run()                   # synthlab.synthea (existing)
    → Synthea CSVs
convert_synthea_to_omop(...)          # synthlab.synthea (existing)
    → OMOP v5.4 CSVs
convert_omop_to_meds(...)             # synthlab.meds (new in this PR)
    → MEDS parquet shards
load_meds_events(meds_dir)            # synthlab.meds (new)
    → polars DataFrame ready for SMB-v1 / MOTOR / ...

Public API

  • MedsConvertConfig dataclass — mirrors the meds_etl_omop CLI surface (backend, num_shards, num_proc, overwrite)
  • convert_omop_to_meds(config) — invokes meds_etl_omop as a subprocess, surfaces stderr on failure, refuses to clobber existing output unless asked
  • load_meds_events(meds_dir, subject_ids=None) — polars-native reader for the sharded parquet, sorted by (subject_id, time); cohort filter pushed into the scan
  • get_meds_cache_dir() / get_meds_info() / print_meds_info() — matches the pattern every other synthlab submodule uses

Install

pip install synthlab[meds] (new optional extra; pulls meds_etl>=0.3 + meds>=0.4).

Infra

  • New tests/ directory + test_meds.py — 15 tests covering cache-dir, info dict, config validation, all error paths (ImportError, FileNotFoundError, FileExistsError), shard reading, subject filtering, and meds_etl_omop console-script registration
  • New .github/workflows/test.yml — runs pytest on every PR + push to main (previously no CI existed)
  • pyproject.toml gets new [meds] and [tests] extras (rolled into [all])
  • README gets a new "MEDS conversion" section with a quickstart snippet

Test plan

  • pytest tests/ passes locally (15/15) on Python 3.11
  • import synthlab.meds clean in fresh env
  • convert_omop_to_meds raises clear errors for missing meds_etl, missing OMOP dir, and existing output dir without overwrite=True
  • load_meds_events round-trips a synthetic parquet shard + respects subject_ids filter
  • GHA CI green on this PR

Motivation

Enables downstream work in smb-protopheno where each cohort's synthetic EHR needs to be encoded by SMB-v1 as part of a joint genomics + EHR model. Without this, every consumer of SynthLab's output has to re-implement the OMOP → MEDS ETL.

🤖 Generated with Claude Code

Adds synthlab.meds, a thin wrapper over the community meds_etl
package (github.com/Medical-Event-Data-Standard/meds_etl). This lets
SynthLab output feed directly into MEDS-native foundation models
such as SMB-v1 (huggingface.co/standardmodelbio) and MOTOR.

API:
- MedsConvertConfig dataclass (omop_dir, meds_dir, backend, shards,
  proc, overwrite) — matches meds_etl_omop's CLI surface.
- convert_omop_to_meds(config): runs meds_etl_omop as subprocess,
  surfaces stderr on failure, refuses to overwrite unless asked.
- load_meds_events(meds_dir, subject_ids=None): polars-native reader
  for the sharded parquet output, sorted by (subject_id, time).
- get_meds_cache_dir / get_meds_info / print_meds_info — mirrors
  the pattern every other synthlab submodule uses.

Pipeline:
  SyntheaRunner.run() -> Synthea CSVs
  convert_synthea_to_omop() -> OMOP v5.4
  convert_omop_to_meds() -> MEDS parquet
  (downstream: SMB-v1 / MOTOR encoder)

Install: `pip install synthlab[meds]` (adds meds_etl + meds pins).

Infra:
- New tests/ dir + test_meds.py (15 tests, all passing on py3.11):
  cache-dir, info dict, config validation, error paths, shard
  reading, subject filtering, meds_etl entry-point registration.
- New .github/workflows/test.yml runs pytest on every PR + push.
- pyproject.toml gains [meds] + [tests] optional extras and
  pulls them into [all].
- README gets a "MEDS conversion" section with quickstart.

No breaking changes to existing APIs.
@bschilder
bschilder merged commit 672691b into main Apr 21, 2026
1 check passed
@bschilder
bschilder deleted the feat/meds-conversion branch April 21, 2026 20:29
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