Skip to content

Experiencer Refinement

The ConText experiencer axis records who a clinical finding is about. A finding under a Family History heading has a family section prior. Local cues refine that prior because a single sentence can switch subject ("the patient's mother has diabetes", "the organ donor was CMV-positive").

openmed.clinical.experiencer refines the experiencer of a governing span using local subject cues, distinguishing three subjects:

Value Subject Example cues
patient the patient (default) none cued
family a relative of the patient mother, father, sibling, maternal, family history, FHx
other a non-patient, non-relative subject donor, roommate, partner, coworker

This axis is a hard safety boundary for coreference-style aggregation: a family-member or other-subject finding must not be merged into the patient record.

Refining assertions

refine_experiencer(spans, context_result, text=...) accepts clinical spans and an existing ClinicalContextResult or ClinicalAssertion, then returns RefinedExperiencerAssertion records. Each record preserves the incoming temporality, certainty, and negation axes while attaching the refined experiencer to the assertion.

from openmed.clinical import ClinicalAssertion, refine_experiencer

text = "The patient's mother has type 2 diabetes"
span = {"start": text.index("diabetes"), "end": len(text), "label": "CONDITION"}
context = ClinicalAssertion(temporality="recent", certainty="certain")

[result] = refine_experiencer([span], context, text=text)
result.assertion.experiencer
# 'family'
result.assignment.cue
# 'mother'

The lower-level resolve_experiencer(text, span, *, section_experiencer=None) API returns only the assignment provenance for one span.

Resolving a span

from openmed.clinical import resolve_experiencer

text = "The patient's mother has type 2 diabetes"
span = {"start": text.index("diabetes"), "end": len(text), "label": "CONDITION"}

result = resolve_experiencer(text, span)
# ExperiencerAssignment(experiencer='family', cue='mother',
#                       cue_offset=(14, 20), source='cue')

resolve_experiencer(text, span, *, section_experiencer=None) returns an ExperiencerAssignment:

Field Meaning
experiencer patient, family, or other.
cue The matched subject cue (lowercased), or None when defaulted.
cue_offset Half-open offsets of the cue in the source text, or None.
source cue, section, or default -- how the value was decided.

Resolution order

  1. Cue -- the subject cue nearest the span, within the span's clause, wins. Resolution is scoped by sentence punctuation (., !, ?, ;) and the contrastive subject-switch markers but, however, and whereas, so a subject named in a previous clause does not leak across the boundary. Coordinating and and or deliberately remain inside the same scope because they commonly join findings about one subject. On a tie the more specific other subject wins over family.
  2. Section prior -- when no cue is found and a section_experiencer is supplied (for example family under a Family History heading), it is used.
  3. Default -- otherwise the span is attributed to the patient.

An explicit cue always overrides the section prior, so "the patient's father also has hypertension" resolves to family even inside a patient-default section.

German source text

Pass language="de" (or a German locale such as de-DE) to resolve_experiencer or refine_experiencer. assert_context(..., language="de") forwards that language to local subject refinement. Whole-word cues include Mutter, Vater, Großmutter, and Spender. An explicit Patient/Patientin subject nearer the finding can override the family prior. German contrastive conjunctions and line boundaries end cue scope; a word such as Muttersprachlerin does not match Mutter.

Supply sections=detect_sections(text, language="de") to assert_context to retain section boundaries and context-source provenance. German medication headers (Medikation, Aktuelle Medikation, Entlassmedikation) end family history scope. German normalization also recognizes whole frequency phrases such as zweimal täglich; it does not infer a schedule from an ambiguous phrase.

These additions have synthetic regression coverage. They do not establish German clinical qualification. Language packs beyond English and German still use the existing English local-subject rules in this resolver.

Notes

Resolution is deterministic and offline. Experiencer refinement is a cue-based heuristic and is not a substitute for clinician review; validate before any clinical use.