aimedicalcoding 0.3.7__tar.gz → 0.3.9__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.7/aimedicalcoding.egg-info → aimedicalcoding-0.3.9}/PKG-INFO +1 -1
  2. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/cvx/patterns.py +12 -8
  3. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/icd10cm/patterns.py +10 -6
  4. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/loinc/patterns.py +9 -1
  5. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/rxnorm/patterns.py +13 -8
  6. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/snomed/patterns.py +13 -10
  7. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9/aimedicalcoding.egg-info}/PKG-INFO +1 -1
  8. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/docs/GAP_SCHEMA.md +2 -2
  9. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/setup.py +1 -1
  10. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/LICENSE +0 -0
  11. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/MANIFEST.in +0 -0
  12. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/README.md +0 -0
  13. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/README_PYPI.md +0 -0
  14. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/__init__.py +0 -0
  15. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/__main__.py +0 -0
  16. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/__init__.py +0 -0
  17. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/base.py +0 -0
  18. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/ccda/__init__.py +0 -0
  19. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/ccda/adapter.py +0 -0
  20. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/ccda/codes.py +0 -0
  21. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/ccda/narrative.py +0 -0
  22. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/ccda/sections.py +0 -0
  23. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/custom_json/__init__.py +0 -0
  24. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/custom_json/adapter.py +0 -0
  25. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/fhir/__init__.py +0 -0
  26. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/fhir/adapter.py +0 -0
  27. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/fhir/codes.py +0 -0
  28. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/adapters/fhir/mapping.py +0 -0
  29. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/api.py +0 -0
  30. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/core/__init__.py +0 -0
  31. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/core/checkdigits.py +0 -0
  32. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/core/models.py +0 -0
  33. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/core/system_registry.py +0 -0
  34. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/pipeline/__init__.py +0 -0
  35. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/pipeline/orchestrator.py +0 -0
  36. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/recovery/__init__.py +0 -0
  37. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/recovery/engine.py +0 -0
  38. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/serialize.py +0 -0
  39. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/__init__.py +0 -0
  40. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/base.py +0 -0
  41. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/cvx/__init__.py +0 -0
  42. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/cvx/handler.py +0 -0
  43. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/cvx/normalize.py +0 -0
  44. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/icd10cm/__init__.py +0 -0
  45. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/icd10cm/handler.py +0 -0
  46. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/icd10cm/icdformat.py +0 -0
  47. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/loinc/__init__.py +0 -0
  48. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/loinc/axes.py +0 -0
  49. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/loinc/handler.py +0 -0
  50. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/loinc/normalize.py +0 -0
  51. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/rxnorm/__init__.py +0 -0
  52. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/rxnorm/handler.py +0 -0
  53. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/rxnorm/normalize.py +0 -0
  54. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/snomed/__init__.py +0 -0
  55. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/snomed/handler.py +0 -0
  56. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/snomed/hierarchy.py +0 -0
  57. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/systems/snomed/qualifiers.py +0 -0
  58. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/terminology/__init__.py +0 -0
  59. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding/terminology/service.py +0 -0
  60. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding.egg-info/SOURCES.txt +0 -0
  61. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding.egg-info/dependency_links.txt +0 -0
  62. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding.egg-info/entry_points.txt +0 -0
  63. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding.egg-info/requires.txt +0 -0
  64. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/aimedicalcoding.egg-info/top_level.txt +0 -0
  65. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/docs/ARCHITECTURE.md +0 -0
  66. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/docs/OUTPUT_GUIDE.md +0 -0
  67. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/docs/patterns/CVX_pattern_analysis.md +0 -0
  68. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/docs/patterns/ICD10CM_pattern_analysis.md +0 -0
  69. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/docs/patterns/LOINC_pattern_analysis.md +0 -0
  70. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/docs/patterns/RxNorm_pattern_analysis.md +0 -0
  71. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/docs/patterns/SNOMED_pattern_analysis.md +0 -0
  72. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/pyproject.toml +0 -0
  73. {aimedicalcoding-0.3.7 → aimedicalcoding-0.3.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aimedicalcoding
3
- Version: 0.3.7
3
+ Version: 0.3.9
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
@@ -73,13 +73,14 @@ def classify(stmt: ClinicalStatement) -> Optional[CvxGapPattern]:
73
73
  if cc and cc.code and cc.system not in STRUCTURAL:
74
74
  return CvxGapPattern.LOCAL_CODE_ONLY
75
75
 
76
+ # no usable code + no vaccine name -> nothing to recover -> not a gap
77
+ if not stmt.raw_text:
78
+ return None
76
79
  if _has_nullflavor(stmt):
77
80
  return CvxGapPattern.NULLFLAVOR
78
- if stmt.raw_text:
79
- if "/text" in (stmt.source_ref or ""):
80
- return CvxGapPattern.NARRATIVE_ONLY
81
- return CvxGapPattern.DISPLAY_ONLY
82
- return None
81
+ if "/text" in (stmt.source_ref or ""):
82
+ return CvxGapPattern.NARRATIVE_ONLY
83
+ return CvxGapPattern.DISPLAY_ONLY
83
84
 
84
85
 
85
86
  # --------------------------------------------------------------------------
@@ -109,17 +110,20 @@ def parse_gap(stmt: ClinicalStatement, pattern: CvxGapPattern) -> Gap:
109
110
 
110
111
  if pattern == CvxGapPattern.RXNORM_ONLY and cc:
111
112
  gap.evidence["rxnorm_code"] = cc.code
112
- gap.evidence["rxnorm_system"] = cc.raw_system
113
+ gap.evidence["rxnorm_system"] = cc.system.value if cc.system else None
114
+ gap.evidence["rxnorm_system_raw"] = cc.raw_system
113
115
  gap.note = ("Use the CDC/NLM CVX↔RxNorm crosswalk — deterministic; "
114
116
  "LLM only if a generic RxCUI maps to multiple CVX valences.")
115
117
  elif pattern == CvxGapPattern.NDC_ONLY and cc:
116
118
  gap.evidence["ndc_code"] = cc.code
117
- gap.evidence["ndc_system"] = cc.raw_system
119
+ gap.evidence["ndc_system"] = cc.system.value if cc.system else None
120
+ gap.evidence["ndc_system_raw"] = cc.raw_system
118
121
  gap.note = ("Use the CDC vaccine NDC↔CVX table (published, free) — "
119
122
  "deterministic mapping from the dispensed NDC to CVX.")
120
123
  elif pattern == CvxGapPattern.LOCAL_CODE_ONLY and cc:
121
124
  gap.evidence["local_code"] = cc.code
122
- gap.evidence["local_system"] = cc.raw_system
125
+ gap.evidence["local_system"] = cc.system.value if cc.system else None
126
+ gap.evidence["local_system_raw"] = cc.raw_system
123
127
  gap.note = ("Crosswalk local immunization code → CVX first; else search "
124
128
  "by normalized vaccine concept (+ valence) → CVX.")
125
129
  elif pattern == CvxGapPattern.BAD_CODE and cc:
@@ -67,13 +67,16 @@ def classify(stmt: ClinicalStatement) -> Optional[Icd10cmGapPattern]:
67
67
  if other: # ICD-9 / local / anything else
68
68
  return Icd10cmGapPattern.LOCAL_CODE_ONLY
69
69
 
70
+ # diagnosis is value-slot: require a value-slot label to recover from.
71
+ # No code AND no value label (e.g. dataAbsentReason, no text) -> not a gap.
72
+ val_label = stmt.value and (stmt.value.original_text or stmt.value.raw)
73
+ if not val_label:
74
+ return None
70
75
  if _has_nullflavor(stmt):
71
76
  return Icd10cmGapPattern.NULLFLAVOR
72
- if stmt.raw_text or (stmt.value and (stmt.value.original_text or stmt.value.raw)):
73
- if "/text" in (stmt.source_ref or ""):
74
- return Icd10cmGapPattern.NARRATIVE_ONLY
75
- return Icd10cmGapPattern.DISPLAY_ONLY
76
- return None
77
+ if "/text" in (stmt.source_ref or ""):
78
+ return Icd10cmGapPattern.NARRATIVE_ONLY
79
+ return Icd10cmGapPattern.DISPLAY_ONLY
77
80
 
78
81
 
79
82
  # --------------------------------------------------------------------------
@@ -117,7 +120,8 @@ def parse_gap(stmt: ClinicalStatement, pattern: Icd10cmGapPattern) -> Gap:
117
120
  "deterministic; LLM to pick among targets / add specificity.")
