Summary
Implemented patient_story() in examples/leiomyosarcoma/story_generators.py to drive synthetic OMOP data generation from examples/leiomyosarcoma/leiomyosarcoma_patient.csv, a flat event log (person_id, event_datetime, days_after_diagnosis, event_type, event_name, concept_id, visit_occurrence_id) for a single leiomyosarcoma patient.
What was built
- Typed row dataclasses (
Person, ConditionOccurrence, VisitOccurrence, ProcedureOccurrence) mirroring each table's columns in orm.yaml, with a shared Row.to_row() that only emits explicitly-set fields — unset fields fall through to the table's normal row generator defaults.
- CSV loading:
_load_patient_events() reads the CSV once and groups rows by (source) person_id; patient_story() consumes one patient's events per call via a module-level iterator.
condition_occurrence: one row per CSV event with event_type == "Condition", concept_id → condition_concept_id.
visit_occurrence: one row per event_type == "Visit" event, concept_id → visit_concept_id.
procedure_occurrence: for each visit, procedures on the same days_after_diagnosis are matched and inserted with visit_occurrence_id set from the visit's actual (DB-assigned) FK, returned via the story generator's yield/send protocol.
Open design decisions / assumptions made
The CSV has no absolute dates and is missing several NOT NULL OMOP fields, so we filled gaps with fixed values pending review:
| Field |
Assumption |
condition_start_date / visit_start_date / procedure_date |
Derived as days_after_diagnosis offset from an anchor date of today (no real anchor diagnosis date available) |
visit_end_date |
Set equal to visit_start_date (treats all visits as single-day) |
condition_type_concept_id |
Hardcoded to 32840 |
visit_type_concept_id |
Hardcoded to 32817 |
procedure_type_concept_id |
Hardcoded to 32817 |
These should be revisited once real anchor dates / source type-concept mappings are available.
Depends on
concept is configured as vocabulary_table: true, so real OMOP concept_ids (e.g. 40482829 for Leiomyosarcoma) referenced by the story rely on make-vocab/create-vocab having been run against a source DB that actually contains those concepts. Not yet verified end-to-end against a live database.
Next steps
🤖 Generated with Claude Code
Summary
Implemented
patient_story()inexamples/leiomyosarcoma/story_generators.pyto drive synthetic OMOP data generation fromexamples/leiomyosarcoma/leiomyosarcoma_patient.csv, a flat event log (person_id, event_datetime, days_after_diagnosis, event_type, event_name, concept_id, visit_occurrence_id) for a single leiomyosarcoma patient.What was built
Person,ConditionOccurrence,VisitOccurrence,ProcedureOccurrence) mirroring each table's columns inorm.yaml, with a sharedRow.to_row()that only emits explicitly-set fields — unset fields fall through to the table's normal row generator defaults._load_patient_events()reads the CSV once and groups rows by (source)person_id;patient_story()consumes one patient's events per call via a module-level iterator.condition_occurrence: one row per CSV event withevent_type == "Condition",concept_id→condition_concept_id.visit_occurrence: one row perevent_type == "Visit"event,concept_id→visit_concept_id.procedure_occurrence: for each visit, procedures on the samedays_after_diagnosisare matched and inserted withvisit_occurrence_idset from the visit's actual (DB-assigned) FK, returned via the story generator'syield/sendprotocol.Open design decisions / assumptions made
The CSV has no absolute dates and is missing several NOT NULL OMOP fields, so we filled gaps with fixed values pending review:
condition_start_date/visit_start_date/procedure_datedays_after_diagnosisoffset from an anchor date of today (no real anchor diagnosis date available)visit_end_datevisit_start_date(treats all visits as single-day)condition_type_concept_id32840visit_type_concept_id32817procedure_type_concept_id32817These should be revisited once real anchor dates / source type-concept mappings are available.
Depends on
conceptis configured asvocabulary_table: true, so real OMOPconcept_ids (e.g.40482829for Leiomyosarcoma) referenced by the story rely onmake-vocab/create-vocabhaving been run against a source DB that actually contains those concepts. Not yet verified end-to-end against a live database.Next steps
create-vocab+create-dataagainst a real destination DB to validate the full FK chainpatient_story's docstring (death,observation_period,measurement,device_exposure,observation,specimen,drug_exposure) if needed for this dataset🤖 Generated with Claude Code