Patient
→
observation_period
documented
Observation period defines spans during which a person is observable. Not a direct field-level mapping from Patient — derived from event data availability. Most implementations either skip this table or emit a placeholder row at person-creation time.
Conversion profile
omop-patient-observation-period
A FHIR instance converts to observation_period iff it validates against this profile.
| Path | Card | Type | Binding / Fixed | Comment |
|---|---|---|---|---|
| Patient.id | 1..* | Required to derive person_id (FK observation_period.person_id). | ||
| Patient.active | MS | Inactive patients may still have historical observation_period rows; not a hard gate. |
ViewDefinition (Stage 1 flattener)
omop-patient-observation-period
2 columns · resource Patient
| column name | FHIRPath | type |
|---|---|---|
| id | Patient.id | id |
| subject_id | Patient.id | id |
Condition: Derived per-person from data availability, not directly from Patient fields
Fields (5)
-
observation_period_id← — integerPKrequiredGenerated primary key (auto-increment or deterministic hash) -
person_id←Patient.idinteger · idFK→PERSONrequiredForeign key to person table, derived from Patient.id -
observation_period_start_date← — daterequiredtransform:min(event_date) across all OMOP clinical tables for this person, or fixed start (e.g. 1900-01-01), or registration dateDerived: earliest event date across all OMOP tables for the person; not directly from a Patient field2 sources ▾
-
Fixed constant 1900-01-01 written at person-creation time (Strategy A — incorrect for production)
-
min(event_date) across all clinical tables computed in post-processing (Strategy B)
- FhirToCdm(csharp) refs/refs/FhirToCdm/CdmPersonBuilder.cs:463-475 — BuildObservationPeriods() with gap merging
- ETL-German-FHIR-Core(sql) refs/refs/ETL-German-FHIR-Core/src/main/resources/post_processing/post_process_observation_period.sql
-
-
observation_period_end_date← — daterequiredtransform:max(event_date) across all OMOP clinical tables for this person, or fixed end, or min(today, Patient.deceasedDateTime)Derived: latest event date, or min(current_date, death_date) if deceased2 sources ▾
-
Fixed constant 2100-01-01 written at person-creation time (Strategy A — incorrect for production)
-
max(event_date) across clinical tables, with optional gap-merging into multiple periods (Strategy B)
- FhirToCdm(csharp) refs/refs/FhirToCdm/CdmPersonBuilder.cs:463-475 — BuildObservationPeriods() configurable gap parameter
- ETL-German-FHIR-Core(sql) refs/refs/ETL-German-FHIR-Core/src/main/resources/post_processing/post_process_observation_period.sql — Caps at death_date when person is deceased
-
-
period_type_concept_id← constant integerFK→CONCEPTrequiredmap:period_type=4481472444814724 = 'Period covering healthcare encounters' (NACHC default)2 sources ▾
-
Constant 44814724 ('Period covering healthcare encounters') hardcoded at person-creation
-
Configurable — concept_id chosen per pipeline; ETL-German derives from SQL without explicit concept_id constant
- FhirToCdm(csharp) refs/refs/FhirToCdm/CdmPersonBuilder.cs:463-475
- ETL-German-FHIR-Core(sql) refs/refs/ETL-German-FHIR-Core/src/main/resources/post_processing/post_process_observation_period.sql
-
Vocabularies
period_type
| Source | Display | Concept ID | Concept Name |
|---|---|---|---|
| 44814724 | Period covering healthcare encounters | 44814724 | Period covering healthcare encounters |
| 44814723 | Period while enrolled in insurance | 44814723 | Period while enrolled in insurance |
| 44814725 | Period inferred by algorithm | 44814725 | Period inferred by algorithm |
| 32817 | EHR | 32817 | EHR |
Edge Cases
Person has zero events
Skip the row (Strategy B) or use fixed window (Strategy A). Strategy B is preferred for production use.
Person is deceased
observation_period_end_date = min(latest_event, death_date). Do not extend past death.
Multiple disjoint observation windows
OMOP supports multiple rows per person. Use a gap parameter (e.g. 30 days) to merge adjacent periods or leave as separate rows.
Incremental loads
Re-derive end dates after each batch; rewrite affected observation_period rows for persons with new events.
Strategy A (fixed 1900-2100) is incorrect for production
Makes cohort definitions meaningless because every person appears observable for 200 years. Use Strategy B (min/max over events) for any analytic use.
omoponfhir, fhir-to-omop-demo, and fhir-x-omop skip this table
Cohort tooling treats these persons as having zero observable time, effectively excluding them from all OHDSI analyses.
Reference Implementations
- NACHC-fhir-to-omop(java) refs/refs/NACHC-fhir-to-omop/src/main/java/org/nachc/tools/fhirtoomop/omop/write/singlepatient/WriteOmopPersonToDatabase.java — Fixed window 1900-01-01 to 2100-01-01, lines 69-82
- FhirToCdm(csharp) refs/refs/FhirToCdm/CdmPersonBuilder.cs — BuildObservationPeriods() with gap merging, lines 463-475
- ETL-German-FHIR-Core(sql) refs/refs/ETL-German-FHIR-Core/src/main/resources/post_processing/post_process_observation_period.sql — SQL post-processing step that derives observation_period from all loaded event tables