hccinfhir 0.2.5__py3-none-any.whl → 0.2.6__py3-none-any.whl

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.
@@ -112,11 +112,23 @@ def apply_coefficients(demographics: Demographics,
112
112
  if interaction_value < 1:
113
113
  continue
114
114
 
115
+ # Standard prefix-based lookup
115
116
  key = (f"{prefix}{interaction_key}".lower(), model_name)
116
117
  if key in coefficients:
117
118
  value = coefficients[key]
118
119
  output[interaction_key] = value
119
120
 
121
+ # No-prefix lookup for ESRD duration coefficients stored without prefix
122
+ # ESRD V21: GE65_DUR*, LT65_DUR*; ESRD V24: FGC_*, FGI_*, LTI_GE65/LT65
123
+ if (interaction_key.startswith('FGC') or
124
+ interaction_key.startswith('FGI') or
125
+ interaction_key.startswith('GE65_DUR') or
126
+ interaction_key.startswith('LT65_DUR') or
127
+ interaction_key in ('LTI_GE65', 'LTI_LT65')):
128
+ key = (interaction_key.lower(), model_name)
129
+ if key in coefficients:
130
+ value = coefficients[key]
131
+ output[interaction_key] = value
120
132
 
121
133
  return output
122
134
 
@@ -6,50 +6,145 @@ def has_any_hcc(hcc_list: List[str], hcc_set: Set[str]) -> int:
6
6
  return int(bool(set(hcc_list) & hcc_set))
7
7
 
8
8
  def create_demographic_interactions(demographics: Demographics) -> dict:
9
- """Creates common demographic-based interactions"""
9
+ """Creates common demographic-based interactions.
10
+
11
+ This function creates interaction variables that are model-agnostic.
12
+ The coefficient lookup will match only the relevant coefficients for
13
+ each model. Comments indicate which models primarily use each interaction.
14
+ """
10
15
  interactions = {}
11
- # Determine sex from demographics.sex instead of category
12
- # Category can start with 'NEM'/'NEF' for new enrollees, not just 'M'/'F'
16
+
17
+ # Common demographic flags
13
18
  is_female = demographics.sex in ('F', '2')
14
19
  is_male = demographics.sex in ('M', '1')
15
20
  is_aged = not demographics.non_aged
16
-
17
- # Original Disability interactions
21
+ lti = int(demographics.lti) if demographics.lti else 0
22
+ fbd = demographics.fbd
23
+ pbd = demographics.pbd
24
+ graft_months = demographics.graft_months
25
+
26
+ # Medicaid indicator (any dual status)
27
+ mcaid = 1 if demographics.dual_elgbl_cd in {
28
+ '01', '02', '03', '04', '05', '06', '07', '08', '09', '10'
29
+ } else 0
30
+
31
+ # Original Disability interactions (V22, V24, V28, ESRD V21, V24)
32
+ # Only for aged (65+); looked up with prefix (e.g., CNA_, DI_)
18
33
  if is_aged:
19
34
  interactions['OriginallyDisabled_Female'] = int(demographics.orig_disabled) * int(is_female)
20
35
  interactions['OriginallyDisabled_Male'] = int(demographics.orig_disabled) * int(is_male)
21
- else:
22
- interactions['OriginallyDisabled_Female'] = 0
23
- interactions['OriginallyDisabled_Male'] = 0
24
36
 
25
- # LTI interactions - used for ESRD models
26
- if demographics.lti:
37
+ # Originally ESRD interactions (ESRD V21, V24 Dialysis); looked up as DI_Originally_ESRD_*
38
+ if is_aged and demographics.orec in ('2', '3'):
39
+ interactions['Originally_ESRD_Female'] = int(is_female)
40
+ interactions['Originally_ESRD_Male'] = int(is_male)
41
+
42
+ # MCAID × sex × age interactions (ESRD V21 Dialysis and Community Graft only)
43
+ # V21 used MCAID; V24 uses FBDual/PBDual (handled in create_dual_interactions)
44
+ if mcaid:
45
+ interactions['MCAID_Female_Aged'] = int(is_female) * int(is_aged)
46
+ interactions['MCAID_Female_NonAged'] = int(is_female) * int(not is_aged)
47
+ interactions['MCAID_Male_Aged'] = int(is_male) * int(is_aged)
48
+ interactions['MCAID_Male_NonAged'] = int(is_male) * int(not is_aged)
49
+
50
+ # LTI interactions for ESRD models
51
+ if lti:
52
+ # ESRD V24 Dialysis: looked up as DI_LTI_Aged, DI_LTI_NonAged
27
53
  interactions['LTI_Aged'] = int(is_aged)
28
54
  interactions['LTI_NonAged'] = int(not is_aged)
29
- else:
30
- interactions['LTI_Aged'] = 0
31
- interactions['LTI_NonAged'] = 0
32
-
55
+ # ESRD V24 Graft Institutional: looked up WITHOUT prefix as LTI_GE65, LTI_LT65
56
+ interactions['LTI_GE65'] = int(is_aged)
57
+ interactions['LTI_LT65'] = int(not is_aged)
58
+
59
+ # LTIMCAID for V24, V28 Institutional model; looked up as INS_LTIMCAID
60
+ if lti and mcaid:
61
+ interactions['LTIMCAID'] = lti * mcaid
62
+
63
+ # New Enrollee interactions for V24, V28, ESRD V21, ESRD V24
33
64
  nemcaid = False
34
- if demographics.new_enrollee and demographics.dual_elgbl_cd in {'01', '02', '03', '04', '05', '06', '08'}:
65
+ if demographics.new_enrollee and demographics.dual_elgbl_cd in {
66
+ '01', '02', '03', '04', '05', '06', '08'
67
+ }:
35
68
  nemcaid = True
36
- ne_origds = int(demographics.age >= 65 and (demographics.orec is not None and demographics.orec == "1"))
37
-
38
- fbd = demographics.fbd
69
+ ne_origds = int(
70
+ demographics.age >= 65 and
71
+ demographics.orec is not None and
72
+ demographics.orec == "1"
73
+ )
39
74
 
40
- # Four mutually exclusive groups
75
+ # V24, V28, ESRD V21: MCAID/NMCAID style; looked up with NE_ or SNPNE_ prefix
41
76
  interactions.update({
42
77
  f'NMCAID_NORIGDIS_{demographics.category}': int(not nemcaid and not ne_origds),
43
78
  f'MCAID_NORIGDIS_{demographics.category}': int(nemcaid and not ne_origds),
44
79
  f'NMCAID_ORIGDIS_{demographics.category}': int(not nemcaid and ne_origds),
45
80
  f'MCAID_ORIGDIS_{demographics.category}': int(nemcaid and ne_origds),
81
+ })
82
+
83
+ # ESRD V24: FBD/ND_PBD style; looked up with DNE_ or GNE_ prefix
84
+ interactions.update({
46
85
  f'FBD_NORIGDIS_{demographics.category}': int(fbd and not ne_origds),
47
86
  f'FBD_ORIGDIS_{demographics.category}': int(fbd and ne_origds),
48
87
  f'ND_PBD_NORIGDIS_{demographics.category}': int(not fbd and not ne_origds),
49
88
  f'ND_PBD_ORIGDIS_{demographics.category}': int(not fbd and ne_origds)
50
89
  })
51
90
 
52
- # output only non-zero interactions
91
+ # Functioning Graft Duration "transplant bumps" for ESRD models
92
+ # All looked up WITHOUT prefix - they match directly by name
93
+ if graft_months and graft_months >= 4:
94
+ is_dur4_9 = (4 <= graft_months <= 9)
95
+ is_dur10pl = (graft_months >= 10)
96
+
97
+ # ESRD V21: simple age-based bumps (GE65_DUR4_9, LT65_DUR4_9, etc.)
98
+ if is_dur4_9:
99
+ interactions['GE65_DUR4_9'] = int(is_aged)
100
+ interactions['LT65_DUR4_9'] = int(not is_aged)
101
+ if is_dur10pl:
102
+ interactions['GE65_DUR10PL'] = int(is_aged)
103
+ interactions['LT65_DUR10PL'] = int(not is_aged)
104
+
105
+ # ESRD V24: FGC (Community) / FGI (Institutional) stratified by dual status
106
+ if not fbd:
107
+ # Non-Dual and Partial Benefit Dual (ND_PBD)
108
+ if is_dur4_9:
109
+ interactions.update({
110
+ 'FGC_GE65_DUR4_9_ND_PBD': int(is_aged) * int(not lti),
111
+ 'FGC_LT65_DUR4_9_ND_PBD': int(not is_aged) * int(not lti),
112
+ 'FGI_GE65_DUR4_9_ND_PBD': int(is_aged) * lti,
113
+ 'FGI_LT65_DUR4_9_ND_PBD': int(not is_aged) * lti,
114
+ })
115
+ if is_dur10pl:
116
+ interactions.update({
117
+ 'FGC_GE65_DUR10PL_ND_PBD': int(is_aged) * int(not lti),
118
+ 'FGC_LT65_DUR10PL_ND_PBD': int(not is_aged) * int(not lti),
119
+ 'FGI_GE65_DUR10PL_ND_PBD': int(is_aged) * lti,
120
+ 'FGI_LT65_DUR10PL_ND_PBD': int(not is_aged) * lti,
121
+ })
122
+ # Extra PBD flag for Partial Benefit Dual members
123
+ if pbd:
124
+ interactions.update({
125
+ 'FGC_PBD_GE65_flag': int(is_aged) * int(not lti),
126
+ 'FGC_PBD_LT65_flag': int(not is_aged) * int(not lti),
127
+ 'FGI_PBD_GE65_flag': int(is_aged) * lti,
128
+ 'FGI_PBD_LT65_flag': int(not is_aged) * lti,
129
+ })
130
+ else:
131
+ # Full Benefit Dual (FBD)
132
+ if is_dur4_9:
133
+ interactions.update({
134
+ 'FGC_GE65_DUR4_9_FBD': int(is_aged) * int(not lti),
135
+ 'FGC_LT65_DUR4_9_FBD': int(not is_aged) * int(not lti),
136
+ 'FGI_GE65_DUR4_9_FBD': int(is_aged) * lti,
137
+ 'FGI_LT65_DUR4_9_FBD': int(not is_aged) * lti,
138
+ })
139
+ if is_dur10pl:
140
+ interactions.update({
141
+ 'FGC_GE65_DUR10PL_FBD': int(is_aged) * int(not lti),
142
+ 'FGC_LT65_DUR10PL_FBD': int(not is_aged) * int(not lti),
143
+ 'FGI_GE65_DUR10PL_FBD': int(is_aged) * lti,
144
+ 'FGI_LT65_DUR10PL_FBD': int(not is_aged) * lti,
145
+ })
146
+
147
+ # Output only non-zero interactions
53
148
  interactions = {k: v for k, v in interactions.items() if v > 0}
54
149
 
55
150
  return interactions
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: hccinfhir
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: HCC Algorithm for FHIR Resources
5
5
  Project-URL: Homepage, https://github.com/mimilabs/hccinfhir
6
6
  Project-URL: Issues, https://github.com/mimilabs/hccinfhir/issues
@@ -9,11 +9,11 @@ hccinfhir/extractor_fhir.py,sha256=wUN3vTm1oTZ-KvfcDebnpQMxAC-7YlRKv12Wrv3p85A,8
9
9
  hccinfhir/filter.py,sha256=j_yD2g6RBXVUV9trKkWzsQ35x3fRvfKUPvEXKUefI64,2007
10
10
  hccinfhir/hccinfhir.py,sha256=NydnH3WBvuyskn76hY70LpUS6XuIEoax_kip1mgfpHw,11225
11
11
  hccinfhir/model_calculate.py,sha256=_TUWNVUsBym0pre3wltXvRuipQaONQ0QBfWPFNAeDsQ,8347
12
- hccinfhir/model_coefficients.py,sha256=5n3QzHX6FJ3MlO0cV9NS7Bqt-lxzVvT_M3zFaWq6Gng,4685
12
+ hccinfhir/model_coefficients.py,sha256=jRHip10AzMrcbaqkumxEXKjrlOSe8taQcXsGmQNzVcA,5330
13
13
  hccinfhir/model_demographics.py,sha256=nImKtJCq1HkR9w2GU8aikybJFgow71CPufBRV8Jn7fM,8932
14
14
  hccinfhir/model_dx_to_cc.py,sha256=Yjc6xKI-jMXsbOzS_chc4NI15Bwagb7BwZZ8cKQaTbk,1540
15
15
  hccinfhir/model_hierarchies.py,sha256=cboUnSHZZfOxA8QZKV4QIE-32duElssML32OqYT-65g,1542
16
- hccinfhir/model_interactions.py,sha256=g6jK27Xu8RQUHS3lk4sk2v6w6wqd52mdbGn0BsnR7Pk,21394
16
+ hccinfhir/model_interactions.py,sha256=5CHRf-YwF4jMYpd0u3XTNvGjwInb7mhOsF4L9boPsuY,25810
17
17
  hccinfhir/samples.py,sha256=2VSWS81cv9EnaHqK7sd6CjwG6FUI9E--5wHgD000REI,9952
18
18
  hccinfhir/utils.py,sha256=WQ2atW0CrdX7sAz_YRLeY4JD-CuH0o-WRusQ_xVVfgY,12152
19
19
  hccinfhir/data/__init__.py,sha256=SGiSkpGrnxbvtEFMMlk82NFHOE50hFXcgKwKUSuVZUg,45
@@ -29,8 +29,8 @@ hccinfhir/data/ra_eligible_cpt_hcpcs_2024.csv,sha256=CawKImfCb8fFMDbWwqvNLRyRAda
29
29
  hccinfhir/data/ra_eligible_cpt_hcpcs_2025.csv,sha256=-tMvv2su5tsSbGUh6fZZCMUEkXInBpcTtbUCi2o_UwI,40359
30
30
  hccinfhir/data/ra_eligible_cpt_hcpcs_2026.csv,sha256=EYGN7k_rgCpJe59lL_yNInUcCkdETDWGSFTXII3LZ0Y,40497
31
31
  hccinfhir/data/ra_hierarchies_2025.csv,sha256=HQSPNloe6mvvwMgv8ZwYAfWKkT2b2eUvm4JQy6S_mVQ,13045
32
- hccinfhir/data/ra_hierarchies_2026.csv,sha256=A6ZQZb0rpRWrySBB_KA5S4PGtMxWuzB2guU3aBE09v0,19596
33
- hccinfhir/data/ra_labels_2026.csv,sha256=YstfP7s-3ZwjP4I_GYPPj3_yn-PQK3Q0Q_MVYZhsfjY,50248
32
+ hccinfhir/data/ra_hierarchies_2026.csv,sha256=pKevSx-dYfLyO-Leruh2AFLn5uO4y49O9EOr-O6-cbY,19595
33
+ hccinfhir/data/ra_labels_2026.csv,sha256=P-Ym0np06E_CxwELdBGZZ7j5NwhXLsHoRPnp3jeYWn4,50248
34
34
  hccinfhir/sample_files/__init__.py,sha256=SGiSkpGrnxbvtEFMMlk82NFHOE50hFXcgKwKUSuVZUg,45
35
35
  hccinfhir/sample_files/sample_834_01.txt,sha256=J2HMXfY6fAFpV36rvLQ3QymRRS2TPqf3TQY6CNS7TrE,1627
36
36
  hccinfhir/sample_files/sample_834_02.txt,sha256=vSvjM69kKfOW9e-8dvlO9zDcRPpOD7LmekLu68z4aB4,926
@@ -55,7 +55,7 @@ hccinfhir/sample_files/sample_eob_1.json,sha256=_NGSVR2ysFpx-DcTvyga6dFCzhQ8Vi9f
55
55
  hccinfhir/sample_files/sample_eob_2.json,sha256=FcnJcx0ApOczxjJ_uxVLzCep9THfNf4xs9Yf7hxk8e4,1769
56
56
  hccinfhir/sample_files/sample_eob_200.ndjson,sha256=CxpjeQ1DCMUzZILaM68UEhfxO0p45YGhDDoCZeq8PxU,1917986
57
57
  hccinfhir/sample_files/sample_eob_3.json,sha256=4BW4wOMBEEU9RDfJR15rBEvk0KNHyuMEh3e055y87Hc,2306
58
- hccinfhir-0.2.5.dist-info/METADATA,sha256=fjqK-VAKUQ_zblUqz4p8qddjSZje16tYVnPGEYyzw4Q,37381
59
- hccinfhir-0.2.5.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
60
- hccinfhir-0.2.5.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
61
- hccinfhir-0.2.5.dist-info/RECORD,,
58
+ hccinfhir-0.2.6.dist-info/METADATA,sha256=rNYXVJ44S85cLd_TT-abUSjs5mLw4h-jLw8hGrJ6BsU,37381
59
+ hccinfhir-0.2.6.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
60
+ hccinfhir-0.2.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
61
+ hccinfhir-0.2.6.dist-info/RECORD,,