DiagnosticReport procedure_occurrence documented

When a DiagnosticReport's LOINC code resolves to an OMOP concept with domain_id = Procedure, the report produces one or more procedure_occurrence rows. This occurs primarily for imaging studies (radiology, nuclear medicine), pathology procedures, and certain clinical assessments whose LOINC codes are classified in the Procedure domain by the OMOP vocabulary. 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.

A FHIR instance converts to procedure_occurrence iff it validates against this profile.
Routing key DiagnosticReport.code ∈ omop-procedure-codes (OMOP domain Procedure)
Path Card Type Binding / Fixed Comment
DiagnosticReport.status fhir/diagnostic-report-statusrequired
DiagnosticReport.code 1..*MS omop-procedure-codesrequired
DiagnosticReport.subject 1..* Reference Required for procedure_occurrence.person_id.
DiagnosticReport.effective[x] 1..*MS Required for procedure_occurrence.procedure_date / procedure_datetime.
ViewDefinition (Stage 1 flattener) omop-diagnosticreport-procedure-occurrence
13 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_cpt DiagnosticReport.code.coding.where(system='http://www.ama-assn.org/go/cpt').first().code code
code_text DiagnosticReport.code.text string
subject_id DiagnosticReport.subject Reference(Patient)
procedure_date DiagnosticReport.effective[x] dateTime|Period
procedure_datetime DiagnosticReport.effective[x] dateTime|Period
procedure_end_date DiagnosticReport.effectivePeriod.end dateTime
procedure_end_datetime DiagnosticReport.effectivePeriod.end dateTime
modifier DiagnosticReport.conclusionCode Coding
performer_id DiagnosticReport.performer[0] Reference(Practitioner)
encounter_id DiagnosticReport.encounter Reference(Encounter)
Condition: DiagnosticReport.code (LOINC) resolves to OMOP concept with domain_id = Procedure

Fields (16)

  • procedure_occurrence_id integer · id
    PKrequired
    Surrogate key. Hash/sequence of DiagnosticReport.id + conclusionCode index. Must be unique across all procedure_occurrence sources.
  • person_id DiagnosticReport.subject integer · Reference(Patient)
    FK→PERSONrequired
    Resolve Patient/{id} reference to integer person_id. Skip row if unresolvable.
  • procedure_concept_id DiagnosticReport.code integer · CodeableConcept
    FK→CONCEPTrequired
    LOINC code looked up in OMOP vocabulary. Must have domain_id = Procedure. Use first LOINC coding found. 0 if concept not found. ETL-German uses loincCodingConcept.getConceptId() (line 274).
  • procedure_date DiagnosticReport.effective[x] date · dateTime|Period
    required
    Date component of effectiveDateTime, or effectivePeriod.start. Skip row if absent (ETL-German behavior).
  • procedure_datetime DiagnosticReport.effective[x] datetime · dateTime|Period
    Full timestamp from effectiveDateTime or effectivePeriod.start.
  • procedure_end_date DiagnosticReport.effectivePeriod.end date · dateTime
    End date from effectivePeriod.end. ETL-German does not set this field (only uses startDateTime). Leave null for effectiveDateTime.
  • procedure_end_datetime DiagnosticReport.effectivePeriod.end datetime · dateTime
    Full timestamp from effectivePeriod.end. ETL-German does not set this field.
  • procedure_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 (line 273). Common default: 32817 (EHR).
    2 sources ▾
  • modifier_concept_id DiagnosticReport.conclusionCode integer · Coding
    FK→CONCEPT
    ETL-German extracts interpretation codes from composite SNOMED expressions in conclusionCode (e.g. the value after = in 118247008:{363713009=373068000}) and resolves them to OMOP concepts (lines 286-297). Set only when conclusionCode contains a :{ composite expression. 0 if absent or unmapped.
    2 sources ▾
  • quantity integer
    DiagnosticReport has no quantity field. Leave null.
  • provider_id DiagnosticReport.performer[0] integer · Reference(Practitioner)
    FK→PROVIDER
    First performer reference resolved to provider_id. Also consider resultsInterpreter[0]. ETL-German does not map this field for DiagnosticReport procedure_occurrence rows (gap in implementation).
  • visit_occurrence_id DiagnosticReport.encounter integer · Reference(Encounter)
    FK→VISIT_OCCURRENCE
    Resolve Encounter/{id} to visit_occurrence_id. ETL-German sets this (line 272).
  • visit_detail_id integer
    FK→VISIT_DETAIL
    Leave null unless visit details are modeled.
  • procedure_source_value DiagnosticReport.conclusionCode.coding[0].code varchar(50) · code
    Verbatim SNOMED code from conclusionCode. ETL-German stores snomedCoding.getCode() (line 277).
    1 source ▾
  • procedure_source_concept_id DiagnosticReport.conclusionCode integer · CodeableConcept
    FK→CONCEPT
    SNOMED conclusionCode resolved to OMOP concept ID. ETL-German stores snomedConcept.getConceptId() (line 276).
    1 source ▾
  • modifier_source_value varchar(50)
    Verbatim interpretation code from composite SNOMED expression. ETL-German stores interpretationConcept.getConceptCode() (line 296). Only set when composite SNOMED expression is present.

Vocabularies

report_code_loinc

Source Display Concept ID Concept Name
24725-4 CT Head W contrast IV 3027018 CT Head W contrast IV
24566-1 XR Chest 2 Views 3003961 XR Chest 2 Views
24532-3 MRI Brain WO contrast 3048098 MRI Brain WO contrast
38269-7 US Abdomen 3042955 US Abdomen
24627-1 MR Heart 3044437 MR Heart
24610-7 XR Spine Lumbar AP+Lateral 3018893 XR Spine Lumbar AP+Lateral

diagnostic_report_category

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

Edge Cases

No effectiveDateTime or effectivePeriod
ETL-German skips the resource entirely. procedure_date is required in OMOP. Alternative: fall back to issued timestamp.
Status is registered, preliminary, cancelled, entered-in-error, or unknown
Reject. Accept only final, amended, corrected, appended.
No conclusionCode
ETL-German skips the resource. Without a conclusion, there is no SNOMED finding to store in procedure_source_concept_id. Only the referenced Observations produce rows.
Multiple conclusionCode entries
Each code produces a separate procedure_occurrence row. The procedure_concept_id (report LOINC) is the same across all rows; only procedure_source_concept_id and procedure_source_value differ.
Composite SNOMED in conclusionCode (e.g. 118247008:{363713009=373068000})
ETL-German splits composite expressions: base code before : maps to procedure_source_concept_id; attributes after :{ are parsed, and the interpretation code (value after =) is resolved to modifier_concept_id.
SNOMED codes joined with + (conjunction)
ETL-German splits on + and creates one row per component code. Each component is processed independently.
No category
ETL-German skips the resource. Alternative: default to procedure_type_concept_id = 32817 (EHR).
LOINC code resolves to Measurement or Observation domain
Route to measurement or observation table instead.
effectivePeriod with both start and end
ETL-German only uses startDateTime for procedure date/datetime. procedure_end_date and procedure_end_datetime are not populated. A complete implementation should use effectivePeriod.end for the end date fields.
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 from procedure_occurrence, measurement, and observation tables by fhirLogicalId or fhirIdentifier before re-inserting.
provider_id not populated by ETL-German
The ETL-German procedure builder does not set provider_id. A complete implementation should resolve performer[0] or resultsInterpreter[0] to a provider.

Reference Implementations