Immunization
— maps to 1 OMOP table| OMOP Table | Status | Mapped | |
|---|---|---|---|
|
drug_exposure
primary
One FHIR Immunization maps to one drug_exposure row. Immunizations are point-in-time events: start_date = end_date, no days_supply or refills. Records are distinguished from other drug exposures by drug_concept_id belonging to the CVX vocabulary. Only completed immunizations are mapped; entered-in-error and not-done are skipped.
|
documented | 23 fields | detail → |
Immunization → OMOP Mapping
FHIR Immunization records vaccine administrations. In OMOP, immunizations are stored in drug_exposure -- there is no dedicated immunization table. Immunization records are distinguished from other drug exposures by having a drug_concept_id that maps to the CVX (vaccine) vocabulary. Some implementations also recognize SNOMED and ATC vaccine codes.
Target OMOP Tables
| OMOP Table | Purpose | Required? |
|---|---|---|
drug_exposure | One row per vaccination event | Yes |
observation | Only when concept domain is "Observation" instead of "Drug" (ETL-German routing) | Conditional |
Mapping Strategy
-
Single-event model. Immunizations are point-in-time events:
drug_exposure_start_date = drug_exposure_end_date. No duration, nodays_supply, norefills. -
Vaccine code vocabulary.
Immunization.vaccineCodeprimarily uses CVX codes in US implementations. European implementations (ETL-German) use ATC and SNOMED. The vaccine code must be resolved to an OMOP standard concept. CVX concepts are loaded into the OMOP vocabulary tables via Athena. When multiplevaccineCode.coding[]entries are present, implementations pick the first recognized vocabulary (ETL-German prefers ATC over SNOMED; omoponfhir takes the first match). -
Status filtering. Only
completedimmunizations should be mapped.entered-in-errorrecords must be skipped.not-donerecords are skipped by most implementations (ETL-German, FhirToCdm), though omoponfhir writes them with astop_reason. TheoccurrenceStringvariant (instead ofoccurrenceDateTime) cannot be mapped becausedrug_exposure_start_dateis NOT NULL. -
Type concept divergence. Implementations disagree on
drug_type_concept_id: 38000179 (Physician administered drug) vs 32817 (EHR) vs 32818 (EHR administration record). The OMOP community is migrating toward 32817 (EHR). WhenImmunization.primarySource = false, consider 44787730 (Patient Self-Reported). -
Lot number.
Immunization.lotNumber→drug_exposure.lot_number. This is one of the few FHIR resources that maps tolot_number-- it is primarily designed for vaccine tracking and adverse event investigation. -
Route.
Immunization.route→route_concept_id. Common vaccine routes: intramuscular (IM → 4302612), subcutaneous (SC → 4302357), oral (PO → 4132161), nasal inhalation (NASINHL → 4262914). -
Domain routing. ETL-German checks the resolved concept's
domain_id. If the concept maps to the "Observation" domain (uncommon for CVX, possible for certain SNOMED codes), the record is routed to theobservationtable instead ofdrug_exposure. -
Reference resolution. Three references must be resolved:
patient→person_id(required -- skip record if unresolvable),encounter→visit_occurrence_id(optional -- null if unresolvable),performer[0].actor→provider_id(optional). The HL7 IG FML comments out all three reference resolutions as TODOs.
Reference Implementations
- fhir-omop-ig (HL7) -- Normative IG; FML at
refs/refs/fhir-omop-ig/input/maps/ImmunizationMap.fml(54 lines). Maps vaccineCode, occurrence, doseQuantity, route, lotNumber. Comments out person_id, encounter, and performer. Status: draft. - omoponfhir (Georgia Tech, Java) -- Bidirectional;
refs/refs/omoponfhir-v54-r4/omoponfhir-omopv5-r4-mapping/src/main/java/edu/gatech/chai/omoponfhir/omopv5/r4/mapping/OmopImmunization.java(641 lines). Most complete field coverage: CVX vocabulary filter, lot number, route, dose quantity, notes→sig, status/stop_reason, performer→provider_id. Uses 38000179 (Physician administered) as type concept. Status: stale (2022). - ETL-German-FHIR-Core (OHDSI, Java) --
refs/refs/ETL-German-FHIR-Core/src/main/java/org/miracum/etl/fhirtoomop/mapper/ImmunizationMapper.java(771 lines). ATC/SNOMED vaccine codes (German MII profiles). Domain routing (Drug vs Observation). Date-aware concept lookup. SNOMED compound code splitting. No lot_number or performer mapping. Uses 32817 (EHR) as type concept. Status: maintained. - FhirToCdm (OHDSI, C#) --
refs/refs/FhirToCdm/FhirToCdmMappings.csCreateDrugExposure()lines 376-404. Minimal mapping: resolves person_id, looks up vaccine code, sets type=32817, links encounter. No lot_number, route, dose, or performer. Status: low activity. - mends-on-fhir (Whistle, OMOP→FHIR) --
refs/refs/mends-on-fhir/whistle-mappings/synthea/whistle-functions/Drug_Exposure.wstllines 250-349. Reverse direction. Routes CVX drug_exposures to FHIR Immunization (line 15-16). Maps lot_number, route, dose, status from stop_reason. Status: maintained. - fhir-x-omop (Python, OMOP→FHIR) --
refs/refs/fhir-x-omop/fhir_x_omop/to_fhir/immunization.py(73 lines). Reverse direction. Hardcoded route code mapping (IM, SC, PO, NASINHL). Maps lot_number, dose, provider. Status: early WIP.
Status in This Project
Not yet implemented. No src/mapper/immunization.ts exists. No Immunization type definition in src/types/fhir.ts. Implementation should add an Immunization interface to the FHIR types and create the mapper following the patterns established by existing mappers.