DiagnosticReport measurement documented

When a DiagnosticReport's LOINC code resolves to an OMOP concept with domain_id = Measurement, the report itself produces one or more measurement rows. Each conclusionCode entry generates a separate row. This is independent of the Observation results referenced by DiagnosticReport.result[], which are mapped by the Observation mapper. Lab panel codes (e.g. 24323-8 Comprehensive metabolic panel) are the primary Measurement-domain codes.

A FHIR instance converts to measurement iff it validates against this profile.
Routing key DiagnosticReport.code ∈ omop-measurement-codes (OMOP domain Measurement)
Path Card Type Binding / Fixed Comment
DiagnosticReport.status fhir/diagnostic-report-statusrequired OMOP measurement requires a finalized report.
DiagnosticReport.code 1..*MS omop-measurement-codesrequired
DiagnosticReport.subject 1..* Reference Required for measurement.person_id.
DiagnosticReport.effective[x] 1..*MS Required for measurement.measurement_date / measurement_datetime.
ViewDefinition (Stage 1 flattener) omop-diagnosticreport-measurement
11 columns · resource DiagnosticReport
column name FHIRPath type
id DiagnosticReport.id id
code_loinc DiagnosticReport.code.coding.where(system='http://loinc.org').first().code code
code_snomed DiagnosticReport.code.coding.where(system='http://snomed.info/sct').first().code code
code_text DiagnosticReport.code.text string
subject_id DiagnosticReport.subject Reference(Patient)
measurement_date DiagnosticReport.effective[x] dateTime|Period
measurement_datetime DiagnosticReport.effective[x] dateTime|Period
value_as DiagnosticReport.conclusionCode CodeableConcept
performer_id DiagnosticReport.performer[0] Reference(Practitioner)
encounter_id DiagnosticReport.encounter Reference(Encounter)
value_text DiagnosticReport.conclusionCode.coding[0].code code
Condition: DiagnosticReport.code (LOINC) resolves to OMOP concept with domain_id = Measurement

Fields (23)

  • measurement_id integer · id
    PKrequired
    Surrogate key. Hash/sequence of DiagnosticReport.id + conclusionCode index. Must be unique across all measurement sources.
  • person_id DiagnosticReport.subject integer · Reference(Patient)
    FK→PERSONrequired
    Resolve Patient/{id} reference to integer person_id. Skip row if unresolvable.
  • measurement_concept_id DiagnosticReport.code integer · CodeableConcept
    FK→CONCEPTrequired
    LOINC code looked up in OMOP vocabulary. Must have domain_id = Measurement. Use first LOINC coding found. 0 if concept not found.
  • measurement_date DiagnosticReport.effective[x] date · dateTime|Period
    required
    Date component of effectiveDateTime, or effectivePeriod.start. Skip row if absent (ETL-German behavior).
    2 sources ▾
  • measurement_datetime DiagnosticReport.effective[x] datetime · dateTime|Period
    Full timestamp from effectiveDateTime or effectivePeriod.start.
  • measurement_time varchar(10)
    Legacy field. Leave null.
  • measurement_type_concept_id DiagnosticReport.category integer · CodeableConcept
    FK→CONCEPTrequiredmap:diagnostic_report_category
    ETL-German maps category via SOURCE_VOCABULARY_ID_DIAGNOSTIC_REPORT_CATEGORY custom concept map. Common defaults: 32817 (EHR) or 32856 (Lab result).
    3 sources ▾
  • operator_concept_id integer
    FK→CONCEPT
    ETL-German maps SNOMED conclusion interpretation codes to operator. Typically null for DiagnosticReport.
  • value_as_number float
    DiagnosticReport conclusions are coded, not numeric. Leave null.
  • value_as_concept_id DiagnosticReport.conclusionCode integer · CodeableConcept
    FK→CONCEPT
    SNOMED conclusion code resolved to OMOP concept. ETL-German currently stores this in measurement_source_concept_id instead.
    2 sources ▾
  • unit_concept_id integer
    FK→CONCEPT
    No units on DiagnosticReport-level measurements. Leave null.
  • range_low float
    No reference ranges on DiagnosticReport. Leave null.
  • range_high float
    No reference ranges on DiagnosticReport. Leave null.
  • provider_id DiagnosticReport.performer[0] integer · Reference(Practitioner)
    FK→PROVIDER
    First performer reference resolved to provider_id. Also consider resultsInterpreter[0].
  • visit_occurrence_id DiagnosticReport.encounter integer · Reference(Encounter)
    FK→VISIT_OCCURRENCE
    Resolve Encounter/{id} to visit_occurrence_id.
  • visit_detail_id integer
    FK→VISIT_DETAIL
    Leave null unless visit details are modeled.
  • measurement_source_value DiagnosticReport.conclusionCode.coding[0].code varchar(50) · code
    Verbatim SNOMED code from conclusionCode. ETL-German uses this field.
  • measurement_source_concept_id DiagnosticReport.conclusionCode integer · CodeableConcept
    FK→CONCEPT
    SNOMED conclusionCode resolved to OMOP concept ID. ETL-German stores the SNOMED concept here (line 339).
    2 sources ▾
  • unit_source_value varchar(50)
    No units. Leave null.
  • unit_source_concept_id integer
    FK→CONCEPT
    No units. Leave null.
  • value_source_value DiagnosticReport.conclusionCode.coding[0].code varchar(50) · code
    Verbatim SNOMED code. ETL-German stores this (line 344).
  • measurement_event_id integer
    Can link back to a related OMOP record if needed. Leave null.
  • meas_event_field_concept_id integer
    FK→CONCEPT
    Leave null.

