Observation
— maps to 2 OMOP tables| OMOP Table | Status | Mapped | |
|---|---|---|---|
|
measurement
primary
Labs and vitals with numeric/coded results. Domain routing based on Observation.category: laboratory and vital-signs route here. Observations with components (e.g. blood pressure) are expanded -- each component produces its own measurement row.
|
implemented | 20 fields | detail → |
|
observation
Qualitative clinical findings: social history, lifestyle factors, survey responses, activity data. One FHIR Observation (or one component) maps to one OMOP observation row. Also receives data from AllergyIntolerance and FamilyMemberHistory.
|
implemented | 21 fields | detail → |
Observation → OMOP Mapping
FHIR Observation is the most versatile clinical resource — it covers lab results, vital signs, social history, surveys, activity data, and more. In OMOP, these split into two tables based on the nature of the data: measurement (quantitative lab/vital results) and observation (qualitative findings, social history, surveys).
Target OMOP Tables
| OMOP Table | Purpose | Required? |
|---|---|---|
measurement | Labs and vitals with numeric/coded results | Conditional — when category is laboratory or vital-signs |
observation | Social history, surveys, activity, other clinical findings | Conditional — when category is social-history, survey, or activity |
Mapping Strategy
-
Domain routing. The central design decision. FHIR uses a single
Observationresource for everything; OMOP separates measurements from observations. Routing is based onObservation.category:laboratory,vital-signs→ measurementsocial-history,survey,activity→ observation- No category → measurement (default, since labs are most common)
A vocabulary-aware implementation would instead look up the OMOP
domain_idof the observation's LOINC/SNOMED code. The category-based approach is a pragmatic approximation that works for most data. -
Status filtering. Only
final,amended, andcorrectedobservations produce rows.preliminary,registered,cancelled,entered-in-error, andunknownare dropped. This is stricter than some implementations (omoponfhir maps everything in bidirectional mode). -
Component expansion. Observations with
component[](e.g., blood pressure with systolic + diastolic) are expanded: each component produces its own OMOP row. The parent observation's metadata (person, encounter, date, provider) is inherited; each component uses its own code and value. Component rows get suffixed IDs ({id}-comp-0,{id}-comp-1). -
Value polymorphism. FHIR
value[x]can be Quantity, CodeableConcept, string, boolean, integer, Range, Ratio, SampledData, time, dateTime, or Period. OMOP measurement handles Quantity (→value_as_number+unit_source_value) and CodeableConcept (→value_as_concept_id). OMOP observation additionally hasvalue_as_string. Other types are captured invalue_source_valueas a verbatim string. -
Operator mapping.
valueQuantity.comparator(<,<=,>=,>) maps tooperator_concept_idin measurement. This captures results like "<10 mg/dL". -
Date requirement.
effectiveDateTimeis required — OMOP date fields are NOT NULL.effectivePeriodis supported viaperiod.startfallback.
Reference Implementations
- fhir-omop-ig (HL7) — Two FML files:
refs/refs/fhir-omop-ig/input/maps/Measurement.fml(53 lines) andrefs/refs/fhir-omop-ig/input/maps/Observation.fml(52 lines). Separate profiles for each target table. - omoponfhir (Georgia Tech, Java) —
refs/refs/omoponfhir-omopv5-r4-mapping/src/main/java/edu/gatech/chai/omoponfhir/omopv5/r4/mapping/OmopObservation.java(264 lines). Bidirectional. Category-based routing. Component support. - FhirToCdm (OHDSI, C#) —
refs/refs/FhirToCdm/FhirToCdmMappings.csCreateMeasurement(). Measurement only; no observation routing. - ETL-German-FHIR-Core (Java) —
refs/refs/ETL-German-FHIR-Core/src/main/java/org/miracum/etl/fhirtoomop/mapper/ObservationMapper.java. Domain-based routing via vocabulary lookup. LOINC and SNOMED. Reference range handling. - fhir-to-omop-demo (jq) —
refs/refs/fhir-to-omop-demo/demo/translate/map/Observation.jq. - fhir-x-omop (Python) —
refs/refs/fhir-x-omop/fhir_x_omop/to_omop/measurement.pyandobservation.py.
Status in This Project
Implemented: src/mapper/observation.ts (194 lines). Category-based routing, component expansion, operator mapping, value polymorphism (Quantity, String, CodeableConcept), reference ranges, interpretation → qualifier. Does not handle effectivePeriod, specimen references, method, bodySite, or vocabulary-based domain routing.