Condition
→
condition_occurrence
implemented
primary
One FHIR Condition maps to one condition_occurrence row. Status filtering drops entered-in-error, refuted, and inactive/resolved conditions. Onset is resolved via a priority chain (onsetDateTime > onsetPeriod.start > recordedDate); conditions with no resolvable start date are skipped. Category drives type_concept_id (problem-list-item vs encounter-diagnosis). Domain routing is not implemented -- all conditions go to condition_occurrence regardless of OMOP vocabulary domain_id.
Conversion profile
omop-condition
A FHIR instance converts to condition_occurrence iff it validates against this profile.
| Path | Card | Type | Binding / Fixed | Comment |
|---|---|---|---|---|
| Condition.verificationStatus | fhir/condition-ver-statusrequired | |||
| Condition.code | 1..*MS | omop-condition-codesrequired | ||
| Condition.subject | 1..* | Reference | ||
| Condition.onset[x] | 1..*MS | Required for condition_occurrence.condition_start_date. |
ViewDefinition (Stage 1 flattener)
omop-condition-condition-occurrence
16 columns · resource Condition
| column name | FHIRPath | type |
|---|---|---|
| id | Condition.id | id |
| code_snomed | Condition.code.coding.where(system='http://snomed.info/sct').first().code | code |
| code_icd10cm | Condition.code.coding.where(system='http://hl7.org/fhir/sid/icd-10-cm').first().code | code |
| code_icd9cm | Condition.code.coding.where(system='http://hl7.org/fhir/sid/icd-9-cm').first().code | code |
| code_icd10 | Condition.code.coding.where(system='http://hl7.org/fhir/sid/icd-10').first().code | code |
| code_text | Condition.code.text | string |
| subject_id | Condition.subject | Reference(Patient) |
| condition_start_date | Condition.onset[x] | dateTime | Period | Age | Range | string |
| condition_start_datetime | Condition.onset[x] | dateTime | Period |
| condition_end_date | Condition.abatement[x] | dateTime | Period |
| condition_end_datetime | Condition.abatement[x] | dateTime | Period |
| condition_status | Condition.clinicalStatus | CodeableConcept |
| condition_status_text | Condition.clinicalStatus.coding[0].code | code |
| stop_reason | Condition.abatementString | string |
| performer_id | Condition.asserter | Reference(Practitioner) |
| encounter_id | Condition.encounter | Reference(Encounter) |
Condition: clinicalStatus in (active, recurrence, relapse, absent) AND verificationStatus not in (entered-in-error, refuted) AND onset or recordedDate resolvable
Implementation:
src/mapper/condition.tsFields (16)
-
condition_occurrence_id←Condition.idinteger · idPKrequiredSurrogate key generated from Condition.id. Hash/sequence/lookup. HL7 IG FML has this commented out (line 11). -
person_id←Condition.subjectinteger · Reference(Patient)FK→PERSONrequiredResolve Patient reference to integer. Defaults to 0 if unresolved; omoponfhir throws FHIRException. -
condition_concept_id←Condition.codeinteger · CodeableConceptFK→CONCEPTrequiredtransform:vocabularyLookup(selectBestCoding(code, [SNOMED, ICD10CM, ICD10, CPT4]))Vocabulary lookup (SNOMED/ICD-10 -> OMOP standard concept). Placeholder: 0. Production requires Athena vocabulary tables.4 sources ▾
-
Service-backed vocabulary lookup via ConceptService (fhirCode2OmopConcept)
-
Database-backed LookupCode() — iterates all code.Coding entries, creates one row per coding
- FhirToCdm(csharp) refs/refs/FhirToCdm/FhirToCdmMappings.cs:263-265
-
FindOmopConcepts with full domain routing (Condition/Observation/Procedure/Measurement) and ICD-10-GM + ORPHA support
- ETL-German-FHIR-Core(java) refs/refs/ETL-German-FHIR-Core/src/main/java/org/miracum/etl/fhirtoomop/mapper/ConditionMapper.java:921-988
-
DB-backed FhirToOmopConceptMapper; hardcoded type concept 32020 (non-standard)
-
-
condition_start_date←Condition.onset[x]date · dateTime | Period | Age | Range | stringrequiredtransform:coalesce(onsetDateTime, onsetPeriod.start, recordedDate)Falls back through onsetDateTime > onsetPeriod.start > recordedDate. Condition skipped if none resolvable.4 sources ▾
-
Full chain: onsetDateTime, onsetPeriod, recordedDate, and onsetAge/onsetRange via ResourceOnset helper
- ETL-German-FHIR-Core(java) refs/refs/ETL-German-FHIR-Core/src/main/java/org/miracum/etl/fhirtoomop/mapper/ConditionMapper.java:737-773
-
onsetDateTime and onsetPeriod; uses 9999-12-31 sentinel when onset missing instead of skipping
-
Both recordedDate (line 22) and onset:dateTime (line 23) mapped; last match wins in FML (no explicit priority)
- fhir-omop-ig(fml) refs/refs/fhir-omop-ig/input/maps/condition.fml:22-23
-
onsetDateTime cast only; crashes if absent (no fallback)
- FhirToCdm(csharp) refs/refs/FhirToCdm/FhirToCdmMappings.cs:265-265
-
-
condition_start_datetime←Condition.onset[x]datetime · dateTime | Periodtransform:coalesce(onsetDateTime, onsetPeriod.start, recordedDate)Full ISO datetime when available. omoponfhir uses 9999-12-31 when missing (line 542). -
condition_end_date←Condition.abatement[x]date · dateTime | Periodtransform:coalesce(abatementDateTime, abatementPeriod.end)FhirToCdm falls back to visit end date when absent (line 301-302). No other implementation does this. -
condition_end_datetime←Condition.abatement[x]datetime · dateTime | Periodtransform:coalesce(abatementDateTime, abatementPeriod.end) -
condition_type_concept_id←Condition.categoryinteger · CodeableConceptFK→CONCEPTrequiredmap:condition_typeproblem-list-item->32840, encounter-diagnosis->32817, default->32817. Implementations vary widely.4 sources ▾
-
Category-aware bidirectional mapping via OmopConceptMapping (problem-list-item vs encounter-diagnosis)
-
Hardcoded 32817 for all conditions regardless of category
- FhirToCdm(csharp) refs/refs/FhirToCdm/FhirToCdmMappings.cs:274-274
- ETL-German-FHIR-Core(java) refs/refs/ETL-German-FHIR-Core/src/main/java/org/miracum/etl/fhirtoomop/mapper/ConditionMapper.java:1102-1102
-
Non-standard hardcoded 32020 (EHR encounter diagnosis) — different concept from standard 32817
-
Different concept IDs per category: encounter-diagnosis→32817, problem-list-item→32818, health-concern→32819
- fhir-x-omop(python) refs/refs/fhir-x-omop/fhir_x_omop/to_omop/condition_occurrence.py:23-27
-
-
condition_status_concept_id←Condition.clinicalStatusinteger · CodeableConceptFK→CONCEPTmap:condition_statusactive/recurrence/relapse->32902, absent->0. ETL-German uses diagnostic confidence instead.3 sources ▾
-
clinicalStatus code passed through directly without concept translation
- fhir-omop-ig(fml) refs/refs/fhir-omop-ig/input/maps/condition.fml:30-34
-
ICD-10-GM diagnostic confidence extension mapped here instead of clinicalStatus (ETL-German specific)
-
Different status concept IDs: active→32893, resolved→32897, inactive→32896
- fhir-x-omop(python) refs/refs/fhir-x-omop/fhir_x_omop/to_omop/condition_occurrence.py:28-32
-
-
condition_status_source_value←Condition.clinicalStatus.coding[0].codevarchar(50) · codeVerbatim clinical status code. ETL-German stores diagnostic confidence code here. -
stop_reason←Condition.abatementStringvarchar(20) · stringtransform:substring(abatementString, 0, 20)Free-text reason for resolution. Truncated to 20 chars. fhir-x-omop uses note[0].text instead.2 sources ▾
-
abatementString (free text) truncated to 20 chars
-
note[0].text used instead of abatementString
- fhir-x-omop(python) refs/refs/fhir-x-omop/fhir_x_omop/to_omop/condition_occurrence.py:33-33
-
-
provider_id←Condition.asserter | Condition.recorderinteger · Reference(Practitioner)FK→PROVIDERtransform:coalesce(resolveRef(asserter), resolveRef(recorder))Asserter preferred; recorder fallback. omoponfhir uses asserter only. fhir-x-omop uses recorder only.3 sources ▾
-
asserter only (no recorder fallback)
-
recorder only (no asserter consideration)
- fhir-x-omop(python) refs/refs/fhir-x-omop/fhir_x_omop/to_omop/condition_occurrence.py:34-34
-
Not mapped (provider_id left null)
- FhirToCdm(csharp) refs/refs/FhirToCdm/FhirToCdmMappings.cs:252-310
- ETL-German-FHIR-Core(java) refs/refs/ETL-German-FHIR-Core/src/main/java/org/miracum/etl/fhirtoomop/mapper/ConditionMapper.java:1079-1116
-
-
visit_occurrence_id←Condition.encounterinteger · Reference(Encounter)FK→VISIT_OCCURRENCEResolve Encounter reference. FhirToCdm also sets visit_detail_id from encounter. -
visit_detail_id← constant integerFK→VISIT_DETAIL=nullNot mapped. FhirToCdm and fhir-x-omop set it to same as visit_occurrence_id. -
condition_source_value←Condition.codevarchar(50) · CodeableConcepttransform:selectBestCoding(code, [SNOMED, ICD10CM, ICD10, CPT4]).codeBest code by vocabulary priority. ETL-German stores raw ICD code. -
condition_source_concept_id←Condition.codeinteger · CodeableConceptFK→CONCEPT=0Source vocabulary concept. Requires vocabulary DB. Placeholder: 0.
Vocabularies
condition_type
| Source | Display | Concept ID | Concept Name |
|---|---|---|---|
| problem-list-item | Problem List Item | 32840 | Problem list from EHR |
| encounter-diagnosis | Encounter Diagnosis | 32817 | EHR |
| health-concern | Health Concern | 32817 | EHR |
| (absent) | Absent / other | 32817 | EHR |
condition_status
| Source | Display | Concept ID | Concept Name |
|---|---|---|---|
| active | Active | 32902 | Active condition |
| recurrence | Recurrence | 32902 | Active condition |
| relapse | Relapse | 32902 | Active condition |
| (absent) | Absent | 0 | Unknown |
condition_code_vocabularies
| Source | Display | Concept ID | Concept Name |
|---|---|---|---|
| http://snomed.info/sct | SNOMED CT | - | SNOMED |
| http://hl7.org/fhir/sid/icd-10-cm | ICD-10-CM | - | ICD10CM |
| http://hl7.org/fhir/sid/icd-10 | ICD-10 | - | ICD10 |
| http://fhir.de/CodeSystem/bfarm/icd-10-gm | ICD-10-GM | - | ICD10GM |
| http://www.ama-assn.org/go/cpt | CPT-4 | - | CPT4 |
| http://www.orpha.net | ORPHA | - | ORPHA |
Edge Cases
Missing onset[x] + missing recordedDate
Skip -- no valid start date. condition_start_date is required in OMOP.
onsetAge (e.g. 45 years)
Not mapped by most. Requires patient birthDate for calculation.
onsetPeriod with start and end
start -> condition_start_date, end -> condition_end_date.
Multiple code.coding entries (e.g. ICD-10 + SNOMED)
Select best coding by vocabulary priority (SNOMED > ICD-10-CM > ICD-10 > CPT-4).
severity present
Dropped by most implementations.
bodySite present
Dropped by most implementations.
stage present
Dropped by most implementations.
verificationStatus = provisional
Mapped. Some implementations skip non-confirmed; this project maps provisional.
verificationStatus = entered-in-error
Skip always. Universal consensus across implementations.
SNOMED code with domain_id != Condition
Should route to observation/procedure/measurement. Requires vocabulary DB.
abatementString longer than 20 chars
Truncated to fit stop_reason varchar(20).
Missing Condition.code
Skip -- no concept to map.
Missing Condition.subject
Skip or error.
ICD-10-GM primary + secondary codes
Split into separate condition_occurrence rows.
Diagnostic confidence (ICD-10-GM extension)
Maps to condition_status_concept_id.
Reference Implementations
- fhir-omop-ig(fml) refs/refs/fhir-omop-ig/input/maps/condition.fml — Normative, minimal (48 lines). Maps code, onset, recordedDate, category, clinicalStatus. No status filtering.
- fhir-omop-ig(fsh) refs/refs/fhir-omop-ig/input/fsh/ConditionOccurrence.fsh — Logical model (23 lines).
- omoponfhir(java) refs/refs/omoponfhir-omopv5-r4-mapping/src/main/java/edu/gatech/chai/omoponfhir/omopv5/r4/mapping/OmopCondition.java:1-620 — Bidirectional. Most complete. ICD-10/SNOMED via ConceptService. Category-based type concepts. Uses 9999-12-31 sentinel for missing onset.
- FhirToCdm(csharp) refs/refs/FhirToCdm/FhirToCdmMappings.cs — CreateConditionOccurrence() line 252. Minimal: onsetDateTime only, hardcoded type concept 32817. Iterates all code.Coding entries.
- ETL-German-FHIR-Core(java) refs/refs/ETL-German-FHIR-Core/src/main/java/org/miracum/etl/fhirtoomop/mapper/ConditionMapper.java:1-1654 — Most comprehensive F->O. Domain routing, ICD-10-GM, severity/bodySite/stage as observations, multi-coding multi-row, Orpha codes, incremental updates.
- NACHC-fhir-to-omop(java) refs/refs/NACHC-fhir-to-omop/src/main/java/org/nachc/tools/fhirtoomop/omop/person/factory/builder/condition/OmopConditionOccurrenceBuilder.java:1-66 — Simple mapper. DB-backed concept lookup. Uses non-standard type concept 32020.
- fhir-x-omop(python) refs/refs/fhir-x-omop/fhir_x_omop/to_omop/condition_occurrence.py:1-46 — Declarative Python mapper F->O. Different status concept IDs (32893/32897/32896) and type concept IDs (32817/32818/32819).
- fhir-x-omop(python) refs/refs/fhir-x-omop/fhir_x_omop/to_fhir/condition.py:1-72 — O->F direction.