Lab results in clinical text arrive as a value, a unit, and a reference range
("Sodium 132 mmol/L (135–145)"). To act on them you need a structured
abnormal flag — is 132 low, normal, high, or critical? OpenMed's
openmed.clinical lab helpers parse the reference range deterministically and
derive the flag, honoring any explicit flag the originating lab already supplied.
The helpers are unit-agnostic by design: they compare numbers within a stated
range and never convert units, so a mmol/L value is never silently compared
against a mg/dL range.
extracting-clinical-entities surfaces lab/measurement entities and you
need to classify each as low / normal / high / critical.<5, >=10, 0.5 - 1.2.H, L, C, HH) and want it honored over
a derived comparison.from openmed.clinical import (
parse_reference_range, derive_abnormal_flag, LAB_FLAG_ADVISORY,
)
# Closed range
rng = parse_reference_range("135-145")
# -> {"low": 135.0, "high": 145.0, "low_inclusive": True, "high_inclusive": True}
derive_abnormal_flag(132, rng) # "low"
derive_abnormal_flag(140, "135-145") # "normal" (raw range string accepted)
derive_abnormal_flag(150, "135 to 145") # "high"
# One-sided bounds
derive_abnormal_flag(7, parse_reference_range("<5")) # "high" (above the cap)
derive_abnormal_flag(3, parse_reference_range(">=10")) # "low"
# Honor the lab's own explicit flag (takes precedence over derived comparison)
derive_abnormal_flag(132, "135-145", explicit_flag="C") # "critical"
derive_abnormal_flag(132, "135-145", explicit_flag="HH") # "critical"
# Unparseable / non-numeric inputs fail safe rather than guessing
derive_abnormal_flag("pending", "135-145") # "unknown"
derive_abnormal_flag(132, "see report") # "unknown"
print(LAB_FLAG_ADVISORY) # surface this disclaimer with derived flags
AbnormalFlag is one of "low" | "normal" | "high" | "critical" | "unknown".
ReferenceRange is a typed mapping of low, high, low_inclusive,
high_inclusive.
parse_reference_range. It handles closed
ranges ("135-145", "0.5 - 1.2", "135 to 145", en/em dashes) and
one-sided bounds ("<5", "<=5", ">10", ">=10"). Contradictory or
unparseable ranges return empty bounds rather than a guess — by design.derive_abnormal_flag(value, range, explicit_flag=).
Resolution order: an explicit lab flag wins first (H/HIGH, L/LOW,
C/CRIT/CRITICAL, HH/LL → critical, N/NORMAL); an unknown explicit flag
returns "unknown" instead of being silently ignored. With no explicit flag,
it compares the numeric value against the parsed bounds, respecting inclusive
vs. exclusive edges."unknown" explicitly. Non-numeric values, empty/unparseable
ranges, or unrecognized explicit flags yield "unknown". Treat it as
"needs review," not "normal."LAB_FLAG_ADVISORY wherever derived flags
are shown — derived flags are heuristic and do not replace the originating
laboratory's own diagnostic flagging.extracting-clinical-entities: analyze_text lab/measurement
entities give you the value text, unit, and often the reference range; this
skill turns them into structured flags. Parse the numeric value out of the
entity surface before calling derive_abnormal_flag.from openmed.clinical import parse_reference_range, derive_abnormal_flag, ReferenceRange, AbnormalFlag, LAB_FLAG_ADVISORY.reconciling-problem-lists / FHIR grounding: a critical/high/low
flag becomes a FHIR Observation.interpretation code (HL7 v3
ObservationInterpretation: H, L, HH, LL, N). Ground the LOINC code and
UCUM unit out-of-process; OpenMed emits the flag, not the terminology binding."<5" makes 5 the high bound exclusive;
a value of exactly 5 flags high. parse_reference_range records
high_inclusive=False for < and True for <= — respect it."critical" comes from the lab's explicit flag (C, HH, LL); the
helpers do not infer critical thresholds beyond the reference range."unknown" from derive_abnormal_flag, not "normal". Don't treat unknown as
in-range.LAB_FLAG_ADVISORY.referenceRange and interpretation:
https://hl7.org/fhir/R4/observation.html