118
121
  elif pattern == Icd10cmGapPattern.LOCAL_CODE_ONLY and cc:
119
122
  gap.evidence["local_code"] = cc.code
120
- gap.evidence["local_system"] = (cc.system.value if cc.system else cc.raw_system)
123
+ gap.evidence["local_system"] = (cc.system.value if cc.system else None)
124
+ gap.evidence["local_system_raw"] = cc.raw_system
121
125
  gap.note = ("Crosswalk the source code → ICD-10-CM (ICD-9 → use CMS GEMs); "
122
126
  "else text + qualifier search.")
123
127
  elif pattern == Icd10cmGapPattern.BAD_CODE and cc:
@@ -77,6 +77,11 @@ def classify(stmt: ClinicalStatement) -> Optional[GapPattern]:
77
77
  if clinical_codes:
78
78
  return GapPattern.LOCAL_CODE_ONLY
79
79
 
80
+ # No usable code: a gap is only actionable if a concept label exists to
81
+ # search with. No code AND no label (e.g. dataAbsentReason with no text)
82
+ # -> nothing to fill -> not a gap.
83
+ if not stmt.raw_text:
84
+ return None
80
85
  has_nullflavor = any(c.system == System.NULLFLAVOR for c in stmt.codings)
81
86
  if has_nullflavor:
