Split dev/ flat directory into dev/scripts/ (29 .py files) and dev/seeds/ (PDFs, Excel, ZIPs, NDJSON, grafana, PY2023). Update all Path(__file__) references to use parents[2] for project root and dev/seeds/ for seed data. Fix path references in src/ too. Add PY2024 CMS quality measure value sets (HWR, UAMCC, ACR) to the REGISTRY and load into DuckDB — enables 2024->2025->2026 diffs. Add HWR tables to notebook DIFF_SPECS now that two years exist.
340 lines
14 KiB
Python
340 lines
14 KiB
Python
"""Generate ALR reference code tables from ALRASRGuide.pdf appendix.
|
|
|
|
Extracts Appendix Tables 3, 4, and 5 (pages 41-46) containing:
|
|
- Primary care service codes (CPT/HCPCS)
|
|
- Physician specialty codes
|
|
- Non-physician practitioner codes
|
|
|
|
Generates SQLTable models at ``src/aco/table/alr_codes.py``.
|
|
|
|
Usage::
|
|
|
|
uv run python dev/scripts/generate_alr_reference_tables.py
|
|
|
|
Source: dev/ALRASRGuide.pdf
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
def extract_reference_codes() -> dict:
|
|
"""Extract reference code tables from ALRASRGuide.pdf appendix.
|
|
|
|
Returns dict with keys: primary_care_codes, physician_specialty_codes,
|
|
non_physician_codes.
|
|
"""
|
|
|
|
# Appendix Table 3: Primary Care Service Codes (pages 41-44)
|
|
# Manually extracted from PDF - comprehensive list
|
|
primary_care_codes = [
|
|
# CPT codes
|
|
("96160", "CPT", "Health Risk Assessment", None),
|
|
("96161", "CPT", "Health Risk Assessment", None),
|
|
("96202", "CPT", "Caregiver Services", None),
|
|
("96203", "CPT", "Caregiver Services", None),
|
|
("97550", "CPT", "Caregiver Services", None),
|
|
("97551", "CPT", "Caregiver Services", None),
|
|
("97552", "CPT", "Caregiver Services", None),
|
|
("99201", "CPT", "New Patient Office Visit", None),
|
|
("99202", "CPT", "New Patient Office Visit", None),
|
|
("99203", "CPT", "New Patient Office Visit", None),
|
|
("99204", "CPT", "New Patient Office Visit", None),
|
|
("99205", "CPT", "New Patient Office Visit", None),
|
|
("99211", "CPT", "Established Patient Office Visit", None),
|
|
("99212", "CPT", "Established Patient Office Visit", None),
|
|
("99213", "CPT", "Established Patient Office Visit", None),
|
|
("99214", "CPT", "Established Patient Office Visit", None),
|
|
("99215", "CPT", "Established Patient Office Visit", None),
|
|
("99304", "CPT", "Nursing Facility Initial Care", "Exclude if in SNF"),
|
|
("99305", "CPT", "Nursing Facility Initial Care", "Exclude if in SNF"),
|
|
("99306", "CPT", "Nursing Facility Initial Care", "Exclude if in SNF"),
|
|
("99307", "CPT", "Nursing Facility Subsequent Care", "Exclude if in SNF"),
|
|
("99308", "CPT", "Nursing Facility Subsequent Care", "Exclude if in SNF"),
|
|
("99309", "CPT", "Nursing Facility Subsequent Care", "Exclude if in SNF"),
|
|
("99310", "CPT", "Nursing Facility Subsequent Care", "Exclude if in SNF"),
|
|
("99315", "CPT", "Nursing Facility Discharge", "Exclude if in SNF"),
|
|
("99316", "CPT", "Nursing Facility Discharge", "Exclude if in SNF"),
|
|
("99318", "CPT", "Nursing Facility Annual Assessment", "Exclude if in SNF"),
|
|
("99324", "CPT", "Domiciliary/Rest Home New Patient", None),
|
|
("99325", "CPT", "Domiciliary/Rest Home New Patient", None),
|
|
("99326", "CPT", "Domiciliary/Rest Home New Patient", None),
|
|
("99327", "CPT", "Domiciliary/Rest Home New Patient", None),
|
|
("99328", "CPT", "Domiciliary/Rest Home New Patient", None),
|
|
("99334", "CPT", "Domiciliary/Rest Home Established Patient", None),
|
|
("99335", "CPT", "Domiciliary/Rest Home Established Patient", None),
|
|
("99336", "CPT", "Domiciliary/Rest Home Established Patient", None),
|
|
("99337", "CPT", "Domiciliary/Rest Home Established Patient", None),
|
|
("99339", "CPT", "Individual Physician Supervision", None),
|
|
("99340", "CPT", "Individual Physician Supervision", None),
|
|
("99341", "CPT", "Home Visit New Patient", None),
|
|
("99342", "CPT", "Home Visit New Patient", None),
|
|
("99343", "CPT", "Home Visit New Patient", None),
|
|
("99344", "CPT", "Home Visit New Patient", None),
|
|
("99345", "CPT", "Home Visit New Patient", None),
|
|
("99347", "CPT", "Home Visit Established Patient", None),
|
|
("99348", "CPT", "Home Visit Established Patient", None),
|
|
("99349", "CPT", "Home Visit Established Patient", None),
|
|
("99350", "CPT", "Home Visit Established Patient", None),
|
|
("99354", "CPT", "Prolonged Services", None),
|
|
("99355", "CPT", "Prolonged Services", None),
|
|
("99406", "CPT", "Smoking Cessation 3-10 min", None),
|
|
("99407", "CPT", "Smoking Cessation >10 min", None),
|
|
("99421", "CPT", "Online Digital E&M 5-10 min", None),
|
|
("99422", "CPT", "Online Digital E&M 11-20 min", None),
|
|
("99423", "CPT", "Online Digital E&M 21+ min", None),
|
|
("99424", "CPT", "Principal Care Management first 30 min", None),
|
|
("99425", "CPT", "Principal Care Management each additional 30 min", None),
|
|
("99426", "CPT", "Principal Care Management initial", None),
|
|
("99427", "CPT", "Principal Care Management subsequent", None),
|
|
("99437", "CPT", "Chronic Care Management", None),
|
|
("99439", "CPT", "Chronic Care Management", None),
|
|
("99441", "CPT", "Telephone E&M 5-10 min (COVID PHE)", None),
|
|
("99442", "CPT", "Telephone E&M 11-20 min (COVID PHE)", None),
|
|
("99443", "CPT", "Telephone E&M 21-30 min (COVID PHE)", None),
|
|
("99483", "CPT", "Cognitive Impairment Assessment", None),
|
|
("99484", "CPT", "Behavioral Health Integration first 20 min", None),
|
|
("99487", "CPT", "Complex Chronic Care Management first 60 min", None),
|
|
(
|
|
"99489",
|
|
"CPT",
|
|
"Complex Chronic Care Management each additional 30 min",
|
|
None,
|
|
),
|
|
("99490", "CPT", "Chronic Care Management first 20 min", None),
|
|
("99491", "CPT", "Chronic Care Management 30 min", None),
|
|
("99492", "CPT", "Behavioral Health Integration initial", None),
|
|
("99493", "CPT", "Behavioral Health Integration subsequent", None),
|
|
("99494", "CPT", "Behavioral Health Integration subsequent", None),
|
|
("99495", "CPT", "Transitional Care 14 days", None),
|
|
("99496", "CPT", "Transitional Care 7 days", None),
|
|
("99497", "CPT", "Advance Care Planning first 30 min", "Exclude if inpatient"),
|
|
(
|
|
"99498",
|
|
"CPT",
|
|
"Advance Care Planning each additional 30 min",
|
|
"Exclude if inpatient",
|
|
),
|
|
# HCPCS codes
|
|
("G0019", "HCPCS", "Community Health Integration", None),
|
|
("G0022", "HCPCS", "Community Health Integration", None),
|
|
("G0023", "HCPCS", "Principal Illness Navigation first 60 min", None),
|
|
("G0024", "HCPCS", "Principal Illness Navigation each additional 30 min", None),
|
|
("G0101", "HCPCS", "Cervical/Vaginal Cancer Screening", None),
|
|
("G0136", "HCPCS", "Social Determinants of Health Assessment", None),
|
|
("G0317", "HCPCS", "Prolonged E&M first hour", None),
|
|
("G0318", "HCPCS", "Prolonged E&M each additional 30 min", None),
|
|
("G0402", "HCPCS", "Welcome to Medicare Visit", None),
|
|
("G0438", "HCPCS", "Annual Wellness Visit initial", None),
|
|
("G0439", "HCPCS", "Annual Wellness Visit subsequent", None),
|
|
("G0442", "HCPCS", "Alcohol Misuse Screening 15 min", None),
|
|
("G0443", "HCPCS", "Alcohol Misuse Counseling", None),
|
|
("G0444", "HCPCS", "Depression Screening Annual", None),
|
|
(
|
|
"G0463",
|
|
"HCPCS",
|
|
"Hospital Outpatient Clinic Visit (ETA hospitals only)",
|
|
None,
|
|
),
|
|
("G0506", "HCPCS", "Chronic Care Management", None),
|
|
("G2010", "HCPCS", "Remote Evaluation Video/Images", None),
|
|
("G2012", "HCPCS", "Virtual Check-In 5-10 min", None),
|
|
("G2058", "HCPCS", "Care Management Services for BHI", None),
|
|
("G2064", "HCPCS", "Care Management Services 20 min", None),
|
|
("G2065", "HCPCS", "Care Management Services 40 min", None),
|
|
("G2086", "HCPCS", "Opioid Use Disorder Treatment 70-100 min", None),
|
|
("G2087", "HCPCS", "Opioid Use Disorder Treatment 100-130 min", None),
|
|
("G2088", "HCPCS", "Opioid Use Disorder Treatment 130+ min", None),
|
|
("G2211", "HCPCS", "Complex E&M Add-on", None),
|
|
("G2212", "HCPCS", "Prolonged Office E&M", None),
|
|
("G2214", "HCPCS", "Chronic Pain Management", None),
|
|
("G2252", "HCPCS", "Communication Technology Services Brief", None),
|
|
("G3002", "HCPCS", "Chronic Pain Management Initial", None),
|
|
("G3003", "HCPCS", "Chronic Pain Management Subsequent", None),
|
|
]
|
|
|
|
# Appendix Table 4: Physician Specialty Codes (page 45)
|
|
physician_specialty_codes = [
|
|
# Step 1: Primary Care Physicians
|
|
("01", 1, "General Practice"),
|
|
("08", 1, "Family Practice"),
|
|
("11", 1, "Internal Medicine"),
|
|
("37", 1, "Pediatric Medicine"),
|
|
("38", 1, "Geriatric Medicine"),
|
|
# Step 2: Specialist Physicians
|
|
("06", 2, "Cardiology"),
|
|
("12", 2, "Osteopathic Manipulative Medicine"),
|
|
("13", 2, "Neurology"),
|
|
("16", 2, "Obstetrics/Gynecology"),
|
|
("23", 2, "Sports Medicine"),
|
|
("25", 2, "Physical Medicine and Rehabilitation"),
|
|
("26", 2, "Psychiatry"),
|
|
("27", 2, "Geriatric Psychiatry"),
|
|
("29", 2, "Pulmonary Disease"),
|
|
("39", 2, "Nephrology"),
|
|
("46", 2, "Endocrinology"),
|
|
("70", 2, "Multispecialty Clinic/Group"),
|
|
("79", 2, "Addiction Medicine"),
|
|
("82", 2, "Hematology"),
|
|
("83", 2, "Hematology/Oncology"),
|
|
("84", 2, "Preventive Medicine"),
|
|
("86", 2, "Neuropsychiatry"),
|
|
("90", 2, "Medical Oncology"),
|
|
("98", 2, "Gynecology/Oncology"),
|
|
]
|
|
|
|
# Appendix Table 5: Non-Physician Practitioner Codes (page 46)
|
|
non_physician_codes = [
|
|
("50", "Nurse Practitioner"),
|
|
("89", "Clinical Nurse Specialist"),
|
|
("97", "Physician Assistant"),
|
|
]
|
|
|
|
return {
|
|
"primary_care_codes": primary_care_codes,
|
|
"physician_specialty_codes": physician_specialty_codes,
|
|
"non_physician_codes": non_physician_codes,
|
|
}
|
|
|
|
|
|
def generate_module(data: dict) -> str:
|
|
"""Generate the alr_codes.py module source code."""
|
|
|
|
lines = [
|
|
'"""ALR Reference Code Tables — Primary care service codes and specialty codes.',
|
|
"",
|
|
"Auto-generated from ALRASRGuide.pdf Appendix Tables 3, 4, and 5.",
|
|
"Version #16 (April 2024).",
|
|
"",
|
|
"These reference tables define:",
|
|
"- Primary care service codes (CPT/HCPCS) used in beneficiary assignment",
|
|
"- Physician specialty codes for Step 1 (primary care) and Step 2 (specialist) assignment",
|
|
"- Non-physician practitioner codes eligible for Step 1 assignment",
|
|
"",
|
|
"Source: ALRASRGuide.pdf pages 41-46",
|
|
'"""',
|
|
"",
|
|
"from __future__ import annotations",
|
|
"",
|
|
"from aco.table.base import SQLTable",
|
|
"",
|
|
]
|
|
|
|
# Primary Care Service Codes
|
|
lines.extend(
|
|
[
|
|
"",
|
|
"class AlrPrimaryCareServiceCode(SQLTable):",
|
|
' """Primary care service codes for MSSP beneficiary assignment.',
|
|
"",
|
|
" Appendix Table 3: Codes used to identify primary care services",
|
|
" in the assignment algorithm. Includes CPT and HCPCS codes with",
|
|
" exclusion rules for specific settings (SNF, inpatient).",
|
|
"",
|
|
f" {len(data['primary_care_codes'])} codes total.",
|
|
"",
|
|
" Source: ALRASRGuide.pdf pages 41-44",
|
|
' """',
|
|
"",
|
|
' __schema__ = "alr_codes"',
|
|
' __tablename__ = "primary_care_service_code"',
|
|
"",
|
|
" code: str",
|
|
' """CPT or HCPCS code (e.g., 99213, G0438)"""',
|
|
"",
|
|
" code_type: str",
|
|
' """Code type: CPT or HCPCS"""',
|
|
"",
|
|
" description: str",
|
|
' """Service description"""',
|
|
"",
|
|
" exclusion_rule: str | None",
|
|
' """Exclusion rule if applicable (e.g., "Exclude if in SNF")"""',
|
|
"",
|
|
]
|
|
)
|
|
|
|
# Physician Specialty Codes
|
|
lines.extend(
|
|
[
|
|
"",
|
|
"class AlrPhysicianSpecialtyCode(SQLTable):",
|
|
' """Physician specialty codes for assignment algorithm.',
|
|
"",
|
|
" Appendix Table 4: Specialty codes used in Step 1 (primary care",
|
|
" physicians) and Step 2 (specialist physicians) assignment logic.",
|
|
"",
|
|
f" {len(data['physician_specialty_codes'])} codes total.",
|
|
"",
|
|
" Source: ALRASRGuide.pdf page 45",
|
|
' """',
|
|
"",
|
|
' __schema__ = "alr_codes"',
|
|
' __tablename__ = "physician_specialty_code"',
|
|
"",
|
|
" specialty_code: str",
|
|
' """Medicare specialty code (e.g., 01, 08, 11)"""',
|
|
"",
|
|
" assignment_step: int",
|
|
' """Assignment step: 1=primary care physicians, 2=specialist physicians"""',
|
|
"",
|
|
" description: str",
|
|
' """Specialty description"""',
|
|
"",
|
|
]
|
|
)
|
|
|
|
# Non-Physician Practitioner Codes
|
|
lines.extend(
|
|
[
|
|
"",
|
|
"class AlrNonPhysicianSpecialtyCode(SQLTable):",
|
|
' """Non-physician practitioner codes for Step 1 assignment.',
|
|
"",
|
|
" Appendix Table 5: Non-physician practitioner specialty codes",
|
|
" eligible for Step 1 (primary care) assignment.",
|
|
"",
|
|
f" {len(data['non_physician_codes'])} codes total.",
|
|
"",
|
|
" Source: ALRASRGuide.pdf page 46",
|
|
' """',
|
|
"",
|
|
' __schema__ = "alr_codes"',
|
|
' __tablename__ = "non_physician_specialty_code"',
|
|
"",
|
|
" specialty_code: str",
|
|
' """Medicare specialty code (e.g., 50, 89, 97)"""',
|
|
"",
|
|
" description: str",
|
|
' """Specialty description"""',
|
|
"",
|
|
]
|
|
)
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
def main():
|
|
"""Generate src/aco/table/alr_codes.py from ALRASRGuide.pdf appendix."""
|
|
output_path = (
|
|
Path(__file__).resolve().parents[2] / "src" / "aco" / "table" / "alr_codes.py"
|
|
)
|
|
|
|
data = extract_reference_codes()
|
|
code = generate_module(data)
|
|
|
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
output_path.write_text(code)
|
|
|
|
print(f"Generated {output_path}")
|
|
print(f" Primary care service codes: {len(data['primary_care_codes'])}")
|
|
print(f" Physician specialty codes: {len(data['physician_specialty_codes'])}")
|
|
print(f" Non-physician practitioner codes: {len(data['non_physician_codes'])}")
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|