aimedicalcoding 0.3.3__tar.gz → 0.3.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. {aimedicalcoding-0.3.3/aimedicalcoding.egg-info → aimedicalcoding-0.3.5}/PKG-INFO +2 -2
  2. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/README.md +2 -2
  3. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/README_PYPI.md +1 -1
  4. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/serialize.py +6 -21
  5. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/snomed/patterns.py +13 -2
  6. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5/aimedicalcoding.egg-info}/PKG-INFO +2 -2
  7. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/docs/GAP_SCHEMA.md +5 -7
  8. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/setup.py +1 -1
  9. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/LICENSE +0 -0
  10. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/MANIFEST.in +0 -0
  11. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/__init__.py +0 -0
  12. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/__main__.py +0 -0
  13. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/__init__.py +0 -0
  14. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/base.py +0 -0
  15. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/ccda/__init__.py +0 -0
  16. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/ccda/adapter.py +0 -0
  17. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/ccda/codes.py +0 -0
  18. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/ccda/narrative.py +0 -0
  19. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/ccda/sections.py +0 -0
  20. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/custom_json/__init__.py +0 -0
  21. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/custom_json/adapter.py +0 -0
  22. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/fhir/__init__.py +0 -0
  23. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/fhir/adapter.py +0 -0
  24. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/fhir/codes.py +0 -0
  25. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/adapters/fhir/mapping.py +0 -0
  26. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/api.py +0 -0
  27. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/core/__init__.py +0 -0
  28. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/core/checkdigits.py +0 -0
  29. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/core/models.py +0 -0
  30. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/core/system_registry.py +0 -0
  31. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/pipeline/__init__.py +0 -0
  32. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/pipeline/orchestrator.py +0 -0
  33. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/recovery/__init__.py +0 -0
  34. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/recovery/engine.py +0 -0
  35. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/__init__.py +0 -0
  36. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/base.py +0 -0
  37. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/cvx/__init__.py +0 -0
  38. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/cvx/handler.py +0 -0
  39. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/cvx/normalize.py +0 -0
  40. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/cvx/patterns.py +0 -0
  41. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/icd10cm/__init__.py +0 -0
  42. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/icd10cm/handler.py +0 -0
  43. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/icd10cm/icdformat.py +0 -0
  44. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/icd10cm/patterns.py +0 -0
  45. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/loinc/__init__.py +0 -0
  46. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/loinc/axes.py +0 -0
  47. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/loinc/handler.py +0 -0
  48. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/loinc/normalize.py +0 -0
  49. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/loinc/patterns.py +0 -0
  50. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/rxnorm/__init__.py +0 -0
  51. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/rxnorm/handler.py +0 -0
  52. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/rxnorm/normalize.py +0 -0
  53. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/rxnorm/patterns.py +0 -0
  54. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/snomed/__init__.py +0 -0
  55. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/snomed/handler.py +0 -0
  56. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/snomed/hierarchy.py +0 -0
  57. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/systems/snomed/qualifiers.py +0 -0
  58. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/terminology/__init__.py +0 -0
  59. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding/terminology/service.py +0 -0
  60. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding.egg-info/SOURCES.txt +0 -0
  61. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding.egg-info/dependency_links.txt +0 -0
  62. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding.egg-info/entry_points.txt +0 -0
  63. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding.egg-info/requires.txt +0 -0
  64. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/aimedicalcoding.egg-info/top_level.txt +0 -0
  65. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/docs/ARCHITECTURE.md +0 -0
  66. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/docs/OUTPUT_GUIDE.md +0 -0
  67. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/docs/patterns/CVX_pattern_analysis.md +0 -0
  68. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/docs/patterns/ICD10CM_pattern_analysis.md +0 -0
  69. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/docs/patterns/LOINC_pattern_analysis.md +0 -0
  70. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/docs/patterns/RxNorm_pattern_analysis.md +0 -0
  71. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/docs/patterns/SNOMED_pattern_analysis.md +0 -0
  72. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/pyproject.toml +0 -0
  73. {aimedicalcoding-0.3.3 → aimedicalcoding-0.3.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aimedicalcoding
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: Detect missing/broken clinical codes (LOINC / SNOMED CT / RxNorm / ICD-10-CM / CVX) in CCDA and FHIR documents, with recovery evidence
5
5
  Author: Aakash Kag, Vinay Shankar Miryala, Siva Karthik, Mohammed Rayaan
6
6
  License: MIT
@@ -194,7 +194,7 @@ to fix it:
194
194
  | `ICD_ONLY` | ICD present, SNOMED missing | official ICD ↔ SNOMED map |
195
195
  | `SNOMED_ONLY` | SNOMED present, ICD-10-CM missing | official SNOMED → ICD-10-CM map |
196
196
  | `NDC_ONLY` | NDC present, RxNorm/CVX missing | NDC ↔ RxNorm / CDC NDC ↔ CVX table |
197
- | `RXNORM_ONLY` | RxNorm vaccine product, CVX missing | CVX ↔ RxNorm map |
197
+ | `RXNORM_ONLY` | RxNorm present, target missing (vaccine CVX; drug allergen → SNOMED) | CVX ↔ RxNorm map / RxNorm ↔ SNOMED via UMLS |
198
198
  | `MULTUM_ONLY` / `FDB_ONLY` / `MEDISPAN_ONLY` | proprietary drug vocabulary, RxNorm missing | vendor ↔ RxNorm via UMLS |
199
199
 
200
200
  ---
@@ -196,7 +196,7 @@ a FHIR Bundle, and which gap patterns each can produce:
196
196
  | Target | CCDA source (slot) | FHIR source (slot) | Gap patterns it can emit |
197
197
  |---|---|---|---|
198
198
  | **LOINC** | results / vitals / surveys — observation `code` (question) | `Observation.code` (category `laboratory`/`vital-signs`/`social-history`/`survey`) | `LOCAL_CODE_ONLY` · `NULLFLAVOR` · `DISPLAY_ONLY` · `NARRATIVE_ONLY` · `BAD_CODE` |
199
- | **SNOMED CT** | problems / family hx / social hx / reactions — `value`; procedures / allergen substance — `code` | `Condition.code` / `FamilyMemberHistory.condition[].code` / `Observation.valueCodeableConcept` / `reaction[].manifestation[]` — value slot; `Procedure.code` / `AllergyIntolerance.code` — code slot | `LOCAL_CODE_ONLY` · **`ICD_ONLY`** · `NULLFLAVOR` · `DISPLAY_ONLY` · `NARRATIVE_ONLY` · `BAD_CODE` |
199
+ | **SNOMED CT** | problems / family hx / social hx / reactions — `value`; procedures / allergen substance — `code` | `Condition.code` / `FamilyMemberHistory.condition[].code` / `Observation.valueCodeableConcept` / `reaction[].manifestation[]` — value slot; `Procedure.code` / `AllergyIntolerance.code` — code slot | `LOCAL_CODE_ONLY` · **`ICD_ONLY`** · **`RXNORM_ONLY`** · `NULLFLAVOR` · `DISPLAY_ONLY` · `NARRATIVE_ONLY` · `BAD_CODE` |
200
200
  | **RxNorm** | medications — `manufacturedMaterial/code` | `Medication.code` via `medicationReference` (or inline `medicationCodeableConcept`) | **`NDC_ONLY`** · **`MULTUM_ONLY`** · **`FDB_ONLY`** · **`MEDISPAN_ONLY`** · `LOCAL_CODE_ONLY` · `NULLFLAVOR` · `DISPLAY_ONLY` · `NARRATIVE_ONLY` |
201
201
  | **ICD-10-CM** | problems / encounters — diagnosis `value` | `Condition.code` (value slot) | **`SNOMED_ONLY`** · `LOCAL_CODE_ONLY` · `NULLFLAVOR` · `DISPLAY_ONLY` · `NARRATIVE_ONLY` · `BAD_CODE` |
202
202
  | **CVX** | immunizations — `manufacturedMaterial/code` | `Immunization.vaccineCode` | **`RXNORM_ONLY`** · **`NDC_ONLY`** · `LOCAL_CODE_ONLY` · `NULLFLAVOR` · `DISPLAY_ONLY` · `NARRATIVE_ONLY` · `BAD_CODE` |
@@ -226,7 +226,7 @@ deterministically to the target. Full schema + per-pattern JSON in
226
226
  | `ICD_ONLY` | ICD-9/10 present, no SNOMED | ICD↔SNOMED map (NLM) |
227
227
  | `SNOMED_ONLY` | SNOMED present, no ICD-10-CM | SNOMED→ICD-10-CM map (NLM) |
228
228
  | `NDC_ONLY` | NDC present, no RxNorm/CVX | NDC↔RxNorm / CDC NDC↔CVX table |
229
- | `RXNORM_ONLY` | RxNorm vaccine product, no CVX | CVX↔RxNorm map |
229
+ | `RXNORM_ONLY` | RxNorm code present, target missing (vaccine → CVX; drug allergen → SNOMED) | CVX↔RxNorm map / RxNorm↔SNOMED via UMLS |
230
230
  | `MULTUM_ONLY` / `FDB_ONLY` / `MEDISPAN_ONLY` | proprietary drug vocab, no RxNorm | vendor↔RxNorm via UMLS CUI |
231
231
 
232
232
  Skipped (never emitted): a valid code for the target (incl. via `<translation>`),
@@ -157,7 +157,7 @@ to fix it:
157
157
  | `ICD_ONLY` | ICD present, SNOMED missing | official ICD ↔ SNOMED map |
158
158
  | `SNOMED_ONLY` | SNOMED present, ICD-10-CM missing | official SNOMED → ICD-10-CM map |
159
159
  | `NDC_ONLY` | NDC present, RxNorm/CVX missing | NDC ↔ RxNorm / CDC NDC ↔ CVX table |
160
- | `RXNORM_ONLY` | RxNorm vaccine product, CVX missing | CVX ↔ RxNorm map |
160
+ | `RXNORM_ONLY` | RxNorm present, target missing (vaccine CVX; drug allergen → SNOMED) | CVX ↔ RxNorm map / RxNorm ↔ SNOMED via UMLS |
161
161
  | `MULTUM_ONLY` / `FDB_ONLY` / `MEDISPAN_ONLY` | proprietary drug vocabulary, RxNorm missing | vendor ↔ RxNorm via UMLS |
162
162
 
163
163
  ---
@@ -121,20 +121,6 @@ def _dedupe(items) -> list:
121
121
  return out
122
122
 
123
123
 
124
- # SNOMED search-term enrichment (Problems 11450-4, Allergies 48765-2, Social
125
- # History 29762-2), matched by section LOINC or by the contexts those sections
126
- # route to (FHIR resources often carry no meta.tag/section code). Which slot's
127
- # labels get appended differs by section:
128
- # - Social History -> CODE tag labels (the question, e.g. "Gender identity" —
129
- # the value label is often a placeholder like "Not on file")
130
- # - Problems / Allergies -> VALUE tag labels (the concept; the code tag is a
131
- # generic marker like ASSERTION / "Problem" — appending it is noise)
132
- _SNOMED_CODE_LABEL_SECTIONS = {"29762-2"}
133
- _SNOMED_CODE_LABEL_CONTEXTS = {"social_history"}
134
- _SNOMED_VALUE_LABEL_SECTIONS = {"11450-4", "48765-2"}
135
- _SNOMED_VALUE_LABEL_CONTEXTS = {"problem", "allergy_substance", "allergy_reaction"}
136
-
137
-
138
124
  def _recovery(record: NormalizedRecord, slot: str, system: str) -> dict:
139
125
  stmt, ev, g = record.statement, record.gap.evidence, record.gap
140
126
 
@@ -146,18 +132,17 @@ def _recovery(record: NormalizedRecord, slot: str, system: str) -> dict:
146
132
  terms = [stmt.display_name, stmt.original_text]
147
133
  # add any normalized term the handler produced
148
134
  terms += [ev.get("analyte_normalized"), ev.get("term_normalized"), ev.get("ingredient")]
149
- # SNOMED only, Problems/Allergies/Social History only: append trailing
150
- # label context from the section-appropriate slot (see constants above).
135
+ # SNOMED: guarantee the TARGET slot's own labels are present, mirroring
136
+ # `target.slot` in the output record — code-slot gaps carry the code tag's
137
+ # displayName/originalText, value-slot gaps the value tag's.
151
138
  if system == System.SNOMEDCT.value:
152
- if (stmt.section_code in _SNOMED_CODE_LABEL_SECTIONS
153
- or stmt.context in _SNOMED_CODE_LABEL_CONTEXTS):
154
- terms += [stmt.display_name, stmt.original_text]
155
- elif (stmt.section_code in _SNOMED_VALUE_LABEL_SECTIONS
156
- or stmt.context in _SNOMED_VALUE_LABEL_CONTEXTS):
139
+ if slot == "value":
157
140
  if stmt.value:
158
141
  terms += [stmt.value.coded_value.display
159
142
  if stmt.value.coded_value else None,
160
143
  stmt.value.original_text]
144
+ else:
145
+ terms += [stmt.display_name, stmt.original_text]
161
146
 
162
147
  rec = {
163
148
  "search_terms": _dedupe(terms),
@@ -31,6 +31,7 @@ ICD_SYSTEMS = {System.ICD10CM, System.ICD9CM, System.ICD10PCS}
31
31
  class SnomedGapPattern(str, Enum):
32
32
  LOCAL_CODE_ONLY = "LOCAL_CODE_ONLY" # a local/other clinical code (incl. CPT), no SNOMED
33
33
  ICD_ONLY = "ICD_ONLY" # ICD-9/10 only -> ICD↔SNOMED crosswalk
34
+ RXNORM_ONLY = "RXNORM_ONLY" # RxNorm-coded allergen -> RxNorm↔SNOMED (UMLS)
34
35
  NULLFLAVOR = "NULLFLAVOR"
35
36
  DISPLAY_ONLY = "DISPLAY_ONLY"
36
37
  NARRATIVE_ONLY = "NARRATIVE_ONLY"
@@ -107,13 +108,17 @@ def classify(stmt: ClinicalStatement) -> Optional[SnomedGapPattern]:
107
108
 
108
109
  if cc and cc.code and cc.system in ICD_SYSTEMS:
109
110
  return SnomedGapPattern.ICD_ONLY
111
+ if cc and cc.code and cc.system == System.RXNORM:
112
+ return SnomedGapPattern.RXNORM_ONLY # standard vocab, not "local"
110
113
  if cc and cc.code and cc.system not in STRUCTURAL:
111
114
  return SnomedGapPattern.LOCAL_CODE_ONLY # CPT / local / other
112
115
 
113
- # no usable concept code
116
+ # no usable concept code. The label must come from the CONCEPT's slot
117
+ # (value display/originalText for value-slot contexts) — raw_text alone
118
+ # misses e.g. reaction observations whose code tag is a bare ASSERTION.
114
119
  if _has_nullflavor(stmt):
115
120
  return SnomedGapPattern.NULLFLAVOR
116
- if stmt.raw_text:
121
+ if concept_term(stmt):
117
122
  if "/text" in (stmt.source_ref or ""):
118
123
  return SnomedGapPattern.NARRATIVE_ONLY
119
124
  return SnomedGapPattern.DISPLAY_ONLY
@@ -152,6 +157,12 @@ def parse_gap(stmt: ClinicalStatement, pattern: SnomedGapPattern) -> Gap:
152
157
  gap.evidence["icd_system"] = (cc.system.value if cc.system else None)
153
158
  gap.note = ("Use the official ICD↔SNOMED map (NLM/UMLS) — deterministic; "
154
159
  "LLM only to choose among multiple map targets.")
160
+ elif pattern == SnomedGapPattern.RXNORM_ONLY and cc:
161
+ gap.evidence["rxnorm_code"] = cc.code
162
+ gap.evidence["rxnorm_system"] = cc.raw_system
163
+ gap.note = ("RxNorm-coded allergen (drug allergy) — crosswalk RxNorm → "
164
+ "SNOMED substance/product via UMLS CUI; LLM only if the "
165
+ "ingredient maps ambiguously.")
155
166
  elif pattern == SnomedGapPattern.BAD_CODE and cc:
156
167
  gap.evidence["malformed_code"] = cc.code
157
168
  gap.note = "SCTID-shaped but Verhoeff check failed; resolve via text + hierarchy."
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aimedicalcoding
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: Detect missing/broken clinical codes (LOINC / SNOMED CT / RxNorm / ICD-10-CM / CVX) in CCDA and FHIR documents, with recovery evidence
5
5
  Author: Aakash Kag, Vinay Shankar Miryala, Siva Karthik, Mohammed Rayaan
6
6
  License: MIT
@@ -194,7 +194,7 @@ to fix it:
194
194
  | `ICD_ONLY` | ICD present, SNOMED missing | official ICD ↔ SNOMED map |
195
195
  | `SNOMED_ONLY` | SNOMED present, ICD-10-CM missing | official SNOMED → ICD-10-CM map |
196
196
  | `NDC_ONLY` | NDC present, RxNorm/CVX missing | NDC ↔ RxNorm / CDC NDC ↔ CVX table |
197
- | `RXNORM_ONLY` | RxNorm vaccine product, CVX missing | CVX ↔ RxNorm map |
197
+ | `RXNORM_ONLY` | RxNorm present, target missing (vaccine CVX; drug allergen → SNOMED) | CVX ↔ RxNorm map / RxNorm ↔ SNOMED via UMLS |
198
198
  | `MULTUM_ONLY` / `FDB_ONLY` / `MEDISPAN_ONLY` | proprietary drug vocabulary, RxNorm missing | vendor ↔ RxNorm via UMLS |
199
199
 
200
200
  ---
@@ -40,7 +40,7 @@ Each record separates four concerns:
40
40
  | `id` | sequence number |
41
41
  | `target.system` | `LOINC` \| `SNOMED-CT` — which terminology this gap recovers |
42
42
  | `target.slot` | `code` (question/analyte) \| `value` (answer) — which slot is being filled |
43
- | `pattern` | `LOCAL_CODE_ONLY` \| `ICD_ONLY` \| `NULLFLAVOR` \| `DISPLAY_ONLY` \| `BAD_CODE` \| `NARRATIVE_ONLY` |
43
+ | `pattern` | `LOCAL_CODE_ONLY` \| `ICD_ONLY` \| `RXNORM_ONLY` \| `NULLFLAVOR` \| `DISPLAY_ONLY` \| `BAD_CODE` \| `NARRATIVE_ONLY` |
44
44
  | `payload_type` | `codeable` (code is the concept, value is a measurement) \| `qa` (code is a question, value is a coded answer) |
45
45
  | `section` | `{ code, name, system }` — the source section |
46
46
  | **`observation`** | the faithful facts of BOTH slots (see below) |
@@ -89,12 +89,9 @@ Each record separates four concerns:
89
89
  - `target.slot = "code"` (LOINC) → search `observation.code.display_text` / `.original_text`.
90
90
  - `target.slot = "value"` (SNOMED value-slot) → search `observation.value.display_text` / `.original_text`.
91
91
  `recovery.search_terms` already gives you the right ones, deduped.
92
- For **SNOMED-CT** targets, extra label context is appended at the end,
93
- section-specific: **Social History (29762-2)** appends the CODE tag's
94
- `display_text`/`original_text` (the question useful when the value label
95
- is a placeholder like "Not on file"); **Problems (11450-4)** and
96
- **Allergies (48765-2)** append the VALUE tag's labels (the concept — the
97
- code tag there is a generic marker like ASSERTION/"Problem").
92
+ For **SNOMED-CT** targets the terms follow `target.slot`: value-slot gaps
93
+ carry the VALUE tag's `display_text`/`original_text`, code-slot gaps the
94
+ CODE tag's — the other slot's labels are not mixed in.
98
95
 
99
96
  ---
100
97
 
@@ -104,6 +101,7 @@ code tag there is a generic marker like ASSERTION/"Problem").
104
101
  |---|---|---|---|
105
102
  | `LOCAL_CODE_ONLY` | both | a local/in-house code (or CPT for SNOMED proc), no target code | crosswalk first, else text+filter |
106
103
  | `ICD_ONLY` | SNOMED | value coded in ICD-9/10 only | **ICD↔SNOMED map** (deterministic) |
104
+ | `RXNORM_ONLY` | SNOMED | allergen coded in RxNorm only (drug allergy) | **RxNorm↔SNOMED via UMLS CUI** |
107
105
  | `NULLFLAVOR` | both | code blank; label recovered from narrative | text+filter on search_terms |
108
106
  | `DISPLAY_ONLY` | both | a display/text but no usable code | text+filter |
109
107
  | `BAD_CODE` | both | shaped right, check digit fails (Luhn/Verhoeff) | LOINC: `checkdigit_correction`; SNOMED: re-resolve |
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="aimedicalcoding",
5
- version="0.3.3",
5
+ version="0.3.5",
6
6
  author="Aakash Kag, Vinay Shankar Miryala, Siva Karthik, Mohammed Rayaan",
7
7
  description=(
8
8
  "Detect missing/broken clinical codes (LOINC / SNOMED CT / RxNorm / "
File without changes