Patient Timelines¶
OMOP Alchemy includes a lightweight timeline layer that projects OMOP CDM ORM objects into a unified, time-ordered event stream per patient.
It is primarily intended for feature construction and exploratory analysis — not for production query pipelines where raw SQLAlchemy queries are more appropriate.
Core concepts¶
EventTime¶
A canonical temporal representation. Every clinical event has a start datetime; an end
datetime is optional. The kind property returns "point" or "interval".
EventValue¶
The value associated with a clinical event — numeric, concept, string, or none.
EventMapping¶
Declares which ORM fields supply the concept, start/end datetimes, and value for a
particular CDM table. Subclasses of ClinicalEvent set _mapping to an EventMapping
instance at class level.
The ClinicalEvent mixin¶
ClinicalEvent is a mixin that adds timeline behaviour to any CDM ORM class. It reads
_mapping to implement event_time, event_value, event_metadata, to_dict, and
to_json.
Concrete event classes¶
Three CDM tables are pre-wired with EventMappings:
| Class | CDM table | Concept field | Value fields |
|---|---|---|---|
Condition_Event |
condition_occurrence |
condition_concept_id |
— |
Measurement_Event |
measurement |
measurement_concept_id |
value_as_number, value_as_concept_id, value_as_string |
Drug_Exposure_Event |
drug_exposure |
drug_concept_id |
quantity |
Bases: Condition_Occurrence, ClinicalEvent
Bases: ClinicalEvent, Measurement
Bases: Drug_Exposure, ClinicalEvent
Person_Timeline¶
Extends the Person ORM class with .events and .timeline properties. Requires an
active SQLAlchemy session (i.e. the object must have been loaded from a session, not
constructed in memory).
Usage example¶
from sqlalchemy.orm import Session
from omop_alchemy.cdm.handlers.timeline import Person_Timeline
with Session(engine) as session:
person = session.get(Person_Timeline, 42)
for event in person.timeline: # sorted by event_time.start
print(event)
print(event.to_dict())
Extending to new tables¶
To add a new CDM table to the timeline, subclass both ClinicalEvent and the target ORM
class and set _mapping:
from omop_alchemy.cdm.handlers.timeline.event_timeline import ClinicalEvent, EventMapping
from omop_alchemy.cdm.model.clinical import Procedure_Occurrence
class Procedure_Event(Procedure_Occurrence, ClinicalEvent):
_mapping = EventMapping(
concept_field="procedure_concept_id",
start_date_field="procedure_date",
start_datetime_field="procedure_datetime",
)