82
87
  return GapPattern.NULLFLAVOR
@@ -94,7 +99,10 @@ def parse_local_code_only(stmt: ClinicalStatement, expand_abbrev: bool = False)
94
99
  local = next((c for c in stmt.codings if c.code and c.system != System.LOINC), None)
95
100
  ev = axes.evidence_packet(stmt, expand_abbrev)
96
101
  ev["local_code"] = local.code if local else None
97
- ev["local_system"] = (local.raw_system if local else None)
102
+ # canonical system (format-independent: "CPT" whether from a CCDA OID or a
103
+ # FHIR URI) drives the crosswalk; raw is kept for provenance.
104
+ ev["local_system"] = (local.system.value if local and local.system else None)
105
+ ev["local_system_raw"] = (local.raw_system if local else None)
98
106
  return Gap(
99
107
  type=GapPattern.LOCAL_CODE_ONLY.value,
100
108
  match_key=axes.build_match_key(stmt, expand_abbrev),
@@ -68,13 +68,14 @@ def classify(stmt: ClinicalStatement) -> Optional[RxnormGapPattern]:
68
68
  if cc and cc.code and cc.system not in STRUCTURAL:
69
69
  return RxnormGapPattern.LOCAL_CODE_ONLY # local/formulary/other
70
70
 
71
+ # no usable code + no drug name -> nothing to recover -> not a gap
72
+ if not stmt.raw_text:
73
+ return None
71
74
  if _has_nullflavor(stmt):
72
75
  return RxnormGapPattern.NULLFLAVOR
73
- if stmt.raw_text:
74
- if "/text" in (stmt.source_ref or ""):
75
- return RxnormGapPattern.NARRATIVE_ONLY
76
- return RxnormGapPattern.DISPLAY_ONLY
77
- return None
76
+ if "/text" in (stmt.source_ref or ""):
77
+ return RxnormGapPattern.NARRATIVE_ONLY
78
+ return RxnormGapPattern.DISPLAY_ONLY
78
79
 
79
80
 
80
81
  # --------------------------------------------------------------------------
@@ -115,7 +116,8 @@ def parse_gap(stmt: ClinicalStatement, pattern: RxnormGapPattern) -> Gap:
115
116
 
116
117
  if pattern == RxnormGapPattern.NDC_ONLY and cc:
117
118
  gap.evidence["ndc_code"] = cc.code
118
- gap.evidence["ndc_system"] = cc.raw_system
119
+ gap.evidence["ndc_system"] = cc.system.value if cc.system else None
120
+ gap.evidence["ndc_system_raw"] = cc.raw_system
119
121
  gap.note = ("Use the NDC↔RxNorm crosswalk (RxNorm release / REST API) — "
120
122
  "deterministic; LLM only if multiple RxCUIs map.")
121
123
  elif pattern in _SOURCE_VOCAB_PATTERN.values() and cc:
@@ -123,15 +125,18 @@ def parse_gap(stmt: ClinicalStatement, pattern: RxnormGapPattern) -> Gap:
123
125
  gap.evidence["source_code"] = cc.code
124
126
  gap.evidence["source_vocab"] = vocab
125
127
  gap.evidence["source_system"] = cc.raw_system
126
- # serialize.py builds a crosswalk hint from local_code/local_system
128
+ # serialize.py builds a crosswalk hint from local_code/local_system.
129
+ # local_system is the canonical vocab (format-independent); raw kept too.
127
130
  gap.evidence["local_code"] = cc.code
128
131
  gap.evidence["local_system"] = vocab
132
+ gap.evidence["local_system_raw"] = cc.raw_system
129
133
  gap.note = (f"Crosswalk {vocab} → RxNorm via the UMLS Metathesaurus "
130
134
  f"(shared CUI) or the vendor's RxNorm map — deterministic; "
131
135
  f"LLM only if the mapping is ambiguous or 1→many.")
132
136
  elif pattern == RxnormGapPattern.LOCAL_CODE_ONLY and cc:
133
137
  gap.evidence["local_code"] = cc.code
134
- gap.evidence["local_system"] = cc.raw_system
138
+ gap.evidence["local_system"] = cc.system.value if cc.system else None
139
+ gap.evidence["local_system_raw"] = cc.raw_system
135
140
  gap.note = ("Crosswalk local/formulary code → RxNorm first; else search by "
136
141
  "ingredient + strength + dose form → SCD/SBD.")
137
142
  elif pattern == RxnormGapPattern.NULLFLAVOR:
@@ -113,16 +113,17 @@ def classify(stmt: ClinicalStatement) -> Optional[SnomedGapPattern]:
113
113
  if cc and cc.code and cc.system not in STRUCTURAL:
114
114
  return SnomedGapPattern.LOCAL_CODE_ONLY # CPT / local / other
115
115
 
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.
116
+ # no usable concept code. A gap is only actionable if a recoverable label
117
+ # exists for the concept's slot (value display/originalText for value-slot
118
+ # contexts). If there is neither a code NOR a label (e.g. dataAbsentReason
119
+ # with no value text/note), there is nothing to fill -> not a gap.
120
+ if not concept_term(stmt):
121
+ return None
119
122
  if _has_nullflavor(stmt):
120
123
  return SnomedGapPattern.NULLFLAVOR
121
- if concept_term(stmt):
122
- if "/text" in (stmt.source_ref or ""):
123
- return SnomedGapPattern.NARRATIVE_ONLY
124
- return SnomedGapPattern.DISPLAY_ONLY
125
- return None
124
+ if "/text" in (stmt.source_ref or ""):
125
+ return SnomedGapPattern.NARRATIVE_ONLY
126
+ return SnomedGapPattern.DISPLAY_ONLY
126
127
 
127
128
 
128
129
  # --------------------------------------------------------------------------
@@ -149,7 +150,8 @@ def parse_gap(stmt: ClinicalStatement, pattern: SnomedGapPattern) -> Gap:
149
150
 
150
151
  if pattern == SnomedGapPattern.LOCAL_CODE_ONLY and cc:
151
152
  gap.evidence["local_code"] = cc.code
152
- gap.evidence["local_system"] = cc.raw_system
153
+ gap.evidence["local_system"] = cc.system.value if cc.system else None
154
+ gap.evidence["local_system_raw"] = cc.raw_system
153
155
  gap.note = ("Crosswalk (system, code) → SNOMED first (e.g. CPT/local map); "
154
156
  "else hierarchy-constrained text search, then LLM.")
155
157
  elif pattern == SnomedGapPattern.ICD_ONLY and cc:
@@ -159,7 +161,8 @@ def parse_gap(stmt: ClinicalStatement, pattern: SnomedGapPattern) -> Gap:
159
161
  "LLM only to choose among multiple map targets.")
