Skip to content

Medication Sig Parser

Medication sigs pack dose, dose-form, route, frequency, duration, and a PRN condition into terse strings ("1 tab PO BID x7 days", "take 2 puffs q4-6h PRN"). openmed.clinical.sig_parser turns them into a structured Sig, the value layer beneath medication grounding, reconciliation, and FHIR Dosage export.

Frequency and duration are not re-implemented here: the parser isolates those candidates and delegates to the shipped medication_sig.normalize_frequency and normalize_duration helpers, which own that lexicon. This module adds what they deliberately exclude -- dose, dose-form, route, and the PRN condition.

Parsing a sig

from openmed.clinical import parse_sig

parse_sig("1 tab PO BID x7 days")
# {'raw': '1 tab PO BID x7 days', 'dose': 1.0, 'unit': 'tablet',
#  'form': 'tablet', 'route': 'oral', 'frequency_per_day': 2.0,
#  'as_needed': False, 'condition': None, 'duration_days': 7, 'missing': []}

The Sig mapping has these fields:

Field Meaning
raw The input sig text.
dose The numeric dose amount, or None.
unit The dose unit (mg, mcg, ml, ...) or the form when the count is a form word.
form The controlled dose-form (tablet, capsule, puff, drop, ...) or None.
route The controlled route (oral, intravenous, subcutaneous, ...) or None.
frequency_per_day Scheduled rate per day, from normalize_frequency, or None.
frequency_period The normalized frequency period when available (4 for q4h).
frequency_period_unit The normalized period unit (h, d, or wk) when available.
as_needed True when the sig is PRN.
condition The PRN reason ("PRN pain" -> pain), or None.
duration_days Duration in days, from normalize_duration, or None.
missing Components not found (dose / route / frequency).

Route and form controlled sets

Routes normalize from common abbreviations and phrases: PO / by mouth -> oral, IV -> intravenous, IM -> intramuscular, SC / SQ -> subcutaneous, SL -> sublingual, PR -> rectal, INH / nebulized -> inhaled, and so on. Dose-form words (tab, cap, puff, gtt, ...) map to a controlled form; puff counts imply an inhaled route when no explicit route is present.

Range intervals such as q4-6h normalize to the shortest deterministic interval for the structured rate (q4h, or 6.0 administrations per day). This captures the maximum allowed PRN frequency without adding dosing logic.

Partial sigs

Malformed or partial sigs parse what is present and flag the rest:

parse_sig("PO daily")["missing"]   # ['dose']

Span-attached variant

parse_sigs(text, spans) parses the sig covered by each medication span and returns the span offset alongside the parsed Sig, so results map back to the source document.

from openmed.clinical import parse_sigs

text = "ibuprofen 1 tab PO q6h PRN pain"
spans = [{"start": 10, "end": len(text), "label": "MEDICATION"}]
parse_sigs(text, spans)
# [{'span': (10, 31), 'sig': {... 'as_needed': True, 'condition': 'pain' ...}}]

Notes

Parsing is deterministic and offline. Sig parsing is support tooling and is not a substitute for clinician review; validate before any clinical use.