annotating-variants
Annotates VCF variants and normalizes HGVS nomenclature with public, license-free annotators…
Converts free-text radiology narratives into structured findings and impression — with measurements, laterality, anatomy, and follow-up recommendations — after OpenMed NER. Use when the user has a CT/MRI/X-ray/ultrasound/mammography report and needs the sections split
$ npx -y skills add maziyarpanahi/openmed --skill structuring-radiology-reports --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/structuring-radiology-reportsContext preview
The summary Claude sees to decide when to auto-load this skill.
Converts free-text radiology narratives into structured findings and impression — with measurements, laterality, anatomy, and follow-up recommendations — after OpenMed NER. Use when the user has a CT/MRI/X-ray/ultrasound/mammography report and needs the sections split
name: structuring-radiology-reports description: "Converts free-text radiology narratives into structured findings and impression — with measurements, laterality, anatomy, and follow-up recommendations — after OpenMed NER. Use when the user has a CT/MRI/X-ray/ultrasound/mammography report and needs the sections split (technique, comparison, findings, impression), lesion measurements and laterality captured, BI-RADS / Lung-RADS assessment categories pulled, or incidental findings and recommended follow-up tracked. Trigger keywords: radiology report, findings, impression, RadLex, DICOM-SR, BI-RADS, Lung-RADS, ACR, laterality, measurement, nodule, incidental finding, follow-up, structured reporting. Pairs after OpenMed: run openmed.analyze_text on the report (Anatomy/Disease/measurement entities), then assemble structured findings. De-identify the report first. Decision-support only — not a diagnostic medical device." license: Apache-2.0 metadata: project: OpenMed category: imaging-ocr pairs: after version: "1.0"
A radiology report is prose, but its *meaning* is structured: a **technique**, a **comparison**, a list of **findings** (each with anatomy, laterality, and a measurement), and an **impression** that may carry an **assessment category** (BI-RADS, Lung-RADS) and a **follow-up recommendation**. This skill turns the narrative into that structure so findings are trackable — especially **incidental findings** that need downstream follow-up.
OpenMed extracts the anatomy, disease/finding, and measurement spans on-device; this skill organizes them into sectioned, coded findings. It is **decision-support, not a diagnostic device** — every structured finding must be attributable back to its source sentence for radiologist review.
`{technique, comparison, findings[], impression}` with measurements and laterality.
assessment categories and the recommended action.
the report recommends.
report.
import openmed
report = (
"TECHNIQUE: CT chest without contrast.\n"
"COMPARISON: CT 2023-11-02.\n"
"FINDINGS: A 8 mm solid nodule is noted in the right upper lobe, "
"unchanged. No pleural effusion.\n"
"IMPRESSION: 8 mm right upper lobe nodule, stable. Lung-RADS 2. "
"Recommend annual low-dose CT screening."
)
# 1) De-identify the report on-device first (synthetic example shown).
deid = openmed.deidentify(report, policy="hipaa_safe_harbor")
text = deid.deidentified_text
# 2) Run NER for anatomy / finding / measurement spans.
ents = openmed.analyze_text(
text,
model_name="anatomy_detection_superclinical", # Anatomy category
output_format="dict",
)["entities"]
# 3) Split sections by header, then attach entities + measurements per finding.
import re
SECTION = re.compile(r"(?im)^(TECHNIQUE|COMPARISON|FINDINGS|IMPRESSION)\s*:")
sections, last, name = {}, 0, None
for m in SECTION.finditer(text):
if name: sections[name] = text[last:m.start()].strip()
name, last = m.group(1).upper(), m.end()
if name: sections[name] = text[last:].strip()
structured = {
"technique": sections.get("TECHNIQUE"),
"comparison": sections.get("COMPARISON"),
"findings": _split_findings(sections.get("FINDINGS", "")), # one per sentence
"impression": sections.get("IMPRESSION"),
"measurements": re.findall(r"\b\d+(?:\.\d+)?\s?(?:mm|cm)\b", text),
"laterality": sorted({w for w in ("right", "left", "bilateral")
if re.search(rf"\b{w}\b", text, re.I)}),
"assessment": (re.search(r"\b(?:BI-RADS|Lung-RADS)\s*\d[A-C]?\b", text, re.I)
or [None])[0] if re.search(r"RADS", text, re.I) else None,
"follow_up": _extract_followup(sections.get("IMPRESSION", "")),
}`_split_findings` / `_extract_followup` are your sentence splitter and a recommendation matcher ("recommend …", "follow-up in N months"); keep each finding tied to its source sentence offsets.
1. **De-identify first.** `openmed.deidentify(report, policy=...)`; structure from `deidentified_text`. Patient name, MRN, accession, and dates go before anything is stored or shared. 2. **Split sections** by the standard headers (TECHNIQUE, COMPARISON, FINDINGS, IMPRESSION; also HISTORY/INDICATION). Reports vary — fall back to position if headers are missing. 3. **Run `analyze_text`** for anatomy and finding entities; capture measurements ("8 mm", "1.2 cm") and laterality ("right", "left", "bilateral") near each finding. 4. **Build one structured finding per observation**: `{anatomy, finding, laterality, measurement, change_vs_prior, source_offsets}`. "Unchanged", "stable", "increased", "new" capture temporal change against the comparison. 5. **Pull the assessment category** (BI-RADS 0-6, Lung-RADS 1-4X) from the impression and the **recommended follow-up** (modality + interval). 6. **Flag incidental findings** — findings unrelated to the exam indication — and route them to a follow-up tracker so they aren't lost. 7. **Map toward RadLex / DICOM-SR** if you need coded interoperability, and surface the whole structure to a radiologist for verification.
OpenMed's `analyze_text` returns a `dict`; `result["entities"]` items carry `text`, `label`, `confidence`, `start`, `end`.
populate each structured finding; keep offsets so every field traces to a source sentence.
(`openmed.multimodal.ocr.ocr`), then run NER on the recognized text.
Local-first healthcare AI: clinical NER and HIPAA PII de-identification on hardware you control. 2,200+ medical models, 35 model-backed PII languages, and Python, MLX, Android and browser runtimes. Apache-2.0 SDK.
Repo: maziyarpanahi/openmed
Annotates VCF variants and normalizes HGVS nomenclature with public, license-free annotators…
Choose the first OpenMed workflow skill for an intake, privacy, extraction, exchange, or…
Package multiple FHIR R4 resources produced from OpenMed output into a single valid…
Adversarially scan already-de-identified clinical text for residual identifiers and emit a…
Produce a signed, reproducible, no-PHI audit trail for an OpenMed de-identification run via…
Generates and verifies 21 CFR Part 11-style audit trails — who/what/when, electronic…