160
162
  elif pattern == SnomedGapPattern.RXNORM_ONLY and cc:
161
163
  gap.evidence["rxnorm_code"] = cc.code
162
- gap.evidence["rxnorm_system"] = cc.raw_system
164
+ gap.evidence["rxnorm_system"] = cc.system.value if cc.system else None
165
+ gap.evidence["rxnorm_system_raw"] = cc.raw_system
163
166
  gap.note = ("RxNorm-coded allergen (drug allergy) — crosswalk RxNorm → "
164
167
  "SNOMED substance/product via UMLS CUI; LLM only if the "
165
168
  "ingredient maps ambiguously.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aimedicalcoding
3
- Version: 0.3.7
3
+ Version: 0.3.9
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
@@ -80,7 +80,7 @@ Each record separates four concerns:
80
80
  "search_terms": ["BUN", "Blood Urea Nitrogen"], // text to query (raw + normalized)
81
81
  "filters": { "specimen": "...", "property": "...", "scale": "..." }, // LOINC axis filters
82
82
  "ecl": "< 404684003", // SNOMED: the candidate constraint
83
- "crosswalk": { "from_system": "LOCAL", "from_code": "BUN" }, // try first (local/ICD → target)
83
+ "crosswalk": { "from_system": "CPT", "from_code": "80061" }, // try first (local/ICD/NDC → target). from_system is the CANONICAL system (e.g. "CPT","NDC","ICD-10-CM"), identical for CCDA and FHIR; the raw OID/URI is in evidence as *_system_raw
84
84
  "checkdigit_correction": "2160-0", // BAD_CODE only
85
85
  "match_key": "…", // human summary (do NOT query verbatim)
86
86
  "suggested_action": "…"
@@ -132,7 +132,7 @@ CODE tag's — the other slot's labels are not mixed in.
132
132
  "recovery": {
133
133
  "search_terms": ["BUN", "Blood Urea Nitrogen"],
134
134
  "filters": { "specimen": "Ser/Plas", "property": "MCnc", "scale": "Qn" },
135
- "crosswalk": { "from_system": "2.16.840.1.113883.19.5.99999.1", "from_code": "BUN" },
135
+ "crosswalk": { "from_system": "LOCAL", "from_code": "BUN" },
136
136
  "match_key": "component:BUN | specimen:Ser/Plas | property:MCnc | scale:Qn | method:-",
137
137
  "suggested_action": "crosswalk local code → target; else text + filter search"
138
138
  },
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="aimedicalcoding",
5
- version="0.3.7",
5
+ version="0.3.9",
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