This page is part of the Vulcan FHIR to OMOP FHIR Implementation Guide (v1.0.0-ballot: INFORMATIVE 1 Ballot 1) based on FHIR (HL7® FHIR® Standard) v5.0.0. No current official version has been published yet. For a full list of available versions, see the Directory of published versions
Official URL: http://hl7.org/fhir/uv/omop/StructureMap/MeasurementMap | Version: 1.0.0-ballot | |||
Standards status: Informative | Maturity Level: 1 | Computable Name: MeasurementMap |
This mapping maps FHIR Observation instances that are considered measurements to OMOP Measurement Table objects. Currently, this is done by considering the category code and mapping 'vital-signs' and 'laboratory' Observations.
FHIR Observation Categories serve as organizational tools within EHR systems, providing essential context for clinical decision support and data retrieval operations. The categories in the FHIR observation-category value set encompass a spectrum of clinical observations, including Social History, Vital Signs, Laboratory, Imaging, Procedure, Survey, Exam, Therapy, and Activity. Considering the OMOP CDM semantically-based framework, FHIR Observations with observation-categories such as Laboratory and Vital Signs may actually map to OMOP's Measurement domain or other domain tables. As such, FHIR Observations may or may not align naturally with OMOP's existing Observation domain architecture, where the data are normalized across the OMOP CDM through Standardized concepts established in each domain. (See: OMOP Domain Assignment Logic for more information.)
OMOP's domain structure inherently categorizes data elements into logical groupings, with the Measurement domain handling quantitative clinical data and the Observation domain managing qualitative findings and contextual information. This existing structure effectively represents many FHIR categories without requiring explicit category mapping. At a high-level, mapping rules can be aligned with OMOP domains as reprsented in the table below However, the nuanced distinction between clinical observations and patient-reported data, or between routine clinical measurements and lifestyle assessments, may not be adequately preserved through domain assignment alone.
FHIR Observation Type | Target OMOP Table | Rationale | Examples |
---|---|---|---|
Laboratory and Vital Signs | Measurement | Accommodates numeric values and supports standardization processes; leverages structured fields for quantitative clinical data requiring units and reference ranges | Lab test results, blood pressure readings, temperature measurements |
Qualitative Observations | Observation | Appropriate for non-numeric components including survey responses, clinical notes, and general observations lacking strict measurement units | Patient-reported outcomes, clinical assessments, survey responses |
Condition-Related Observations | Condition | Suitable when observations align closely with diagnoses or clinical conditions representing documented medical states | Diagnostic findings, clinical impressions, documented conditions |
Keep in mind that the domain-based guidelines outlined above serve as one of many approaches to consider, with recognition that specific edge cases will require detailed concept-based mapping decisions during implementation.
FHIR Observation resources support multiple value types (Quantity, CodeableConcept, string, Boolean), requiring careful consideration for OMOP field assignments. The following mapping strategy addresses this complexity through type-specific field assignments.
FHIR Value Type | Target OMOP Field | Primary Table | Description | Examples |
---|---|---|---|---|
Quantity (Numeric) | value_as_number |
Measurement | Preserves quantitative nature of clinical measurements while maintaining data integrity | Laboratory test results, vital sign measurements, dosage amounts |
CodeableConcept | value_as_concept_id |
Measurement/Observation | Ensures semantic consistency and enables standardized clinical queries using standardized terminologies | SNOMED CT codes, LOINC codes, ICD-10 codes |
String/Text | value_as_string |
Measurement/Observation | Maintains descriptive clinical information that cannot be effectively represented through numeric or coded values | Patient-reported descriptions, free-text observations, clinical notes |
Boolean | value_as_concept_id |
Measurement/Observation | Typically mapped to standardized Yes/No concepts in OMOP vocabulary | Presence/absence indicators, binary clinical assessments |
Implementation teams should note that FHIR's expressiveness often exceeds OMOP's structural capacity, requiring careful evaluation of value types that may need adaptation or exclusion if they cannot be effectively represented in the target OMOP model.
FHIR Observation units are embedded within the Quantity type structure, typically utilizing standardized systems such as UCUM (Unified Code for Units of Measure). The mapping process must preserve unit information through OMOP's unit_concept_id
field in the Measurement table.
While UCUM provides a robust grammar-based approach for constructing unit expressions and supports machine-to-machine communication through consistent representation (using "mg" rather than variations like "milligram" or "milligramme"), implementation teams must exercise caution when working with UCUM units in clinical data warehouses. UCUM's flexibility in allowing the creation of new units through its grammar system, while beneficial for specialized domains, can introduce analytical challenges by generating separate groups of records with nuanced units if not properly managed. Care should be taken to normalize units of measure assigned to each result type within the datastore to support analytic consistency. For example, while UCUM may allow both "mg/dL" and "mg/100mL" as valid representations of the same conceptual unit, data normalization processes should require standardized unit assignment to ensure accurate cross-patient comparisons and longitudinal analysis.
/// url = 'http://hl7.org/fhir/uv/omop/StructureMap/MeasurementMap' /// name = 'MeasurementMap' /// title = 'Mapping Observation resource to Measurement OMOP Domain' /// status = 'draft' uses "http://hl7.org/fhir/StructureDefinition/Observation" alias Observation as source uses "http://hl7.org/fhir/uv/omop/StructureDefinition/Measurement" alias MeasureTable as target group Measures(source src : Observation, target tgt : MeasureTable) { src where ('vital-signs' | 'laboratory').supersetOf(Observation.category.coding.code) then { src.code as s -> tgt then { s.coding as sc -> tgt then { sc.code as a -> tgt.measurement_concept_id = a; }; }; // src.id as id -> tgt.measurement_id = cast(id, "integer"); src.effective : dateTime as edt -> tgt.measurement_datetime = edt, tgt.measurement_date = cast(edt, 'date'); // src.subject as s -> tgt then { src.effective : instant as einst -> tgt.measurement_datetime = cast(einst, 'dateTime'), tgt.measurement_date = cast(einst, 'date'); src.effective : Period as s -> tgt then { s.start as eps -> tgt.measurement_datetime = cast(eps, 'dateTime'), tgt.measurement_date = cast(eps, 'date'); }; src.issued as s where (src.issued.toDate != src.effectiveDateTime) -> tgt.measurement_source_value = cast(s, 'string'); src.value : Quantity as s -> tgt then { s.value as a -> tgt.value_as_number = a; s.unit as b -> tgt.unit_concept_id = b; }; // src.performer as s -> tgt then { src.value : CodeableConcept as s -> tgt then { s.coding as sc -> tgt then { sc.code as a -> tgt.value_as_concept_id = a; }; }; src.value : string as b -> tgt.value_source_value = b; src.interpretation as c -> tgt.value_as_concept_id = c; src.note as d -> tgt.measurement_source_value = d; } "OnlyMeasures"; }