ccda_to_omop.visit_reconciliation module
Visit_reconciliation.py
This module contains functions for linking domain rows to visits as well as functions to differentiate visit_occurrence from visit_detail.
Main entry points are: - assign_visit_occurrence_ids_to_events() - assign_visit_detail_ids_to_events() - reclassify_nested_visit_occurrences_as_detail()
This code processes visit data to create a hierarchical structure where inpatient parent visits (<= 1 year duration) are kept in visit_occurrence and their nested child visits are moved to visit_detail.
Process: 1. Identify inpatient parent visits with duration <= 1 year 2. Find visits temporally nested within each parent 3. Create visit_detail records for nested children 4. Return updated visit_occurrence (parents + standalone) and new visit_detail list
- ccda_to_omop.visit_reconciliation.assign_visit_detail_ids_to_events(data_dict: dict[str, list[dict[str, None | str | float | int | int32 | int64 | datetime | date] | None] | None])[source]
visit_detail FK reconciliation: Match clinical domain events to visit_detail records.
This assigns visit_detail_id to events that occur during nested visits. Events must already have visit_occurrence_id set (from assign_visit_occurrence_ids_to_events).
For events that fall within multiple nested visits, chooses the most specific (smallest duration) visit_detail.
- Parameters:
data_dict – Dictionary with config_name → list of records (omop_dict)
- ccda_to_omop.visit_reconciliation.assign_visit_occurrence_ids_to_events(data_dict: dict[str, list[dict[str, None | str | float | int | int32 | int64 | datetime | date] | None] | None])[source]
Assign visit_occurrence_id FKs to all clinical event records in data_dict.
Iterates over all configs in data_dict whose domain is one of Measurement, Observation, Condition, Procedure, Drug, or Device, and calls reconcile_visit_FK_with_specific_domain() to match each event to a visit.
Expects visit records to be under the
'Visit'config key (after visit hierarchy processing has merged Visit and Visit_encompassingEncounter). Removes the temporary__visit_candidateskey from all records after reconciliation is complete.- Parameters:
data_dict – Dict mapping config names to lists of record dicts, as returned by parse_doc().
- ccda_to_omop.visit_reconciliation.create_visit_detail_record(visit_dict: dict[str, None | str | float | int | int32 | int64 | datetime | date], top_level_parent_id: int64, immediate_parent_id: int64 | None = None) dict[str, None | str | float | int | int32 | int64 | datetime | date][source]
Convert a visit (visit_occurrence) record into visit_detail format.
- Parameters:
visit_dict – Visit record to convert
top_level_parent_id – The top-level visit_occurrence_id
immediate_parent_id – The immediate parent’s visit_detail_id (or None for Layer 2)
- Returns:
Dictionary in visit_detail format
- ccda_to_omop.visit_reconciliation.find_most_specific_parent(child_dict: dict[str, None | str | float | int | int32 | int64 | datetime | date], potential_parents: list[dict[str, None | str | float | int | int32 | int64 | datetime | date]]) int64 | None[source]
Find the most specific (shortest duration, most immediate) parent for a child visit.
When multiple parents overlap and contain a child, choose the parent with the shortest duration as it represents the most specific/immediate context.
However, if the child has multiple containing parents that are at the same hierarchy level (i.e., the parents don’t contain each other), returns None to avoid ambiguity. The child visit will remain at its current level.
- Parameters:
child_dict – Child visit record
potential_parents – List of potential parent visit records
- Returns:
No parent found
Multiple parents at the same hierarchy level exist (ambiguous)
- Return type:
visit_occurrence_id of the most specific parent, or None if
- ccda_to_omop.visit_reconciliation.get_visit_detail_duration(visit_detail_dict: dict[str, None | str | float | int | int32 | int64 | datetime | date]) float[source]
Calculate duration of a visit_detail in days.
- Parameters:
visit_detail_dict – Visit_detail record
- Returns:
Duration in days (float)
- ccda_to_omop.visit_reconciliation.get_visit_duration_days(visit_dict: dict[str, None | str | float | int | int32 | int64 | datetime | date]) float | None[source]
Calculate visit duration in days.
- Parameters:
visit_dict – Dictionary containing visit record
- Returns:
Duration in days, or None if dates are missing
- ccda_to_omop.visit_reconciliation.identify_inpatient_parents(visit_list: list[dict[str, None | str | float | int | int32 | int64 | datetime | date]]) list[dict[str, None | str | float | int | int32 | int64 | datetime | date]][source]
Identify inpatient parent visits that are meaningful and time-bounded.
Criteria: - visit_concept_id is in INPATIENT_CONCEPT_IDS - Duration between start and end is <= 1 year - Has valid start and end datetimes
- Parameters:
visit_list – List of visit record dictionaries
- Returns:
List containing only eligible inpatient parent visits
- ccda_to_omop.visit_reconciliation.is_temporally_contained(child_dict: dict[str, None | str | float | int | int32 | int64 | datetime | date], parent_dict: dict[str, None | str | float | int | int32 | int64 | datetime | date]) bool[source]
Check if child visit is temporally contained within parent visit.
- Parameters:
child_dict – Child visit record
parent_dict – Parent visit record
- Returns:
True if child is fully contained within parent timeframe
- ccda_to_omop.visit_reconciliation.reclassify_nested_visit_occurrences_as_detail(omop_dict: dict[str, list[dict[str, None | str | float | int | int32 | int64 | datetime | date]] | None]) dict[str, list[dict[str, None | str | float | int | int32 | int64 | datetime | date]] | None][source]
Main entry point for visit hierarchy processing. Merges visits from both ‘Visit’ and ‘Visit_encompassingEncounter’ configs, deduplicates them, processes hierarchy, and creates visit_detail records.
Strategy: 1. Collect visits from both configs 2. Deduplicate (keep ‘Visit’ when duplicate exists with ‘Visit_encompassingEncounter’) 3. Process merged list as unified hierarchy 4. Put results in ‘Visit’ config and create ‘VISITDETAIL_visit_occurrence’ config
- Parameters:
omop_dict – Dictionary of config_name → list of records
- Returns:
‘Visit’: top-level visit_occurrence records (merged from both configs)
’VISITDETAIL_visit_occurrence’: visit_detail records
’Visit_encompassingEncounter’: removed (merged into ‘Visit’)
- Return type:
Updated omop_dict with
- ccda_to_omop.visit_reconciliation.reconcile_visit_FK_with_specific_domain(domain: str, domain_dict: list[dict[str, None | str | float | int | int32 | int64 | datetime | date]] | None, visit_dict: list[dict[str, None | str | float | int | int32 | int64 | datetime | date]] | None)[source]
Assign visit_occurrence_id to each event record in a clinical domain.
Matches each event in domain_dict to a visit in visit_dict by checking whether the event’s date falls within the visit’s start/end window. If exactly one visit matches, its visit_occurrence_id is written into the event record. If zero or multiple visits match, a warning is logged and the field is left unset (or a
__visit_candidateskey is added for ambiguous cases).- Parameters:
domain – OMOP domain name (e.g.
'Measurement','Condition'). Must be a key in the module-leveldomain_datesconfig dict.domain_dict – List of clinical event record dicts to be matched.
visit_dict – List of visit_occurrence record dicts to match against.
- ccda_to_omop.visit_reconciliation.reconcile_visit_detail_FK_with_specific_domain(domain: str, domain_dict: list[dict[str, None | str | float | int | int32 | int64 | datetime | date]] | None, visit_detail_dict: list[dict[str, None | str | float | int | int32 | int64 | datetime | date]] | None)[source]
Match events to visit_detail records by temporal containment. Choose the most specific (smallest duration) matching visit_detail.
- Parameters:
domain – Domain name (e.g., ‘Measurement’, ‘Condition’)
domain_dict – List of event records to reconcile
visit_detail_dict – List of visit_detail records
- ccda_to_omop.visit_reconciliation.strip_tz(dt)[source]
Remove timezone info from a datetime, leaving date objects unchanged.
- Parameters:
dt – A datetime.datetime, datetime.date, or None value.
- Returns:
The same value with tzinfo removed if it was a timezone-aware datetime; otherwise the original value unchanged.