1706 lines
60 KiB
Python
1706 lines
60 KiB
Python
"""Tests for aco.express.ahrq_measures — AHRQ PQI measure functions.
|
|
|
|
Tests verify staging, shared exclusions, helper functions, and individual
|
|
PQI measure denom/exclusion/numerator chains.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import date
|
|
|
|
import narwhals as nw
|
|
import polars as pl
|
|
import pytest
|
|
|
|
from aco.express.ahrq_measures import (
|
|
_pqi_denom,
|
|
_pqi_num,
|
|
_pqi_simple_exclusions,
|
|
int_pqi_01_denom,
|
|
int_pqi_01_exclusions,
|
|
int_pqi_01_num,
|
|
int_pqi_03_denom,
|
|
int_pqi_03_exclusions,
|
|
int_pqi_03_num,
|
|
int_pqi_05_denom,
|
|
int_pqi_05_exclusions,
|
|
int_pqi_05_num,
|
|
int_pqi_07_denom,
|
|
int_pqi_07_exclusions,
|
|
int_pqi_07_num,
|
|
int_pqi_08_denom,
|
|
int_pqi_08_exclusions,
|
|
int_pqi_08_num,
|
|
int_pqi_11_denom,
|
|
int_pqi_11_exclusions,
|
|
int_pqi_11_num,
|
|
int_pqi_12_denom,
|
|
int_pqi_12_exclusions,
|
|
int_pqi_12_num,
|
|
int_pqi_14_denom,
|
|
int_pqi_14_exclusions,
|
|
int_pqi_14_num,
|
|
int_pqi_15_denom,
|
|
int_pqi_15_exclusions,
|
|
int_pqi_15_num,
|
|
int_pqi_16_denom,
|
|
int_pqi_16_exclusions,
|
|
int_pqi_16_num,
|
|
int_pqi_shared_exclusion_missing_dates,
|
|
int_pqi_shared_exclusion_missing_gender,
|
|
int_pqi_shared_exclusion_missing_primary_dx,
|
|
int_pqi_shared_exclusion_transfer,
|
|
int_pqi_shared_exclusion_ungroupable_drg,
|
|
int_pqi_shared_exclusion_union,
|
|
int_pqi_shared_exclusions_missing_age,
|
|
stg_pqi_inpatient_encounter,
|
|
stg_pqi_member_months,
|
|
)
|
|
|
|
# ── fixtures ─────────────────────────────────────────────────────────────────
|
|
|
|
|
|
@pytest.fixture
|
|
def core_encounter_for_pqi() -> pl.DataFrame:
|
|
"""Core encounter records for PQI staging."""
|
|
return pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1", "E2", "E3"],
|
|
"person_id": ["P1", "P1", "P2"],
|
|
"encounter_type": ["acute inpatient", "ed", "acute inpatient"],
|
|
"encounter_start_date": [
|
|
date(2024, 3, 15),
|
|
date(2024, 4, 1),
|
|
date(2024, 5, 10),
|
|
],
|
|
"encounter_end_date": [
|
|
date(2024, 3, 20),
|
|
date(2024, 4, 1),
|
|
date(2024, 5, 15),
|
|
],
|
|
"length_of_stay": [5, 0, 5],
|
|
"admit_source_code": [None, None, None],
|
|
"admit_source_description": [None, None, None],
|
|
"admit_type_code": [None, None, None],
|
|
"admit_type_description": [None, None, None],
|
|
"discharge_disposition_code": ["01", "01", "01"],
|
|
"discharge_disposition_description": ["home", "home", "home"],
|
|
"attending_provider_id": [None, None, None],
|
|
"attending_provider_name": [None, None, None],
|
|
"facility_id": [None, None, None],
|
|
"facility_name": [None, None, None],
|
|
"primary_diagnosis_code_type": [
|
|
"icd-10-cm",
|
|
"icd-10-cm",
|
|
"icd-10-cm",
|
|
],
|
|
"primary_diagnosis_code": ["E11.65", "R10.9", "J44.1"],
|
|
"primary_diagnosis_description": [None, None, None],
|
|
"drg_code_type": ["ms-drg", None, "ms-drg"],
|
|
"drg_code": ["638", None, "190"],
|
|
"drg_description": [None, None, None],
|
|
"paid_amount": [8000.0, 500.0, 12000.0],
|
|
"allowed_amount": [10000.0, 600.0, 14000.0],
|
|
"charge_amount": [20000.0, 1000.0, 25000.0],
|
|
"data_source": ["test", "test", "test"],
|
|
"encounter_source_type": ["claim", "clinical", "claim"],
|
|
"encounter_group": ["claims", "clinical", "claims"],
|
|
}
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def pqi_inpatient_df() -> pl.DataFrame:
|
|
"""Staged PQI inpatient encounters."""
|
|
return pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1", "E2"],
|
|
"data_source": ["test", "test"],
|
|
"drg_code": ["638", "190"],
|
|
"drg_description": [None, None],
|
|
"admit_source_code": [None, None],
|
|
"encounter_start_date": [
|
|
date(2024, 3, 15),
|
|
date(2024, 5, 10),
|
|
],
|
|
"encounter_end_date": [date(2024, 3, 20), date(2024, 5, 15)],
|
|
"length_of_stay": [5, 5],
|
|
"primary_diagnosis_code": ["E11.65", "J44.1"],
|
|
"person_id": ["P1", "P2"],
|
|
"facility_id": [None, None],
|
|
"paid_amount": [8000.0, 12000.0],
|
|
"year_number": [2024, 2024],
|
|
}
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def core_patient_pqi() -> pl.DataFrame:
|
|
"""Patient records for PQI tests."""
|
|
return pl.DataFrame(
|
|
{
|
|
"person_id": ["P1", "P2", "P3"],
|
|
"sex": ["male", "female", "unknown"],
|
|
"birth_date": [
|
|
date(1960, 1, 1),
|
|
date(1970, 6, 15),
|
|
None,
|
|
],
|
|
"death_date": [None, None, None],
|
|
"data_source": ["test", "test", "test"],
|
|
"first_name": [None, None, None],
|
|
"last_name": [None, None, None],
|
|
"state": [None, None, None],
|
|
"zip_code": [None, None, None],
|
|
"race": [None, None, None],
|
|
}
|
|
)
|
|
|
|
|
|
# ── Reusable helpers ────────────────────────────────────────────────────────
|
|
|
|
|
|
def _make_inpatient(
|
|
encounter_id: str = "E1",
|
|
data_source: str = "test",
|
|
primary_diagnosis_code: str = "E10.10",
|
|
person_id: str = "P1",
|
|
year: int = 2024,
|
|
drg_code: str | None = None,
|
|
admit_source_code: str | None = None,
|
|
) -> pl.DataFrame:
|
|
"""Minimal staged inpatient encounter."""
|
|
return pl.DataFrame(
|
|
{
|
|
"encounter_id": [encounter_id],
|
|
"data_source": [data_source],
|
|
"drg_code": [drg_code],
|
|
"drg_description": [None],
|
|
"admit_source_code": [admit_source_code],
|
|
"encounter_start_date": [date(year, 3, 15)],
|
|
"encounter_end_date": [date(year, 3, 20)],
|
|
"length_of_stay": [5],
|
|
"primary_diagnosis_code": [primary_diagnosis_code],
|
|
"person_id": [person_id],
|
|
"facility_id": [None],
|
|
"paid_amount": [1000.0],
|
|
"year_number": [year],
|
|
}
|
|
)
|
|
|
|
|
|
def _make_mm(
|
|
person_id: str = "P1",
|
|
year_month: str = "202401",
|
|
) -> pl.DataFrame:
|
|
"""Minimal member months."""
|
|
return pl.DataFrame(
|
|
{
|
|
"data_source": ["test"],
|
|
"person_id": [person_id],
|
|
"first_day_of_month": [date(int(year_month[:4]), 1, 1)],
|
|
"year_month": [year_month],
|
|
}
|
|
)
|
|
|
|
|
|
def _make_patient(
|
|
person_id: str = "P1",
|
|
birth_date: date = date(1960, 1, 1),
|
|
sex: str = "male",
|
|
) -> pl.DataFrame:
|
|
return pl.DataFrame(
|
|
{
|
|
"person_id": [person_id],
|
|
"data_source": ["test"],
|
|
"birth_date": [birth_date],
|
|
"sex": [sex],
|
|
}
|
|
)
|
|
|
|
|
|
def _make_denom(
|
|
person_id: str = "P1",
|
|
year_number: int = 2024,
|
|
age: int = 64,
|
|
) -> pl.DataFrame:
|
|
return pl.DataFrame(
|
|
{
|
|
"person_id": [person_id],
|
|
"data_source": ["test"],
|
|
"year_number": [year_number],
|
|
"age": [age],
|
|
}
|
|
)
|
|
|
|
|
|
def _empty_exclusions() -> pl.DataFrame:
|
|
return pl.DataFrame(
|
|
{
|
|
"encounter_id": pl.Series([], dtype=pl.Utf8),
|
|
"data_source": pl.Series([], dtype=pl.Utf8),
|
|
"exclusion_reason": pl.Series([], dtype=pl.Utf8),
|
|
"exclusion_number": pl.Series([], dtype=pl.Int64),
|
|
}
|
|
)
|
|
|
|
|
|
def _make_shared_exclusion_union(
|
|
encounter_id: str = "EX1",
|
|
reason: str = "transfer",
|
|
) -> pl.DataFrame:
|
|
return pl.DataFrame(
|
|
{
|
|
"encounter_id": [encounter_id],
|
|
"data_source": ["test"],
|
|
"exclusion_reason": [reason],
|
|
}
|
|
)
|
|
|
|
|
|
def _make_value_set(
|
|
value_set_name: str,
|
|
pqi_number: str,
|
|
codes: list[str],
|
|
) -> pl.DataFrame:
|
|
return pl.DataFrame(
|
|
{
|
|
"value_set_name": [value_set_name] * len(codes),
|
|
"pqi_number": [pqi_number] * len(codes),
|
|
"code": codes,
|
|
}
|
|
)
|
|
|
|
|
|
def _make_condition(
|
|
encounter_id: str = "E1",
|
|
normalized_code: str = "CF01",
|
|
code_type: str = "icd-10-cm",
|
|
) -> pl.DataFrame:
|
|
return pl.DataFrame(
|
|
{
|
|
"encounter_id": [encounter_id],
|
|
"data_source": ["test"],
|
|
"normalized_code": [normalized_code],
|
|
"normalized_code_type": [code_type],
|
|
}
|
|
)
|
|
|
|
|
|
def _make_procedure(
|
|
encounter_id: str = "E1",
|
|
normalized_code: str = "PROC1",
|
|
code_type: str = "icd-10-pcs",
|
|
) -> pl.DataFrame:
|
|
return pl.DataFrame(
|
|
{
|
|
"encounter_id": [encounter_id],
|
|
"data_source": ["test"],
|
|
"normalized_code": [normalized_code],
|
|
"normalized_code_type": [code_type],
|
|
}
|
|
)
|
|
|
|
|
|
# ── stg_pqi_inpatient_encounter ─────────────────────────────────────────────
|
|
|
|
|
|
class TestStgPqiInpatientEncounter:
|
|
def test_filters_to_acute_inpatient(self, core_encounter_for_pqi) -> None:
|
|
result = stg_pqi_inpatient_encounter(core_encounter_for_pqi)
|
|
assert isinstance(result, pl.DataFrame)
|
|
assert len(result) == 2 # Only acute inpatient
|
|
|
|
def test_adds_year_number(self, core_encounter_for_pqi) -> None:
|
|
result = stg_pqi_inpatient_encounter(core_encounter_for_pqi)
|
|
assert "year_number" in result.columns
|
|
assert result["year_number"][0] == 2024
|
|
|
|
def test_expected_columns(self, core_encounter_for_pqi) -> None:
|
|
result = stg_pqi_inpatient_encounter(core_encounter_for_pqi)
|
|
for col in [
|
|
"encounter_id",
|
|
"data_source",
|
|
"drg_code",
|
|
"primary_diagnosis_code",
|
|
"person_id",
|
|
"year_number",
|
|
]:
|
|
assert col in result.columns
|
|
|
|
def test_ed_excluded(self, core_encounter_for_pqi) -> None:
|
|
result = stg_pqi_inpatient_encounter(core_encounter_for_pqi)
|
|
ids = result["encounter_id"].to_list()
|
|
assert "E2" not in ids
|
|
|
|
|
|
# ── stg_pqi_member_months ───────────────────────────────────────────────────
|
|
|
|
|
|
class TestStgPqiMemberMonths:
|
|
def test_joins_calendar(self) -> None:
|
|
mm = pl.DataFrame(
|
|
{
|
|
"data_source": ["test"],
|
|
"person_id": ["P1"],
|
|
"year_month": ["202401"],
|
|
}
|
|
)
|
|
cal = pl.DataFrame(
|
|
{
|
|
"year_month": ["2024-01"],
|
|
"first_day_of_month": [date(2024, 1, 1)],
|
|
}
|
|
)
|
|
result = stg_pqi_member_months(mm, cal)
|
|
assert isinstance(result, pl.DataFrame)
|
|
assert len(result) == 1
|
|
assert result["first_day_of_month"][0] == date(2024, 1, 1)
|
|
|
|
def test_no_match_returns_empty(self) -> None:
|
|
mm = pl.DataFrame(
|
|
{
|
|
"data_source": ["test"],
|
|
"person_id": ["P1"],
|
|
"year_month": ["202401"],
|
|
}
|
|
)
|
|
cal = pl.DataFrame(
|
|
{
|
|
"year_month": ["2023-12"],
|
|
"first_day_of_month": [date(2023, 12, 1)],
|
|
}
|
|
)
|
|
result = stg_pqi_member_months(mm, cal)
|
|
assert len(result) == 0
|
|
|
|
def test_expected_columns(self) -> None:
|
|
mm = pl.DataFrame(
|
|
{
|
|
"data_source": ["test"],
|
|
"person_id": ["P1"],
|
|
"year_month": ["202401"],
|
|
}
|
|
)
|
|
cal = pl.DataFrame(
|
|
{
|
|
"year_month": ["2024-01"],
|
|
"first_day_of_month": [date(2024, 1, 1)],
|
|
}
|
|
)
|
|
result = stg_pqi_member_months(mm, cal)
|
|
for col in [
|
|
"data_source",
|
|
"person_id",
|
|
"first_day_of_month",
|
|
"year_month",
|
|
]:
|
|
assert col in result.columns
|
|
|
|
|
|
# ── shared exclusion functions ──────────────────────────────────────────────
|
|
|
|
|
|
class TestSharedExclusions:
|
|
def test_missing_dates_finds_nulls(self) -> None:
|
|
enc = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1", "E2"],
|
|
"data_source": ["test", "test"],
|
|
"drg_code": [None, None],
|
|
"drg_description": [None, None],
|
|
"admit_source_code": [None, None],
|
|
"encounter_start_date": [None, date(2024, 1, 1)],
|
|
"encounter_end_date": [None, date(2024, 1, 5)],
|
|
"length_of_stay": [None, 4],
|
|
"primary_diagnosis_code": [None, "I21.0"],
|
|
"person_id": ["P1", "P2"],
|
|
"facility_id": [None, None],
|
|
"paid_amount": [None, 1000.0],
|
|
"year_number": [2024, 2024],
|
|
}
|
|
)
|
|
result = int_pqi_shared_exclusion_missing_dates(enc)
|
|
assert len(result) == 1
|
|
assert result["encounter_id"][0] == "E1"
|
|
|
|
def test_missing_gender_filters_invalid(self, core_patient_pqi) -> None:
|
|
result = int_pqi_shared_exclusion_missing_gender(core_patient_pqi)
|
|
assert len(result) == 1
|
|
assert result["person_id"][0] == "P3"
|
|
|
|
def test_missing_primary_dx(self) -> None:
|
|
enc = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1", "E2"],
|
|
"data_source": ["test", "test"],
|
|
"drg_code": [None, None],
|
|
"drg_description": [None, None],
|
|
"admit_source_code": [None, None],
|
|
"encounter_start_date": [date(2024, 1, 1)] * 2,
|
|
"encounter_end_date": [date(2024, 1, 5)] * 2,
|
|
"length_of_stay": [4, 4],
|
|
"primary_diagnosis_code": [None, "I21.0"],
|
|
"person_id": ["P1", "P2"],
|
|
"facility_id": [None, None],
|
|
"paid_amount": [1000.0, 2000.0],
|
|
"year_number": [2024, 2024],
|
|
}
|
|
)
|
|
result = int_pqi_shared_exclusion_missing_primary_dx(enc)
|
|
assert len(result) == 1
|
|
assert result["encounter_id"][0] == "E1"
|
|
|
|
def test_transfer_exclusion(self) -> None:
|
|
enc = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1", "E2", "E3"],
|
|
"data_source": ["test"] * 3,
|
|
"drg_code": [None] * 3,
|
|
"drg_description": [None] * 3,
|
|
"admit_source_code": ["4", "1", "6"],
|
|
"encounter_start_date": [date(2024, 1, 1)] * 3,
|
|
"encounter_end_date": [date(2024, 1, 5)] * 3,
|
|
"length_of_stay": [4] * 3,
|
|
"primary_diagnosis_code": ["I21.0"] * 3,
|
|
"person_id": ["P1", "P2", "P3"],
|
|
"facility_id": [None] * 3,
|
|
"paid_amount": [1000.0] * 3,
|
|
"year_number": [2024] * 3,
|
|
}
|
|
)
|
|
result = int_pqi_shared_exclusion_transfer(enc)
|
|
ids = result["encounter_id"].to_list()
|
|
assert "E1" in ids # admit_source_code = "4"
|
|
assert "E2" not in ids # admit_source_code = "1"
|
|
assert "E3" in ids # admit_source_code = "6"
|
|
|
|
def test_ungroupable_drg(self) -> None:
|
|
enc = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1", "E2"],
|
|
"data_source": ["test", "test"],
|
|
"drg_code": ["999", "280"],
|
|
"drg_description": [None, None],
|
|
"admit_source_code": [None, None],
|
|
"encounter_start_date": [date(2024, 1, 1)] * 2,
|
|
"encounter_end_date": [date(2024, 1, 5)] * 2,
|
|
"length_of_stay": [4, 4],
|
|
"primary_diagnosis_code": ["I21.0"] * 2,
|
|
"person_id": ["P1", "P2"],
|
|
"facility_id": [None, None],
|
|
"paid_amount": [1000.0] * 2,
|
|
"year_number": [2024, 2024],
|
|
}
|
|
)
|
|
result = int_pqi_shared_exclusion_ungroupable_drg(enc)
|
|
assert len(result) == 1
|
|
assert result["encounter_id"][0] == "E1"
|
|
|
|
def test_missing_age(self, core_patient_pqi) -> None:
|
|
result = int_pqi_shared_exclusions_missing_age(core_patient_pqi)
|
|
assert len(result) == 1
|
|
assert result["person_id"][0] == "P3"
|
|
|
|
|
|
# ── int_pqi_shared_exclusion_union ──────────────────────────────────────────
|
|
|
|
|
|
class TestSharedExclusionUnion:
|
|
def test_union_all_exclusion_types(self) -> None:
|
|
enc = _make_inpatient("E1", person_id="P1")
|
|
enc2 = _make_inpatient("E2", person_id="P2")
|
|
encounters = pl.concat([enc, enc2])
|
|
|
|
missing_age = pl.DataFrame(
|
|
{
|
|
"data_source": ["test"],
|
|
"person_id": ["P1"],
|
|
}
|
|
)
|
|
missing_gender = pl.DataFrame(
|
|
{
|
|
"data_source": ["test"],
|
|
"person_id": ["P2"],
|
|
}
|
|
)
|
|
missing_dates = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1"],
|
|
"data_source": ["test"],
|
|
}
|
|
)
|
|
missing_dx = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E2"],
|
|
"data_source": ["test"],
|
|
}
|
|
)
|
|
transfer = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1"],
|
|
"data_source": ["test"],
|
|
}
|
|
)
|
|
ungroupable = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E2"],
|
|
"data_source": ["test"],
|
|
}
|
|
)
|
|
|
|
result = int_pqi_shared_exclusion_union(
|
|
encounters,
|
|
missing_age,
|
|
missing_gender,
|
|
missing_dates,
|
|
missing_dx,
|
|
transfer,
|
|
ungroupable,
|
|
)
|
|
assert isinstance(result, pl.DataFrame)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "missing age" in reasons
|
|
assert "missing gender" in reasons
|
|
assert "missing dates" in reasons
|
|
assert "missing primary diagnosis" in reasons
|
|
assert "transfer" in reasons
|
|
assert "ungroupable DRG" in reasons
|
|
for col in [
|
|
"encounter_id",
|
|
"data_source",
|
|
"exclusion_reason",
|
|
]:
|
|
assert col in result.columns
|
|
|
|
def test_empty_exclusions(self) -> None:
|
|
enc = _make_inpatient()
|
|
empty_person = pl.DataFrame(
|
|
{
|
|
"data_source": pl.Series([], dtype=pl.Utf8),
|
|
"person_id": pl.Series([], dtype=pl.Utf8),
|
|
}
|
|
)
|
|
empty_enc = pl.DataFrame(
|
|
{
|
|
"encounter_id": pl.Series([], dtype=pl.Utf8),
|
|
"data_source": pl.Series([], dtype=pl.Utf8),
|
|
}
|
|
)
|
|
result = int_pqi_shared_exclusion_union(
|
|
enc,
|
|
empty_person,
|
|
empty_person,
|
|
empty_enc,
|
|
empty_enc,
|
|
empty_enc,
|
|
empty_enc,
|
|
)
|
|
assert len(result) == 0
|
|
|
|
|
|
# ── Helper functions (_pqi_denom, _pqi_simple_exclusions, _pqi_num) ─────────
|
|
|
|
|
|
class TestPqiDenom:
|
|
def test_filters_by_min_age(self) -> None:
|
|
mm = nw.from_native(_make_mm("P1", "202401"))
|
|
patient = nw.from_native(_make_patient("P1", date(1960, 1, 1)))
|
|
result = _pqi_denom(mm, patient, min_age=18)
|
|
native = nw.to_native(result)
|
|
assert len(native) == 1
|
|
|
|
def test_filters_underage(self) -> None:
|
|
mm = nw.from_native(_make_mm("P1", "202401"))
|
|
patient = nw.from_native(_make_patient("P1", date(2010, 1, 1)))
|
|
result = _pqi_denom(mm, patient, min_age=18)
|
|
native = nw.to_native(result)
|
|
assert len(native) == 0
|
|
|
|
def test_max_age_filter(self) -> None:
|
|
mm = nw.from_native(_make_mm("P1", "202401"))
|
|
# Person born 1960 -> age ~64 in 2024
|
|
patient = nw.from_native(_make_patient("P1", date(1960, 1, 1)))
|
|
result = _pqi_denom(mm, patient, min_age=18, max_age=39)
|
|
native = nw.to_native(result)
|
|
assert len(native) == 0 # 64 > 39
|
|
|
|
def test_max_age_within_range(self) -> None:
|
|
mm = nw.from_native(_make_mm("P1", "202401"))
|
|
# Person born 1995 -> age ~29 in 2024 (within 18-39)
|
|
patient = nw.from_native(_make_patient("P1", date(1995, 1, 1)))
|
|
result = _pqi_denom(mm, patient, min_age=18, max_age=39)
|
|
native = nw.to_native(result)
|
|
assert len(native) == 1
|
|
|
|
def test_expected_columns(self) -> None:
|
|
mm = nw.from_native(_make_mm("P1", "202401"))
|
|
patient = nw.from_native(_make_patient("P1", date(1960, 1, 1)))
|
|
result = _pqi_denom(mm, patient)
|
|
native = nw.to_native(result)
|
|
for col in ["year_number", "person_id", "data_source", "age"]:
|
|
assert col in native.columns
|
|
|
|
|
|
class TestPqiSimpleExclusions:
|
|
def test_adds_exclusion_number(self) -> None:
|
|
shared = nw.from_native(
|
|
pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1", "E1", "E2"],
|
|
"data_source": ["test", "test", "test"],
|
|
"exclusion_reason": [
|
|
"missing age",
|
|
"transfer",
|
|
"missing dates",
|
|
],
|
|
}
|
|
)
|
|
)
|
|
result = _pqi_simple_exclusions(shared)
|
|
native = nw.to_native(result)
|
|
assert "exclusion_number" in native.columns
|
|
assert len(native) == 3
|
|
|
|
|
|
class TestPqiNum:
|
|
def test_matches_value_set_and_denom(self) -> None:
|
|
encounters = nw.from_native(
|
|
_make_inpatient("E1", primary_diagnosis_code="DX01")
|
|
)
|
|
value_set = nw.from_native(_make_value_set("test_dx_codes", "99", ["DX01"]))
|
|
denom = nw.from_native(_make_denom("P1", 2024))
|
|
exclusions = nw.from_native(_empty_exclusions())
|
|
result = _pqi_num(
|
|
encounters,
|
|
value_set,
|
|
denom,
|
|
exclusions,
|
|
"test_dx_codes",
|
|
"99",
|
|
)
|
|
native = nw.to_native(result)
|
|
assert len(native) == 1
|
|
assert native["encounter_id"][0] == "E1"
|
|
|
|
def test_excludes_excluded_encounters(self) -> None:
|
|
encounters = nw.from_native(
|
|
_make_inpatient("E1", primary_diagnosis_code="DX01")
|
|
)
|
|
value_set = nw.from_native(_make_value_set("test_dx_codes", "99", ["DX01"]))
|
|
denom = nw.from_native(_make_denom("P1", 2024))
|
|
exclusions = nw.from_native(
|
|
pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1"],
|
|
"data_source": ["test"],
|
|
"exclusion_reason": ["transfer"],
|
|
"exclusion_number": [1],
|
|
}
|
|
)
|
|
)
|
|
result = _pqi_num(
|
|
encounters,
|
|
value_set,
|
|
denom,
|
|
exclusions,
|
|
"test_dx_codes",
|
|
"99",
|
|
)
|
|
native = nw.to_native(result)
|
|
assert len(native) == 0
|
|
|
|
def test_no_match_in_value_set(self) -> None:
|
|
encounters = nw.from_native(
|
|
_make_inpatient("E1", primary_diagnosis_code="ZZZ99")
|
|
)
|
|
value_set = nw.from_native(_make_value_set("test_dx_codes", "99", ["DX01"]))
|
|
denom = nw.from_native(_make_denom("P1", 2024))
|
|
exclusions = nw.from_native(_empty_exclusions())
|
|
result = _pqi_num(
|
|
encounters,
|
|
value_set,
|
|
denom,
|
|
exclusions,
|
|
"test_dx_codes",
|
|
"99",
|
|
)
|
|
native = nw.to_native(result)
|
|
assert len(native) == 0
|
|
|
|
|
|
# ── PQI 01 ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPqi01Denom:
|
|
def test_returns_dataframe(self) -> None:
|
|
result = int_pqi_01_denom(_make_mm(), _make_patient())
|
|
assert isinstance(result, pl.DataFrame)
|
|
|
|
def test_filters_by_age(self) -> None:
|
|
patient = pl.concat(
|
|
[
|
|
_make_patient("P1", date(1960, 1, 1)),
|
|
_make_patient("P2", date(2010, 1, 1)),
|
|
]
|
|
)
|
|
mm2 = pl.concat([_make_mm("P1"), _make_mm("P2")])
|
|
result = int_pqi_01_denom(mm2, patient)
|
|
ids = result["person_id"].to_list()
|
|
assert "P1" in ids
|
|
assert "P2" not in ids
|
|
|
|
def test_expected_columns(self) -> None:
|
|
result = int_pqi_01_denom(_make_mm(), _make_patient())
|
|
for col in ["year_number", "person_id", "data_source", "age"]:
|
|
assert col in result.columns
|
|
|
|
|
|
class TestPqi01Exclusions:
|
|
def test_passes_through_shared(self) -> None:
|
|
shared = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1", "E2"],
|
|
"data_source": ["test", "test"],
|
|
"exclusion_reason": ["missing age", "transfer"],
|
|
}
|
|
)
|
|
result = int_pqi_01_exclusions(shared)
|
|
assert isinstance(result, pl.DataFrame)
|
|
assert len(result) == 2
|
|
assert "exclusion_number" in result.columns
|
|
|
|
def test_expected_columns(self) -> None:
|
|
shared = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1"],
|
|
"data_source": ["test"],
|
|
"exclusion_reason": ["test"],
|
|
}
|
|
)
|
|
result = int_pqi_01_exclusions(shared)
|
|
for col in [
|
|
"encounter_id",
|
|
"data_source",
|
|
"exclusion_reason",
|
|
"exclusion_number",
|
|
]:
|
|
assert col in result.columns
|
|
|
|
|
|
class TestPqi01Num:
|
|
def test_matches_value_set(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="E10.10")
|
|
value_set = _make_value_set(
|
|
"diabetes_with_short-term_complications_diagnosis_codes",
|
|
"01",
|
|
["E10.10"],
|
|
)
|
|
denom = _make_denom()
|
|
exclusions = _empty_exclusions()
|
|
result = int_pqi_01_num(encounters, value_set, denom, exclusions)
|
|
assert len(result) == 1
|
|
|
|
def test_excludes_excluded_encounters(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="E10.10")
|
|
value_set = _make_value_set(
|
|
"diabetes_with_short-term_complications_diagnosis_codes",
|
|
"01",
|
|
["E10.10"],
|
|
)
|
|
denom = _make_denom()
|
|
exclusions = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1"],
|
|
"data_source": ["test"],
|
|
"exclusion_reason": ["transfer"],
|
|
"exclusion_number": [1],
|
|
}
|
|
)
|
|
result = int_pqi_01_num(encounters, value_set, denom, exclusions)
|
|
assert len(result) == 0
|
|
|
|
|
|
# ── PQI 03 ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPqi03:
|
|
def test_denom(self) -> None:
|
|
result = int_pqi_03_denom(_make_mm(), _make_patient())
|
|
assert isinstance(result, pl.DataFrame)
|
|
assert len(result) == 1
|
|
|
|
def test_exclusions(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
result = int_pqi_03_exclusions(shared)
|
|
assert len(result) == 1
|
|
assert "exclusion_number" in result.columns
|
|
|
|
def test_num_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="DX03")
|
|
vs = _make_value_set(
|
|
"diabetes_with_long-term_complications_diagnosis_codes",
|
|
"03",
|
|
["DX03"],
|
|
)
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_03_num(encounters, vs, denom, excl)
|
|
assert len(result) == 1
|
|
|
|
def test_num_no_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="ZZZ")
|
|
vs = _make_value_set(
|
|
"diabetes_with_long-term_complications_diagnosis_codes",
|
|
"03",
|
|
["DX03"],
|
|
)
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_03_num(encounters, vs, denom, excl)
|
|
assert len(result) == 0
|
|
|
|
|
|
# ── PQI 05 ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPqi05:
|
|
def test_denom_age_40_plus(self) -> None:
|
|
mm = pl.concat([_make_mm("P1"), _make_mm("P2")])
|
|
patient = pl.concat(
|
|
[
|
|
_make_patient("P1", date(1960, 1, 1)), # ~64
|
|
_make_patient("P2", date(1990, 1, 1)), # ~34, < 40
|
|
]
|
|
)
|
|
result = int_pqi_05_denom(mm, patient)
|
|
ids = result["person_id"].to_list()
|
|
assert "P1" in ids
|
|
assert "P2" not in ids
|
|
|
|
def test_exclusions_shared_only(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = _make_value_set(
|
|
"cystic_fibrosis_and_anomalies_of_the_respiratory_system",
|
|
"05",
|
|
["CF01"],
|
|
)
|
|
condition = _make_condition("E99", "NOTCF", "icd-10-cm")
|
|
result = int_pqi_05_exclusions(shared, vs, condition)
|
|
# Only shared exclusion present
|
|
assert len(result) == 1
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "transfer" in reasons
|
|
|
|
def test_exclusions_cystic_fibrosis(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = _make_value_set(
|
|
"cystic_fibrosis_and_anomalies_of_the_respiratory_system",
|
|
"05",
|
|
["CF01"],
|
|
)
|
|
condition = _make_condition("E1", "CF01", "icd-10-cm")
|
|
result = int_pqi_05_exclusions(shared, vs, condition)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "cystic fibrosis" in reasons
|
|
|
|
def test_num_copd_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="COPD1")
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"chronic_obstructive_pulmonary_disorder",
|
|
"05",
|
|
["COPD1"],
|
|
),
|
|
_make_value_set("asthma", "05", ["AST1"]),
|
|
]
|
|
)
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_05_num(encounters, vs, denom, excl)
|
|
assert len(result) == 1
|
|
|
|
def test_num_asthma_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="AST1")
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"chronic_obstructive_pulmonary_disorder",
|
|
"05",
|
|
["COPD1"],
|
|
),
|
|
_make_value_set("asthma", "05", ["AST1"]),
|
|
]
|
|
)
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_05_num(encounters, vs, denom, excl)
|
|
assert len(result) == 1
|
|
|
|
def test_num_no_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="ZZZ")
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"chronic_obstructive_pulmonary_disorder",
|
|
"05",
|
|
["COPD1"],
|
|
),
|
|
_make_value_set("asthma", "05", ["AST1"]),
|
|
]
|
|
)
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_05_num(encounters, vs, denom, excl)
|
|
assert len(result) == 0
|
|
|
|
def test_num_excluded(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="COPD1")
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"chronic_obstructive_pulmonary_disorder",
|
|
"05",
|
|
["COPD1"],
|
|
),
|
|
_make_value_set("asthma", "05", ["AST1"]),
|
|
]
|
|
)
|
|
denom = _make_denom()
|
|
excl = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1"],
|
|
"data_source": ["test"],
|
|
"exclusion_reason": ["cystic fibrosis"],
|
|
"exclusion_number": [1],
|
|
}
|
|
)
|
|
result = int_pqi_05_num(encounters, vs, denom, excl)
|
|
assert len(result) == 0
|
|
|
|
|
|
# ── PQI 07 ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPqi07:
|
|
def test_denom(self) -> None:
|
|
result = int_pqi_07_denom(_make_mm(), _make_patient())
|
|
assert isinstance(result, pl.DataFrame)
|
|
assert len(result) == 1
|
|
|
|
def test_exclusions_shared_only(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set("cardiac_procedure_codes", "appendix_b", ["CP01"]),
|
|
_make_value_set(
|
|
"exclusion_kidney_disease_diagnosis_codes",
|
|
"07",
|
|
["CKD01"],
|
|
),
|
|
_make_value_set(
|
|
"exclusion_dialysis_access_procedure_codes",
|
|
"07",
|
|
["DIA01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E99", "NOMATCH", "icd-10-cm")
|
|
procedure = _make_procedure("E99", "NOMATCH", "icd-10-pcs")
|
|
result = int_pqi_07_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "transfer" in reasons
|
|
assert "cardiac procedure" not in reasons
|
|
|
|
def test_exclusions_cardiac_procedure(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set("cardiac_procedure_codes", "appendix_b", ["CP01"]),
|
|
_make_value_set(
|
|
"exclusion_kidney_disease_diagnosis_codes",
|
|
"07",
|
|
["CKD01"],
|
|
),
|
|
_make_value_set(
|
|
"exclusion_dialysis_access_procedure_codes",
|
|
"07",
|
|
["DIA01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E99", "NOMATCH", "icd-10-cm")
|
|
procedure = _make_procedure("E1", "CP01", "icd-10-pcs")
|
|
result = int_pqi_07_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "cardiac procedure" in reasons
|
|
|
|
def test_exclusions_ckd_with_dialysis(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set("cardiac_procedure_codes", "appendix_b", ["CP01"]),
|
|
_make_value_set(
|
|
"exclusion_kidney_disease_diagnosis_codes",
|
|
"07",
|
|
["CKD01"],
|
|
),
|
|
_make_value_set(
|
|
"exclusion_dialysis_access_procedure_codes",
|
|
"07",
|
|
["DIA01"],
|
|
),
|
|
]
|
|
)
|
|
# Same encounter has CKD condition AND dialysis procedure
|
|
condition = _make_condition("E1", "CKD01", "icd-10-cm")
|
|
procedure = _make_procedure("E1", "DIA01", "icd-10-pcs")
|
|
result = int_pqi_07_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "ckd" in reasons
|
|
|
|
def test_exclusions_ckd_without_dialysis(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set("cardiac_procedure_codes", "appendix_b", ["CP01"]),
|
|
_make_value_set(
|
|
"exclusion_kidney_disease_diagnosis_codes",
|
|
"07",
|
|
["CKD01"],
|
|
),
|
|
_make_value_set(
|
|
"exclusion_dialysis_access_procedure_codes",
|
|
"07",
|
|
["DIA01"],
|
|
),
|
|
]
|
|
)
|
|
# CKD condition but NO dialysis procedure
|
|
condition = _make_condition("E1", "CKD01", "icd-10-cm")
|
|
procedure = _make_procedure("E99", "NOMATCH", "icd-10-pcs")
|
|
result = int_pqi_07_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "ckd" not in reasons
|
|
|
|
def test_num_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="HYP01")
|
|
vs = _make_value_set("hypertension_diagnosis_codes", "07", ["HYP01"])
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_07_num(encounters, vs, denom, excl)
|
|
assert len(result) == 1
|
|
|
|
def test_num_excluded(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="HYP01")
|
|
vs = _make_value_set("hypertension_diagnosis_codes", "07", ["HYP01"])
|
|
denom = _make_denom()
|
|
excl = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1"],
|
|
"data_source": ["test"],
|
|
"exclusion_reason": ["cardiac procedure"],
|
|
"exclusion_number": [1],
|
|
}
|
|
)
|
|
result = int_pqi_07_num(encounters, vs, denom, excl)
|
|
assert len(result) == 0
|
|
|
|
|
|
# ── PQI 08 ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPqi08:
|
|
def test_denom(self) -> None:
|
|
result = int_pqi_08_denom(_make_mm(), _make_patient())
|
|
assert isinstance(result, pl.DataFrame)
|
|
assert len(result) == 1
|
|
|
|
def test_exclusions_shared_only(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = _make_value_set("cardiac_procedure_codes", "appendix_b", ["CP01"])
|
|
procedure = _make_procedure("E99", "NOMATCH", "icd-10-pcs")
|
|
result = int_pqi_08_exclusions(shared, vs, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "transfer" in reasons
|
|
assert "cardiac procedure" not in reasons
|
|
|
|
def test_exclusions_cardiac(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = _make_value_set("cardiac_procedure_codes", "appendix_b", ["CP01"])
|
|
procedure = _make_procedure("E1", "CP01", "icd-10-pcs")
|
|
result = int_pqi_08_exclusions(shared, vs, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "cardiac procedure" in reasons
|
|
|
|
def test_num_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="HF01")
|
|
vs = _make_value_set("heart_failure_diagnosis_codes", "08", ["HF01"])
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_08_num(encounters, vs, denom, excl)
|
|
assert len(result) == 1
|
|
|
|
def test_num_no_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="ZZZ")
|
|
vs = _make_value_set("heart_failure_diagnosis_codes", "08", ["HF01"])
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_08_num(encounters, vs, denom, excl)
|
|
assert len(result) == 0
|
|
|
|
|
|
# ── PQI 11 ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPqi11:
|
|
def test_denom(self) -> None:
|
|
result = int_pqi_11_denom(_make_mm(), _make_patient())
|
|
assert isinstance(result, pl.DataFrame)
|
|
assert len(result) == 1
|
|
|
|
def test_exclusions_shared_only(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"sickle_cell_anemia_or_hb-s_disease_diagnosis_codes",
|
|
"11",
|
|
["SC01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_diagnosis_codes",
|
|
"appendix_c",
|
|
["IM_DX01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_procedure_codes",
|
|
"appendix_c",
|
|
["IM_PX01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E99", "NOMATCH", "icd-10-cm")
|
|
procedure = _make_procedure("E99", "NOMATCH", "icd-10-pcs")
|
|
result = int_pqi_11_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "transfer" in reasons
|
|
assert "sickle cell" not in reasons
|
|
|
|
def test_exclusions_sickle_cell(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"sickle_cell_anemia_or_hb-s_disease_diagnosis_codes",
|
|
"11",
|
|
["SC01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_diagnosis_codes",
|
|
"appendix_c",
|
|
["IM_DX01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_procedure_codes",
|
|
"appendix_c",
|
|
["IM_PX01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E1", "SC01", "icd-10-cm")
|
|
procedure = _make_procedure("E99", "NOMATCH", "icd-10-pcs")
|
|
result = int_pqi_11_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "sickle cell" in reasons
|
|
|
|
def test_exclusions_immunocompromised_dx(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"sickle_cell_anemia_or_hb-s_disease_diagnosis_codes",
|
|
"11",
|
|
["SC01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_diagnosis_codes",
|
|
"appendix_c",
|
|
["IM_DX01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_procedure_codes",
|
|
"appendix_c",
|
|
["IM_PX01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E1", "IM_DX01", "icd-10-cm")
|
|
procedure = _make_procedure("E99", "NOMATCH", "icd-10-pcs")
|
|
result = int_pqi_11_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "immunocompromised diagnosis" in reasons
|
|
|
|
def test_exclusions_immunocompromised_px(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"sickle_cell_anemia_or_hb-s_disease_diagnosis_codes",
|
|
"11",
|
|
["SC01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_diagnosis_codes",
|
|
"appendix_c",
|
|
["IM_DX01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_procedure_codes",
|
|
"appendix_c",
|
|
["IM_PX01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E99", "NOMATCH", "icd-10-cm")
|
|
procedure = _make_procedure("E1", "IM_PX01", "icd-10-pcs")
|
|
result = int_pqi_11_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "immunocompromised procedure" in reasons
|
|
|
|
def test_num_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="PN01")
|
|
vs = _make_value_set(
|
|
"community_acquired_bacterial_pneumonia_diagnosis_codes",
|
|
"11",
|
|
["PN01"],
|
|
)
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_11_num(encounters, vs, denom, excl)
|
|
assert len(result) == 1
|
|
|
|
def test_num_excluded(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="PN01")
|
|
vs = _make_value_set(
|
|
"community_acquired_bacterial_pneumonia_diagnosis_codes",
|
|
"11",
|
|
["PN01"],
|
|
)
|
|
denom = _make_denom()
|
|
excl = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1"],
|
|
"data_source": ["test"],
|
|
"exclusion_reason": ["sickle cell"],
|
|
"exclusion_number": [1],
|
|
}
|
|
)
|
|
result = int_pqi_11_num(encounters, vs, denom, excl)
|
|
assert len(result) == 0
|
|
|
|
|
|
# ── PQI 12 ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPqi12:
|
|
def test_denom(self) -> None:
|
|
result = int_pqi_12_denom(_make_mm(), _make_patient())
|
|
assert isinstance(result, pl.DataFrame)
|
|
assert len(result) == 1
|
|
|
|
def test_exclusions_shared_only(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"kidney_or_urinary_tract_disorder_diagnosis_codes",
|
|
"12",
|
|
["KID01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_diagnosis_codes",
|
|
"appendix_c",
|
|
["IM_DX01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_procedure_codes",
|
|
"appendix_c",
|
|
["IM_PX01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E99", "NOMATCH", "icd-10-cm")
|
|
procedure = _make_procedure("E99", "NOMATCH", "icd-10-pcs")
|
|
result = int_pqi_12_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "transfer" in reasons
|
|
assert "kidney" not in reasons
|
|
|
|
def test_exclusions_kidney(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"kidney_or_urinary_tract_disorder_diagnosis_codes",
|
|
"12",
|
|
["KID01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_diagnosis_codes",
|
|
"appendix_c",
|
|
["IM_DX01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_procedure_codes",
|
|
"appendix_c",
|
|
["IM_PX01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E1", "KID01", "icd-10-cm")
|
|
procedure = _make_procedure("E99", "NOMATCH", "icd-10-pcs")
|
|
result = int_pqi_12_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "kidney" in reasons
|
|
|
|
def test_exclusions_immunocompromised_dx(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"kidney_or_urinary_tract_disorder_diagnosis_codes",
|
|
"12",
|
|
["KID01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_diagnosis_codes",
|
|
"appendix_c",
|
|
["IM_DX01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_procedure_codes",
|
|
"appendix_c",
|
|
["IM_PX01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E1", "IM_DX01", "icd-10-cm")
|
|
procedure = _make_procedure("E99", "NOMATCH", "icd-10-pcs")
|
|
result = int_pqi_12_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "immunocompromised diagnosis" in reasons
|
|
|
|
def test_exclusions_immunocompromised_px(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"kidney_or_urinary_tract_disorder_diagnosis_codes",
|
|
"12",
|
|
["KID01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_diagnosis_codes",
|
|
"appendix_c",
|
|
["IM_DX01"],
|
|
),
|
|
_make_value_set(
|
|
"immunocompromised_state_procedure_codes",
|
|
"appendix_c",
|
|
["IM_PX01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E99", "NOMATCH", "icd-10-cm")
|
|
procedure = _make_procedure("E1", "IM_PX01", "icd-10-pcs")
|
|
result = int_pqi_12_exclusions(shared, vs, condition, procedure)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "immunocompromised procedure" in reasons
|
|
|
|
def test_num_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="UTI01")
|
|
vs = _make_value_set("urinary_tract_infection_diagnosis_codes", "12", ["UTI01"])
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_12_num(encounters, vs, denom, excl)
|
|
assert len(result) == 1
|
|
|
|
def test_num_no_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="ZZZ")
|
|
vs = _make_value_set("urinary_tract_infection_diagnosis_codes", "12", ["UTI01"])
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_12_num(encounters, vs, denom, excl)
|
|
assert len(result) == 0
|
|
|
|
|
|
# ── PQI 14 ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPqi14:
|
|
def test_denom(self) -> None:
|
|
result = int_pqi_14_denom(_make_mm(), _make_patient())
|
|
assert isinstance(result, pl.DataFrame)
|
|
assert len(result) == 1
|
|
|
|
def test_exclusions(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
result = int_pqi_14_exclusions(shared)
|
|
assert len(result) == 1
|
|
assert "exclusion_number" in result.columns
|
|
|
|
def test_num_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="UDM01")
|
|
vs = _make_value_set("uncontrolled_diabetes_diagnosis_codes", "14", ["UDM01"])
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_14_num(encounters, vs, denom, excl)
|
|
assert len(result) == 1
|
|
|
|
def test_num_excluded(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="UDM01")
|
|
vs = _make_value_set("uncontrolled_diabetes_diagnosis_codes", "14", ["UDM01"])
|
|
denom = _make_denom()
|
|
excl = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1"],
|
|
"data_source": ["test"],
|
|
"exclusion_reason": ["transfer"],
|
|
"exclusion_number": [1],
|
|
}
|
|
)
|
|
result = int_pqi_14_num(encounters, vs, denom, excl)
|
|
assert len(result) == 0
|
|
|
|
|
|
# ── PQI 15 ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPqi15:
|
|
def test_denom_age_18_39(self) -> None:
|
|
mm = pl.concat([_make_mm("P1"), _make_mm("P2")])
|
|
patient = pl.concat(
|
|
[
|
|
_make_patient("P1", date(1995, 1, 1)), # ~29, in range
|
|
_make_patient("P2", date(1960, 1, 1)), # ~64, too old
|
|
]
|
|
)
|
|
result = int_pqi_15_denom(mm, patient)
|
|
ids = result["person_id"].to_list()
|
|
assert "P1" in ids
|
|
assert "P2" not in ids
|
|
|
|
def test_exclusions_shared_only(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = _make_value_set(
|
|
"cystic_fibrosis_and_anomalies_of_the_respiratory_system_diagnosis_codes",
|
|
"15",
|
|
["CF15"],
|
|
)
|
|
condition = _make_condition("E99", "NOMATCH", "icd-10-cm")
|
|
result = int_pqi_15_exclusions(shared, vs, condition)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "transfer" in reasons
|
|
assert "cystic fibrosis" not in reasons
|
|
|
|
def test_exclusions_cystic_fibrosis(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = _make_value_set(
|
|
"cystic_fibrosis_and_anomalies_of_the_respiratory_system_diagnosis_codes",
|
|
"15",
|
|
["CF15"],
|
|
)
|
|
condition = _make_condition("E1", "CF15", "icd-10-cm")
|
|
result = int_pqi_15_exclusions(shared, vs, condition)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "cystic fibrosis" in reasons
|
|
|
|
def test_num_match(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="AST15")
|
|
vs = _make_value_set("asthma_diagnosis_codes", "15", ["AST15"])
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_15_num(encounters, vs, denom, excl)
|
|
assert len(result) == 1
|
|
|
|
def test_num_excluded(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="AST15")
|
|
vs = _make_value_set("asthma_diagnosis_codes", "15", ["AST15"])
|
|
denom = _make_denom()
|
|
excl = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1"],
|
|
"data_source": ["test"],
|
|
"exclusion_reason": ["cystic fibrosis"],
|
|
"exclusion_number": [1],
|
|
}
|
|
)
|
|
result = int_pqi_15_num(encounters, vs, denom, excl)
|
|
assert len(result) == 0
|
|
|
|
|
|
# ── PQI 16 ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPqi16:
|
|
def test_denom(self) -> None:
|
|
result = int_pqi_16_denom(_make_mm(), _make_patient())
|
|
assert isinstance(result, pl.DataFrame)
|
|
assert len(result) == 1
|
|
|
|
def test_exclusions_shared_only(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"traumatic_amputation_of_the_lower_extremity_diagnosis_codes",
|
|
"16",
|
|
["AMP01"],
|
|
),
|
|
_make_value_set(
|
|
"mdc_14_principal_diagnosis_codes",
|
|
"appendix_f",
|
|
["PREG01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E99", "NOMATCH", "icd-10-cm")
|
|
result = int_pqi_16_exclusions(shared, vs, condition)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "transfer" in reasons
|
|
assert "amputation" not in reasons
|
|
assert "pregnancy" not in reasons
|
|
|
|
def test_exclusions_amputation(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"traumatic_amputation_of_the_lower_extremity_diagnosis_codes",
|
|
"16",
|
|
["AMP01"],
|
|
),
|
|
_make_value_set(
|
|
"mdc_14_principal_diagnosis_codes",
|
|
"appendix_f",
|
|
["PREG01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E1", "AMP01", "icd-10-cm")
|
|
result = int_pqi_16_exclusions(shared, vs, condition)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "amputation" in reasons
|
|
|
|
def test_exclusions_pregnancy(self) -> None:
|
|
shared = _make_shared_exclusion_union()
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set(
|
|
"traumatic_amputation_of_the_lower_extremity_diagnosis_codes",
|
|
"16",
|
|
["AMP01"],
|
|
),
|
|
_make_value_set(
|
|
"mdc_14_principal_diagnosis_codes",
|
|
"appendix_f",
|
|
["PREG01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E1", "PREG01", "icd-10-cm")
|
|
result = int_pqi_16_exclusions(shared, vs, condition)
|
|
reasons = set(result["exclusion_reason"].to_list())
|
|
assert "pregnancy" in reasons
|
|
|
|
def test_num_match(self) -> None:
|
|
"""PQI 16 num requires diabetes dx + amputation px on same encounter."""
|
|
encounters = _make_inpatient(primary_diagnosis_code="ANYCODE")
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set("diabetes_diagnosis_codes", "16", ["DM16"]),
|
|
_make_value_set(
|
|
"lower-extremity_amputation_procedure_codes",
|
|
"16",
|
|
["LAMP01"],
|
|
),
|
|
]
|
|
)
|
|
# Condition has diabetes dx on same encounter
|
|
condition = _make_condition("E1", "DM16", "icd-10-cm")
|
|
# Procedure has amputation px on same encounter
|
|
procedure = _make_procedure("E1", "LAMP01", "icd-10-pcs")
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_16_num(encounters, vs, denom, excl, condition, procedure)
|
|
assert len(result) == 1
|
|
assert result["encounter_id"][0] == "E1"
|
|
|
|
def test_num_no_diabetes_dx(self) -> None:
|
|
"""No diabetes diagnosis -> no numerator match."""
|
|
encounters = _make_inpatient(primary_diagnosis_code="ANYCODE")
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set("diabetes_diagnosis_codes", "16", ["DM16"]),
|
|
_make_value_set(
|
|
"lower-extremity_amputation_procedure_codes",
|
|
"16",
|
|
["LAMP01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E1", "NOMATCH", "icd-10-cm")
|
|
procedure = _make_procedure("E1", "LAMP01", "icd-10-pcs")
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_16_num(encounters, vs, denom, excl, condition, procedure)
|
|
assert len(result) == 0
|
|
|
|
def test_num_no_amputation_px(self) -> None:
|
|
"""No amputation procedure -> no numerator match."""
|
|
encounters = _make_inpatient(primary_diagnosis_code="ANYCODE")
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set("diabetes_diagnosis_codes", "16", ["DM16"]),
|
|
_make_value_set(
|
|
"lower-extremity_amputation_procedure_codes",
|
|
"16",
|
|
["LAMP01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E1", "DM16", "icd-10-cm")
|
|
procedure = _make_procedure("E1", "NOMATCH", "icd-10-pcs")
|
|
denom = _make_denom()
|
|
excl = _empty_exclusions()
|
|
result = int_pqi_16_num(encounters, vs, denom, excl, condition, procedure)
|
|
assert len(result) == 0
|
|
|
|
def test_num_excluded(self) -> None:
|
|
encounters = _make_inpatient(primary_diagnosis_code="ANYCODE")
|
|
vs = pl.concat(
|
|
[
|
|
_make_value_set("diabetes_diagnosis_codes", "16", ["DM16"]),
|
|
_make_value_set(
|
|
"lower-extremity_amputation_procedure_codes",
|
|
"16",
|
|
["LAMP01"],
|
|
),
|
|
]
|
|
)
|
|
condition = _make_condition("E1", "DM16", "icd-10-cm")
|
|
procedure = _make_procedure("E1", "LAMP01", "icd-10-pcs")
|
|
denom = _make_denom()
|
|
excl = pl.DataFrame(
|
|
{
|
|
"encounter_id": ["E1"],
|
|
"data_source": ["test"],
|
|
"exclusion_reason": ["amputation"],
|
|
"exclusion_number": [1],
|
|
}
|
|
)
|
|
result = int_pqi_16_num(encounters, vs, denom, excl, condition, procedure)
|
|
assert len(result) == 0
|