hccinfhir 0.1.4__tar.gz → 0.1.6__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.
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/PKG-INFO +183 -12
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/README.md +182 -11
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/__init__.py +1 -1
- hccinfhir-0.1.6/hccinfhir/data/hcc_is_chronic.csv +876 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/datamodels.py +41 -1
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/extractor_fhir.py +2 -2
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/hccinfhir.py +74 -23
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/model_calculate.py +48 -28
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/model_coefficients.py +11 -7
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/model_demographics.py +62 -12
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/model_interactions.py +34 -11
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/pyproject.toml +1 -1
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/.gitignore +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/LICENSE +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/data/__init__.py +0 -0
- /hccinfhir-0.1.4/hccinfhir/data/hcc_is_chronic.csv → /hccinfhir-0.1.6/hccinfhir/data/hcc_is_chronic_without_esrd_model.csv +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/data/ra_coefficients_2025.csv +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/data/ra_coefficients_2026.csv +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/data/ra_dx_to_cc_2025.csv +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/data/ra_dx_to_cc_2026.csv +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/data/ra_eligible_cpt_hcpcs_2023.csv +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/data/ra_eligible_cpt_hcpcs_2024.csv +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/data/ra_eligible_cpt_hcpcs_2025.csv +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/data/ra_eligible_cpt_hcpcs_2026.csv +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/data/ra_hierarchies_2025.csv +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/data/ra_hierarchies_2026.csv +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/extractor.py +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/extractor_837.py +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/filter.py +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/model_dx_to_cc.py +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/model_hierarchies.py +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/__init__.py +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_0.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_1.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_10.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_11.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_12.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_2.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_3.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_4.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_5.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_6.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_7.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_8.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_837_9.txt +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_eob_1.json +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_eob_2.json +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_eob_200.ndjson +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/sample_files/sample_eob_3.json +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/samples.py +0 -0
- {hccinfhir-0.1.4 → hccinfhir-0.1.6}/hccinfhir/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: hccinfhir
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.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
|
|
@@ -60,12 +60,12 @@ print(f"HCCs: {result.hcc_list}")
|
|
|
60
60
|
HCCInFHIR supports three primary data sources for HCC risk adjustment calculations:
|
|
61
61
|
|
|
62
62
|
### 1. **CMS Encounter Data Records (EDRs)**
|
|
63
|
-
- **Input**: X12 837
|
|
63
|
+
- **Input**: X12 837 5010 transaction files (text format) + demographic data from payers
|
|
64
64
|
- **Use Case**: Medicare Advantage plans processing encounter data for CMS submissions
|
|
65
65
|
- **Output**: Risk scores with detailed HCC mappings and interactions
|
|
66
66
|
|
|
67
67
|
### 2. **Clearinghouse 837 Claims**
|
|
68
|
-
- **Input**: X12 837 institutional/professional claim files + patient demographics
|
|
68
|
+
- **Input**: X12 837 5010 institutional/professional claim files + patient demographics
|
|
69
69
|
- **Use Case**: Health plans and providers calculating risk scores from claims data
|
|
70
70
|
- **Output**: Service-level analysis with filtering and risk score calculations
|
|
71
71
|
|
|
@@ -535,6 +535,89 @@ export_data = result.model_dump(
|
|
|
535
535
|
)
|
|
536
536
|
```
|
|
537
537
|
|
|
538
|
+
### Overriding Demographic Categorization
|
|
539
|
+
|
|
540
|
+
**Problem**: Sometimes demographic data has quality issues (e.g., ESRD patients with incorrect `orec`/`crec` codes), leading to wrong risk score calculations.
|
|
541
|
+
|
|
542
|
+
**Solution**: Use the `prefix_override` parameter to manually specify the coefficient prefix.
|
|
543
|
+
|
|
544
|
+
#### Common Use Case: ESRD Patients with Incorrect OREC/CREC
|
|
545
|
+
|
|
546
|
+
```python
|
|
547
|
+
from hccinfhir import HCCInFHIR, Demographics
|
|
548
|
+
|
|
549
|
+
# ESRD dialysis patient, but source data has wrong orec/crec codes
|
|
550
|
+
processor = HCCInFHIR(model_name="CMS-HCC ESRD Model V24")
|
|
551
|
+
|
|
552
|
+
demographics = Demographics(
|
|
553
|
+
age=65,
|
|
554
|
+
sex="F",
|
|
555
|
+
orec="0", # Should be '2' or '3' for ESRD, but data is incorrect
|
|
556
|
+
crec="0" # Should be '2' or '3' for ESRD, but data is incorrect
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
diagnosis_codes = ["N18.6", "E11.22", "I12.0"] # ESRD + diabetes + hypertensive CKD
|
|
560
|
+
|
|
561
|
+
# Force ESRD dialysis coefficients despite incorrect orec/crec
|
|
562
|
+
result = processor.calculate_from_diagnosis(
|
|
563
|
+
diagnosis_codes,
|
|
564
|
+
demographics,
|
|
565
|
+
prefix_override='DI_' # DI_ = ESRD Dialysis
|
|
566
|
+
)
|
|
567
|
+
|
|
568
|
+
print(f"Risk Score with override: {result.risk_score}")
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
#### Other Common Scenarios
|
|
572
|
+
|
|
573
|
+
```python
|
|
574
|
+
# Long-term institutionalized patient not properly flagged
|
|
575
|
+
processor = HCCInFHIR(model_name="CMS-HCC Model V28")
|
|
576
|
+
demographics = Demographics(age=78, sex="M")
|
|
577
|
+
diagnosis_codes = ["F03.90", "I48.91", "N18.4"]
|
|
578
|
+
|
|
579
|
+
result = processor.calculate_from_diagnosis(
|
|
580
|
+
diagnosis_codes,
|
|
581
|
+
demographics,
|
|
582
|
+
prefix_override='INS_' # INS_ = Institutionalized
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
# New enrollee with missing flag
|
|
586
|
+
result = processor.calculate_from_diagnosis(
|
|
587
|
+
diagnosis_codes,
|
|
588
|
+
demographics,
|
|
589
|
+
prefix_override='NE_' # NE_ = New Enrollee
|
|
590
|
+
)
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
#### Common Prefix Values
|
|
594
|
+
|
|
595
|
+
**CMS-HCC Models (V22, V24, V28):**
|
|
596
|
+
- `CNA_` - Community, Non-Dual, Aged (65+)
|
|
597
|
+
- `CND_` - Community, Non-Dual, Disabled (<65)
|
|
598
|
+
- `CFA_` - Community, Full Benefit Dual, Aged
|
|
599
|
+
- `CFD_` - Community, Full Benefit Dual, Disabled
|
|
600
|
+
- `CPA_` - Community, Partial Benefit Dual, Aged
|
|
601
|
+
- `CPD_` - Community, Partial Benefit Dual, Disabled
|
|
602
|
+
- `INS_` - Long-Term Institutionalized
|
|
603
|
+
- `NE_` - New Enrollee
|
|
604
|
+
- `SNPNE_` - Special Needs Plan New Enrollee
|
|
605
|
+
|
|
606
|
+
**ESRD Models (V21, V24):**
|
|
607
|
+
- `DI_` - Dialysis (standard)
|
|
608
|
+
- `DNE_` - Dialysis New Enrollee
|
|
609
|
+
- `GI_` - Graft, Institutionalized
|
|
610
|
+
- `GNE_` - Graft, New Enrollee
|
|
611
|
+
- `GFPA_`, `GFPN_`, `GNPA_`, `GNPN_` - Graft with various dual/age combinations
|
|
612
|
+
|
|
613
|
+
**RxHCC Model (V08):**
|
|
614
|
+
- `Rx_CE_LowAged_` - Community, Low Income, Aged
|
|
615
|
+
- `Rx_CE_NoLowAged_` - Community, Not Low Income, Aged
|
|
616
|
+
- `Rx_NE_Lo_` - New Enrollee, Low Income
|
|
617
|
+
- `Rx_CE_LTI_` - Community, Long-Term Institutionalized
|
|
618
|
+
|
|
619
|
+
See [CLAUDE.md](./CLAUDE.md#coefficient-prefix-reference) for complete prefix reference.
|
|
620
|
+
|
|
538
621
|
### Custom Filtering Rules
|
|
539
622
|
|
|
540
623
|
```python
|
|
@@ -544,7 +627,7 @@ from hccinfhir.filter import apply_filter
|
|
|
544
627
|
filtered_data = apply_filter(
|
|
545
628
|
service_data,
|
|
546
629
|
include_inpatient=True,
|
|
547
|
-
include_outpatient=True,
|
|
630
|
+
include_outpatient=True,
|
|
548
631
|
eligible_cpt_hcpcs_file="custom_procedures.csv"
|
|
549
632
|
)
|
|
550
633
|
```
|
|
@@ -579,17 +662,105 @@ except ModelNotFoundError as e:
|
|
|
579
662
|
print(f"Model configuration error: {e}")
|
|
580
663
|
```
|
|
581
664
|
|
|
582
|
-
|
|
665
|
+
### Custom Valuesets
|
|
583
666
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
667
|
+
Users can generate custom and more specific valuesets using the mimilabs data lakehouse.
|
|
668
|
+
|
|
669
|
+
For example, the valuesets in the package are created as follows:
|
|
670
|
+
|
|
671
|
+
`ra_dx_to_cc_mapping_2026.csv`
|
|
672
|
+
```sql
|
|
673
|
+
WITH latest_years AS (
|
|
674
|
+
SELECT
|
|
675
|
+
model_name,
|
|
676
|
+
MAX(year) as latest_year
|
|
677
|
+
FROM mimi_ws_1.cmspayment.ra_dx_to_cc_mapping
|
|
678
|
+
WHERE model_type = 'Initial'
|
|
679
|
+
AND year <= 2026 -- Don't go beyond 2026
|
|
680
|
+
GROUP BY model_name
|
|
681
|
+
)
|
|
682
|
+
SELECT
|
|
683
|
+
r.diagnosis_code,
|
|
684
|
+
r.cc,
|
|
685
|
+
r.model_name
|
|
686
|
+
FROM mimi_ws_1.cmspayment.ra_dx_to_cc_mapping r
|
|
687
|
+
INNER JOIN latest_years l
|
|
688
|
+
ON r.model_name = l.model_name
|
|
689
|
+
AND r.year = l.latest_year
|
|
690
|
+
WHERE r.model_type = 'Initial'
|
|
691
|
+
ORDER BY r.model_name, r.diagnosis_code;
|
|
692
|
+
```
|
|
587
693
|
|
|
588
|
-
|
|
589
|
-
|
|
694
|
+
`ra_hierarchies_2026.csv`
|
|
695
|
+
```sql
|
|
696
|
+
WITH latest_dates AS (
|
|
697
|
+
SELECT
|
|
698
|
+
model_domain,
|
|
699
|
+
model_version,
|
|
700
|
+
model_fullname,
|
|
701
|
+
MAX(eff_last_date) as latest_eff_last_date
|
|
702
|
+
FROM mimi_ws_1.cmspayment.ra_hierarchies
|
|
703
|
+
GROUP BY model_domain, model_version, model_fullname
|
|
704
|
+
)
|
|
705
|
+
SELECT
|
|
706
|
+
r.cc_parent,
|
|
707
|
+
r.cc_child,
|
|
708
|
+
r.model_domain,
|
|
709
|
+
r.model_version,
|
|
710
|
+
r.model_fullname
|
|
711
|
+
FROM mimi_ws_1.cmspayment.ra_hierarchies r
|
|
712
|
+
INNER JOIN latest_dates l
|
|
713
|
+
ON r.model_domain = l.model_domain
|
|
714
|
+
AND r.model_version = l.model_version
|
|
715
|
+
AND r.model_fullname = l.model_fullname
|
|
716
|
+
AND r.eff_last_date = l.latest_eff_last_date
|
|
717
|
+
ORDER BY r.model_domain, r.model_version, r.model_fullname, r.cc_parent, r.cc_child;
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
`ra_coefficients_2026.csv`
|
|
722
|
+
```sql
|
|
723
|
+
WITH preferred_records AS (
|
|
724
|
+
SELECT
|
|
725
|
+
model_domain,
|
|
726
|
+
model_version,
|
|
727
|
+
MAX(eff_last_date) as latest_eff_last_date
|
|
728
|
+
FROM mimi_ws_1.cmspayment.ra_coefficients
|
|
729
|
+
GROUP BY model_domain, model_version
|
|
730
|
+
)
|
|
731
|
+
SELECT
|
|
732
|
+
r.coefficient,
|
|
733
|
+
r.value,
|
|
734
|
+
r.model_domain,
|
|
735
|
+
r.model_version
|
|
736
|
+
FROM mimi_ws_1.cmspayment.ra_coefficients r
|
|
737
|
+
INNER JOIN preferred_records p
|
|
738
|
+
ON r.model_domain = p.model_domain
|
|
739
|
+
AND r.model_version = p.model_version
|
|
740
|
+
AND r.eff_last_date = p.latest_eff_last_date
|
|
741
|
+
ORDER BY r.model_domain, r.model_version, r.coefficient;
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
`ra_eligible_cpt_hcpcs_2026.csv`
|
|
745
|
+
```sql
|
|
746
|
+
SELECT DISTINCT cpt_hcpcs_code
|
|
747
|
+
FROM mimi_ws_1.cmspayment.ra_eligible_cpt_hcpcs
|
|
748
|
+
WHERE is_included = 'yes' AND YEAR(mimi_src_file_date) = 2025;
|
|
749
|
+
```
|
|
590
750
|
|
|
591
|
-
|
|
592
|
-
|
|
751
|
+
`hcc_is_chronic.csv`
|
|
752
|
+
```sql
|
|
753
|
+
SELECT hcc, is_chronic, model_version, model_domain
|
|
754
|
+
FROM cmspayment.ra_report_to_congress
|
|
755
|
+
WHERE mimi_src_file_name = '2024riskadjustmentinma-rtc.pdf'
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
## 🧪 Testing
|
|
759
|
+
|
|
760
|
+
```bash
|
|
761
|
+
$ hatch shell
|
|
762
|
+
$ pip install -e .
|
|
763
|
+
$ pytest tests/*
|
|
593
764
|
```
|
|
594
765
|
|
|
595
766
|
## 📄 License
|
|
@@ -46,12 +46,12 @@ print(f"HCCs: {result.hcc_list}")
|
|
|
46
46
|
HCCInFHIR supports three primary data sources for HCC risk adjustment calculations:
|
|
47
47
|
|
|
48
48
|
### 1. **CMS Encounter Data Records (EDRs)**
|
|
49
|
-
- **Input**: X12 837
|
|
49
|
+
- **Input**: X12 837 5010 transaction files (text format) + demographic data from payers
|
|
50
50
|
- **Use Case**: Medicare Advantage plans processing encounter data for CMS submissions
|
|
51
51
|
- **Output**: Risk scores with detailed HCC mappings and interactions
|
|
52
52
|
|
|
53
53
|
### 2. **Clearinghouse 837 Claims**
|
|
54
|
-
- **Input**: X12 837 institutional/professional claim files + patient demographics
|
|
54
|
+
- **Input**: X12 837 5010 institutional/professional claim files + patient demographics
|
|
55
55
|
- **Use Case**: Health plans and providers calculating risk scores from claims data
|
|
56
56
|
- **Output**: Service-level analysis with filtering and risk score calculations
|
|
57
57
|
|
|
@@ -521,6 +521,89 @@ export_data = result.model_dump(
|
|
|
521
521
|
)
|
|
522
522
|
```
|
|
523
523
|
|
|
524
|
+
### Overriding Demographic Categorization
|
|
525
|
+
|
|
526
|
+
**Problem**: Sometimes demographic data has quality issues (e.g., ESRD patients with incorrect `orec`/`crec` codes), leading to wrong risk score calculations.
|
|
527
|
+
|
|
528
|
+
**Solution**: Use the `prefix_override` parameter to manually specify the coefficient prefix.
|
|
529
|
+
|
|
530
|
+
#### Common Use Case: ESRD Patients with Incorrect OREC/CREC
|
|
531
|
+
|
|
532
|
+
```python
|
|
533
|
+
from hccinfhir import HCCInFHIR, Demographics
|
|
534
|
+
|
|
535
|
+
# ESRD dialysis patient, but source data has wrong orec/crec codes
|
|
536
|
+
processor = HCCInFHIR(model_name="CMS-HCC ESRD Model V24")
|
|
537
|
+
|
|
538
|
+
demographics = Demographics(
|
|
539
|
+
age=65,
|
|
540
|
+
sex="F",
|
|
541
|
+
orec="0", # Should be '2' or '3' for ESRD, but data is incorrect
|
|
542
|
+
crec="0" # Should be '2' or '3' for ESRD, but data is incorrect
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
diagnosis_codes = ["N18.6", "E11.22", "I12.0"] # ESRD + diabetes + hypertensive CKD
|
|
546
|
+
|
|
547
|
+
# Force ESRD dialysis coefficients despite incorrect orec/crec
|
|
548
|
+
result = processor.calculate_from_diagnosis(
|
|
549
|
+
diagnosis_codes,
|
|
550
|
+
demographics,
|
|
551
|
+
prefix_override='DI_' # DI_ = ESRD Dialysis
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
print(f"Risk Score with override: {result.risk_score}")
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
#### Other Common Scenarios
|
|
558
|
+
|
|
559
|
+
```python
|
|
560
|
+
# Long-term institutionalized patient not properly flagged
|
|
561
|
+
processor = HCCInFHIR(model_name="CMS-HCC Model V28")
|
|
562
|
+
demographics = Demographics(age=78, sex="M")
|
|
563
|
+
diagnosis_codes = ["F03.90", "I48.91", "N18.4"]
|
|
564
|
+
|
|
565
|
+
result = processor.calculate_from_diagnosis(
|
|
566
|
+
diagnosis_codes,
|
|
567
|
+
demographics,
|
|
568
|
+
prefix_override='INS_' # INS_ = Institutionalized
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
# New enrollee with missing flag
|
|
572
|
+
result = processor.calculate_from_diagnosis(
|
|
573
|
+
diagnosis_codes,
|
|
574
|
+
demographics,
|
|
575
|
+
prefix_override='NE_' # NE_ = New Enrollee
|
|
576
|
+
)
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
#### Common Prefix Values
|
|
580
|
+
|
|
581
|
+
**CMS-HCC Models (V22, V24, V28):**
|
|
582
|
+
- `CNA_` - Community, Non-Dual, Aged (65+)
|
|
583
|
+
- `CND_` - Community, Non-Dual, Disabled (<65)
|
|
584
|
+
- `CFA_` - Community, Full Benefit Dual, Aged
|
|
585
|
+
- `CFD_` - Community, Full Benefit Dual, Disabled
|
|
586
|
+
- `CPA_` - Community, Partial Benefit Dual, Aged
|
|
587
|
+
- `CPD_` - Community, Partial Benefit Dual, Disabled
|
|
588
|
+
- `INS_` - Long-Term Institutionalized
|
|
589
|
+
- `NE_` - New Enrollee
|
|
590
|
+
- `SNPNE_` - Special Needs Plan New Enrollee
|
|
591
|
+
|
|
592
|
+
**ESRD Models (V21, V24):**
|
|
593
|
+
- `DI_` - Dialysis (standard)
|
|
594
|
+
- `DNE_` - Dialysis New Enrollee
|
|
595
|
+
- `GI_` - Graft, Institutionalized
|
|
596
|
+
- `GNE_` - Graft, New Enrollee
|
|
597
|
+
- `GFPA_`, `GFPN_`, `GNPA_`, `GNPN_` - Graft with various dual/age combinations
|
|
598
|
+
|
|
599
|
+
**RxHCC Model (V08):**
|
|
600
|
+
- `Rx_CE_LowAged_` - Community, Low Income, Aged
|
|
601
|
+
- `Rx_CE_NoLowAged_` - Community, Not Low Income, Aged
|
|
602
|
+
- `Rx_NE_Lo_` - New Enrollee, Low Income
|
|
603
|
+
- `Rx_CE_LTI_` - Community, Long-Term Institutionalized
|
|
604
|
+
|
|
605
|
+
See [CLAUDE.md](./CLAUDE.md#coefficient-prefix-reference) for complete prefix reference.
|
|
606
|
+
|
|
524
607
|
### Custom Filtering Rules
|
|
525
608
|
|
|
526
609
|
```python
|
|
@@ -530,7 +613,7 @@ from hccinfhir.filter import apply_filter
|
|
|
530
613
|
filtered_data = apply_filter(
|
|
531
614
|
service_data,
|
|
532
615
|
include_inpatient=True,
|
|
533
|
-
include_outpatient=True,
|
|
616
|
+
include_outpatient=True,
|
|
534
617
|
eligible_cpt_hcpcs_file="custom_procedures.csv"
|
|
535
618
|
)
|
|
536
619
|
```
|
|
@@ -565,17 +648,105 @@ except ModelNotFoundError as e:
|
|
|
565
648
|
print(f"Model configuration error: {e}")
|
|
566
649
|
```
|
|
567
650
|
|
|
568
|
-
|
|
651
|
+
### Custom Valuesets
|
|
569
652
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
653
|
+
Users can generate custom and more specific valuesets using the mimilabs data lakehouse.
|
|
654
|
+
|
|
655
|
+
For example, the valuesets in the package are created as follows:
|
|
656
|
+
|
|
657
|
+
`ra_dx_to_cc_mapping_2026.csv`
|
|
658
|
+
```sql
|
|
659
|
+
WITH latest_years AS (
|
|
660
|
+
SELECT
|
|
661
|
+
model_name,
|
|
662
|
+
MAX(year) as latest_year
|
|
663
|
+
FROM mimi_ws_1.cmspayment.ra_dx_to_cc_mapping
|
|
664
|
+
WHERE model_type = 'Initial'
|
|
665
|
+
AND year <= 2026 -- Don't go beyond 2026
|
|
666
|
+
GROUP BY model_name
|
|
667
|
+
)
|
|
668
|
+
SELECT
|
|
669
|
+
r.diagnosis_code,
|
|
670
|
+
r.cc,
|
|
671
|
+
r.model_name
|
|
672
|
+
FROM mimi_ws_1.cmspayment.ra_dx_to_cc_mapping r
|
|
673
|
+
INNER JOIN latest_years l
|
|
674
|
+
ON r.model_name = l.model_name
|
|
675
|
+
AND r.year = l.latest_year
|
|
676
|
+
WHERE r.model_type = 'Initial'
|
|
677
|
+
ORDER BY r.model_name, r.diagnosis_code;
|
|
678
|
+
```
|
|
573
679
|
|
|
574
|
-
|
|
575
|
-
|
|
680
|
+
`ra_hierarchies_2026.csv`
|
|
681
|
+
```sql
|
|
682
|
+
WITH latest_dates AS (
|
|
683
|
+
SELECT
|
|
684
|
+
model_domain,
|
|
685
|
+
model_version,
|
|
686
|
+
model_fullname,
|
|
687
|
+
MAX(eff_last_date) as latest_eff_last_date
|
|
688
|
+
FROM mimi_ws_1.cmspayment.ra_hierarchies
|
|
689
|
+
GROUP BY model_domain, model_version, model_fullname
|
|
690
|
+
)
|
|
691
|
+
SELECT
|
|
692
|
+
r.cc_parent,
|
|
693
|
+
r.cc_child,
|
|
694
|
+
r.model_domain,
|
|
695
|
+
r.model_version,
|
|
696
|
+
r.model_fullname
|
|
697
|
+
FROM mimi_ws_1.cmspayment.ra_hierarchies r
|
|
698
|
+
INNER JOIN latest_dates l
|
|
699
|
+
ON r.model_domain = l.model_domain
|
|
700
|
+
AND r.model_version = l.model_version
|
|
701
|
+
AND r.model_fullname = l.model_fullname
|
|
702
|
+
AND r.eff_last_date = l.latest_eff_last_date
|
|
703
|
+
ORDER BY r.model_domain, r.model_version, r.model_fullname, r.cc_parent, r.cc_child;
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
`ra_coefficients_2026.csv`
|
|
708
|
+
```sql
|
|
709
|
+
WITH preferred_records AS (
|
|
710
|
+
SELECT
|
|
711
|
+
model_domain,
|
|
712
|
+
model_version,
|
|
713
|
+
MAX(eff_last_date) as latest_eff_last_date
|
|
714
|
+
FROM mimi_ws_1.cmspayment.ra_coefficients
|
|
715
|
+
GROUP BY model_domain, model_version
|
|
716
|
+
)
|
|
717
|
+
SELECT
|
|
718
|
+
r.coefficient,
|
|
719
|
+
r.value,
|
|
720
|
+
r.model_domain,
|
|
721
|
+
r.model_version
|
|
722
|
+
FROM mimi_ws_1.cmspayment.ra_coefficients r
|
|
723
|
+
INNER JOIN preferred_records p
|
|
724
|
+
ON r.model_domain = p.model_domain
|
|
725
|
+
AND r.model_version = p.model_version
|
|
726
|
+
AND r.eff_last_date = p.latest_eff_last_date
|
|
727
|
+
ORDER BY r.model_domain, r.model_version, r.coefficient;
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
`ra_eligible_cpt_hcpcs_2026.csv`
|
|
731
|
+
```sql
|
|
732
|
+
SELECT DISTINCT cpt_hcpcs_code
|
|
733
|
+
FROM mimi_ws_1.cmspayment.ra_eligible_cpt_hcpcs
|
|
734
|
+
WHERE is_included = 'yes' AND YEAR(mimi_src_file_date) = 2025;
|
|
735
|
+
```
|
|
576
736
|
|
|
577
|
-
|
|
578
|
-
|
|
737
|
+
`hcc_is_chronic.csv`
|
|
738
|
+
```sql
|
|
739
|
+
SELECT hcc, is_chronic, model_version, model_domain
|
|
740
|
+
FROM cmspayment.ra_report_to_congress
|
|
741
|
+
WHERE mimi_src_file_name = '2024riskadjustmentinma-rtc.pdf'
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
## 🧪 Testing
|
|
745
|
+
|
|
746
|
+
```bash
|
|
747
|
+
$ hatch shell
|
|
748
|
+
$ pip install -e .
|
|
749
|
+
$ pytest tests/*
|
|
579
750
|
```
|
|
580
751
|
|
|
581
752
|
## 📄 License
|