Agent Skillsmaziyarpanahi/openmed › parsing-hl7v2-messages

parsing-hl7v2-messages

GitHub

解析HL7 v2.x消息,提取OBX-5和NTE-3中的临床文本,支持去标识化和分析。适用于从接口引擎或实验室系统接收数据时,需挖掘嵌入的笔记或结果文本的场景。

skills/parsing-hl7v2-messages/SKILL.md maziyarpanahi/openmed

Trigger Scenarios

接收HL7 v2消息(如ADT、ORU、MDM) 需要从OBX/NTE字段提取临床叙述文本 对HL7数据进行去标识化及NLP分析

Install

npx skills add maziyarpanahi/openmed --skill parsing-hl7v2-messages -g -y
More Options

Use without installing

npx skills use maziyarpanahi/openmed@parsing-hl7v2-messages

指定 Agent (Claude Code)

npx skills add maziyarpanahi/openmed --skill parsing-hl7v2-messages -a claude-code -g -y

安装 repo 全部 skill

npx skills add maziyarpanahi/openmed --all -g -y

预览 repo 内 skill

npx skills add maziyarpanahi/openmed --list

SKILL.md

Frontmatter
{
    "name": "parsing-hl7v2-messages",
    "license": "Apache-2.0",
    "metadata": {
        "pairs": "before",
        "project": "OpenMed",
        "version": "1.0",
        "category": "data-ingestion"
    },
    "description": "Decodes pipe-delimited HL7 v2.x messages (ADT, ORU, MDM, ORM) into structured segments\/fields\/components and surfaces OBX-5 and NTE-3 free-text narrative for OpenMed. Use before OpenMed processing when ingesting HL7 v2 feeds from an interface engine, lab\/results system, or ADT stream and you need the embedded clinical note text de-identified and analyzed. Flatten OBX\/NTE text then call openmed.deidentify and openmed.analyze_text; segment-aware redaction is available via openmed.interop.hl7v2. Trigger keywords: HL7, HL7 v2, ADT, ORU, OBX, MSH, PID, pipe-delimited, interface engine, Mirth, lab results."
}

Parsing HL7 v2 Messages for OpenMed

HL7 v2.x is the workhorse of hospital interfacing — ADT (admit/discharge/ transfer), ORU (observation results), MDM (document management), and ORM (orders) messages flow continuously between EHR, lab, radiology, and ancillary systems. The clinical narrative you want for NLP is buried in OBX-5 (observation value) and NTE-3 (notes/comments) fields, wrapped in a pipe-and-caret encoding. This skill decodes that envelope and hands the free text to OpenMed.

When to use

  • You receive HL7 v2 messages from an interface engine (Mirth/NextGen Connect, Rhapsody, Cloverleaf) and want to mine embedded note/result text.
  • A lab feed (ORU^R01) carries impression/comment narrative in OBX/NTE.
  • An MDM^T02 transcription message carries a full report in OBX-5.
  • You need a de-identified, structured feed into openmed.analyze_text.

HL7 v2 structure in one minute

A message is segments separated by \r (carriage return). Each segment is 3-letter-named, then fields split by |, components by ^, repetitions by ~, sub-components by &, with \ as escape. The encoding characters are declared in MSH-1 (the field separator) and MSH-2 (^~\&). Field positions are one-based, and MSH is special: MSH-1 is the separator, so MSH-2 is the first real field.

MSH|^~\&|LAB|HOSP|EHR|HOSP|20240302101500||ORU^R01|MSG0001|P|2.5
PID|1||MRN12345^^^HOSP^MR||DOE^JANE^Q||19700115|F|||1 FAKE ST^^SPRINGFIELD^IL^62704
OBR|1||ORD9|CBC^Complete Blood Count
OBX|1|TX|IMPRESSION||Mild leukocytosis; clinically correlate.||||||F
NTE|1||Patient reports fatigue x1 week. Dr. Smith notified.

Quick start

Parse the envelope and pull narrative from OBX-5 / NTE-3, then hand off:

import openmed
from openmed.interop.hl7v2 import parse_hl7v2

raw = open("results.hl7", encoding="utf-8").read()
msg = parse_hl7v2(raw)               # -> HL7Message (segments preserved)

narrative_chunks = []
for seg in msg.segments:
    if seg.name == "OBX":
        # OBX-2 is the value type; OBX-5 is the observation value.
        value_type = seg.get_field(2)
        if value_type in {"TX", "FT", "CE", "ST"}:
            narrative_chunks.append(seg.get_field(5) or "")
    elif seg.name == "NTE":
        narrative_chunks.append(seg.get_field(3) or "")

# Decode component delimiters into plain text before NLP.
flat = "\n".join(c.replace("^", " ").replace("&", " ") for c in narrative_chunks if c)

# Hand the narrative to OpenMed.
deid = openmed.deidentify(flat, method="replace", policy="hipaa_safe_harbor")
result = openmed.analyze_text(deid.text, output_format="dict")

HL7Segment.get_field(position) uses one-based HL7 positions and returns None for absent fields. HL7Message.segment_names() lists segments in order.

Whole-message segment-aware de-identification

When you need to redact the entire message (structured PID/NK1/GT1 fields and OBX/NTE free text) while preserving HL7 framing, use the bundled redactor instead of hand-rolling it:

from openmed.interop.hl7v2 import redact_hl7v2

safe = redact_hl7v2("results.hl7")   # path or message text
# PID-3 hashed, PID-5 name surrogated, PID-7 DOB date-shifted, OBX-5/NTE-3
# free text masked via openmed.deidentify — delimiters and segment order kept.