Vocabularies

report_code_loinc

Source Display Concept ID Concept Name
24323-8 Comprehensive metabolic panel 3004410 Comprehensive metabolic panel
24357-6 Urinalysis macro panel 3002385 Urinalysis macro panel
58410-2 CBC panel (blood) 3016502 CBC panel (blood)

diagnostic_report_category

Source Display Concept ID Concept Name
LAB Laboratory studies 32856 Lab result
RAD Radiology 32817 EHR
PAT Pathology 32817 EHR
MB Microbiology 32817 EHR
(absent) No category 32817 EHR

Edge Cases

No effectiveDateTime or effectivePeriod
ETL-German skips the resource entirely. Alternative: fall back to issued timestamp.
Status is registered, preliminary, cancelled, entered-in-error, or unknown
Reject. Accept only final, amended, corrected, appended. Preliminary results may change and should not be committed to the CDM.
No conclusionCode
ETL-German skips the resource. Without a conclusion, there is no value to store. Only the referenced Observations produce rows.
Multiple conclusionCode entries
Each code produces a separate measurement row. The measurement_concept_id (report LOINC) is the same across all rows; only measurement_source_concept_id and value_source_value differ.
Composite SNOMED in conclusionCode (e.g. 118247008:{363713009=373068000})
ETL-German splits composite expressions: base code before : maps to measurement_source_concept_id; attributes after :{ are parsed for interpretation codes mapped to operator_concept_id.
SNOMED codes joined with + (conjunction)
ETL-German splits on + and creates one row per component code.
No category
ETL-German skips the resource. Alternative: default to measurement_type_concept_id = 32817 (EHR).
LOINC code resolves to Observation or Procedure domain
Route to observation or procedure_occurrence table instead.
Report with result[] but no code or conclusionCode
No report-level row produced. The Observations in result[] are still mapped independently.
subject references Group (not Patient)
Not supported. OMOP requires a single person_id. Skip the resource.
Incremental updates (same DiagnosticReport reprocessed)
ETL-German deletes existing OMOP rows by fhirLogicalId or fhirIdentifier before re-inserting.

Reference Implementations