redact_hl7v2 applies DEFAULT_FIELD_MAP (PID, PD1, NK1, GT1, IN1/IN2, OBX, NTE). Extend or override it with field_map={("ZPS", 4): {"action": "hash"}} for site-specific Z-segments, and pass date_shift_days= for a fixed, interval-preserving shift.

Workflow

  1. Frame-split safely. Real feeds use \r, \r\n, or MLLP framing (\x0b\x1c\r). parse_hl7v2 auto-detects the segment separator; strip MLLP control bytes before parsing.
  2. Read encoding from MSH — never assume |^~\&. The adapter derives the delimiter set from MSH-1/MSH-2 (HL7V2Encoding.from_msh_segment).
  3. Locate narrative. OBX-5 (gated by OBX-2 value type), NTE-3, and report-bearing segments. Concatenate repetitions (~) and components (^).
  4. De-identify, then analyze with OpenMed.
  5. Rejoin results to the patient/encounter via PID-3 (patient id) and PV1-19 (visit number) — but redact those identifiers in anything you persist.

Hand-off to / from OpenMed

  • To OpenMed: flattened OBX-5/NTE-3 text → openmed.deidentifyopenmed.analyze_text.
  • Adapter: openmed.interop.hl7v2 provides parse_hl7v2, redact_hl7v2, HL7Message, HL7Segment, HL7V2Encoding, HL7FieldRule, and DEFAULT_FIELD_MAP for segment-aware de-id that preserves message framing. It is parse-and-redact only — not a conformance validator.
  • Re-link by id, not by PHI: carry PID-3/PV1-19 as keys, but store hashed or surrogate values (the default redact_hl7v2 hashes PID-3).

Edge cases & gotchas

  • MLLP wrapper. Messages off a TCP MLLP listener are framed with \x0b (start) and \x1c\r (end). Strip these before parse_hl7v2.
  • Escape sequences. \F\, \S\, \T\, \R\, \E\ encode literal delimiters, and \.br\ is a line break inside OBX text. Unescape before NLP.
  • Repeating OBX. A single result can span many OBX segments (one line each); reassemble in order before summarizing.
  • Value types matter. Only treat OBX-5 as narrative when OBX-2 is a text type (TX, FT, ST, CE); numeric (NM) and coded-only values are not free text. The default redactor restricts free-text redaction to FT/TX.
  • Z-segments. Site-defined Z* segments often carry extra PHI; add explicit field_map rules — they are not in the default map.
  • Versions vary. v2.3 through v2.8 differ in field cardinality; resolve positions against MSH-12 (version id), don't hardcode across versions.

Standards & references

Version History

  • f213557 Current 2026-07-23 00:45

Same Skill Collection

skills/building-with-openmed/SKILL.md
skills/loading-openmed-models/SKILL.md
skills/annotating-variants/SKILL.md
skills/assembling-fhir-bundles/SKILL.md
skills/auditing-deid-leakage/SKILL.md
skills/auditing-deidentification-runs/SKILL.md
skills/auditing-part11-trails/SKILL.md
skills/auditing-safe-harbor-checklist/SKILL.md
skills/auditing-subgroup-fairness/SKILL.md
skills/authoring-model-cards/SKILL.md
skills/batch-processing-clinical-text/SKILL.md
skills/benchmarking-clinical-ner/SKILL.md
skills/bridging-presidio-and-spacy/SKILL.md
skills/building-gold-corpus/SKILL.md
skills/building-patient-timelines/SKILL.md
skills/checking-hipaa-compliance/SKILL.md
skills/choosing-openmed-models/SKILL.md
skills/coding-hcc-risk-adjustment/SKILL.md
skills/coding-icd10/SKILL.md
skills/computing-ecqms/SKILL.md
skills/configuring-privacy-policies/SKILL.md
skills/defining-cohort-phenotypes/SKILL.md
skills/deidentifying-clinical-text/SKILL.md
skills/deidentifying-multilingual-text/SKILL.md
skills/deploying-openmed-mcp/SKILL.md
skills/detecting-pv-signals/SKILL.md
skills/enforcing-nophi-logging/SKILL.md
skills/etl-to-omop-cdm/SKILL.md
skills/evaluating-with-leakage-gates/SKILL.md
skills/exporting-bulk-fhir/SKILL.md
skills/exporting-to-fhir/SKILL.md
skills/extracting-clinical-entities/SKILL.md
skills/extracting-dicom-metadata/SKILL.md
skills/extracting-lab-tables/SKILL.md
skills/extracting-pii-entities/SKILL.md
skills/extracting-sdoh/SKILL.md
skills/fetching-fhir-resources/SKILL.md
skills/gating-deid-leakage/SKILL.md
skills/generating-synthea-data/SKILL.md
skills/generating-synthetic-surrogates/SKILL.md
skills/ingesting-clinical-documents/SKILL.md
skills/linking-umls-concepts/SKILL.md
skills/mapping-loinc/SKILL.md
skills/mapping-to-snomed/SKILL.md
skills/mining-pubmed-literature/SKILL.md
skills/normalizing-rxnorm/SKILL.md
skills/parsing-ccda-documents/SKILL.md
skills/parsing-lab-values/SKILL.md
skills/parsing-trial-eligibility/SKILL.md

Metadata

Files
0
Version
f213557
Hash
334df5b0
Indexed
2026-07-23 00:45

ホーム - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-07-29 13:11
浙ICP备14020137号-1 $お客様$