| """Cached data loaders for the RHTP dashboard. |
| |
| Every loader reads from /data/<topic>/<file>. Replace the file with a |
| real-data file of the same schema to switch from synthetic to live data. |
| """ |
| from __future__ import annotations |
|
|
| from pathlib import Path |
| from typing import Optional |
|
|
| import pandas as pd |
| import streamlit as st |
|
|
| |
| ROOT_CANDIDATES = [Path("/app"), Path(__file__).resolve().parents[2]] |
| for _root in ROOT_CANDIDATES: |
| if (_root / "data").exists(): |
| ROOT = _root |
| break |
| else: |
| ROOT = ROOT_CANDIDATES[-1] |
| DATA = ROOT / "data" |
|
|
|
|
| def _read(rel: str) -> pd.DataFrame: |
| """Read a CSV (or its parquet sibling if present and newer). |
| |
| `fips` and `county_fips` are kept as zero-padded strings so they merge |
| cleanly across files. Use object dtype rather than pandas string[python] |
| -- the latter trips patsy when used as a categorical fixed effect. |
| """ |
| csv = DATA / rel |
| parquet = csv.with_suffix(".parquet") |
| if parquet.exists() and parquet.stat().st_mtime >= csv.stat().st_mtime: |
| df = pd.read_parquet(parquet) |
| else: |
| df = pd.read_csv(csv, dtype={"fips": str, "county_fips": str}) |
| for c in ("fips", "county_fips"): |
| if c in df.columns: |
| df[c] = df[c].astype(str).str.zfill(5) |
| return df |
|
|
|
|
| |
| |
| |
| @st.cache_data(show_spinner=False) |
| def counties() -> pd.DataFrame: |
| return _read("geography/montana_counties.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def population_panel() -> pd.DataFrame: |
| return _read("geography/county_population_panel.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def hospitals() -> pd.DataFrame: |
| return _read("geography/montana_hospitals.csv") |
|
|
|
|
| |
| |
| |
| @st.cache_data(show_spinner=False) |
| def facility_quarter_ops() -> pd.DataFrame: |
| df = _read("facilities/facility_quarter_ops.csv") |
| df["period"] = df["year"].astype(str) + "Q" + df["quarter"].astype(str) |
| df["period_index"] = df["year"] * 4 + (df["quarter"] - 1) |
| return df |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def facility_quarter_treatment() -> pd.DataFrame: |
| df = _read("facilities/facility_quarter_treatment_status.csv") |
| df["period"] = df["year"].astype(str) + "Q" + df["quarter"].astype(str) |
| df["period_index"] = df["year"] * 4 + (df["quarter"] - 1) |
| return df |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def coe_implementation() -> pd.DataFrame: |
| return _read("facilities/coe_implementation.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def telehealth_activation() -> pd.DataFrame: |
| return _read("facilities/telehealth_activation.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def shared_services() -> pd.DataFrame: |
| return _read("facilities/shared_services.csv") |
|
|
|
|
| |
| |
| |
| @st.cache_data(show_spinner=False) |
| def workforce_panel() -> pd.DataFrame: |
| return _read("workforce/workforce_county_year.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def service_commitment_awards() -> pd.DataFrame: |
| return _read("workforce/service_commitment_awards.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def residency_slots() -> pd.DataFrame: |
| return _read("workforce/residency_slots.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def training_participants() -> pd.DataFrame: |
| return _read("workforce/training_participants.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def workforce_supports() -> pd.DataFrame: |
| return _read("workforce/workforce_supports.csv") |
|
|
|
|
| |
| |
| |
| @st.cache_data(show_spinner=False) |
| def member_month_pmpm() -> pd.DataFrame: |
| return _read("claims/member_month_pmpm.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def county_quarter_treatment_status() -> pd.DataFrame: |
| return _read("claims/county_quarter_treatment_status.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def ed_high_utilizers() -> pd.DataFrame: |
| return _read("claims/ed_high_utilizers.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def tnt_cpt_usage() -> pd.DataFrame: |
| return _read("claims/tnt_cpt_usage.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def pharmacy_prescribing() -> pd.DataFrame: |
| return _read("claims/pharmacy_prescribing.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def outpatient_share() -> pd.DataFrame: |
| return _read("claims/outpatient_share.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def ems_modernization() -> pd.DataFrame: |
| return _read("claims/ems_modernization.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def vbc_attribution() -> pd.DataFrame: |
| return _read("claims/vbc_attribution.csv") |
|
|
|
|
| |
| |
| |
| @st.cache_data(show_spinner=False) |
| def prevention_panel() -> pd.DataFrame: |
| return _read("prevention/prevention_county_year.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def school_sites() -> pd.DataFrame: |
| return _read("prevention/school_sites.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def mobile_care_runs() -> pd.DataFrame: |
| return _read("prevention/mobile_care_runs.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def chap_rollout() -> pd.DataFrame: |
| return _read("prevention/chap_rollout.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def crisis_infrastructure() -> pd.DataFrame: |
| return _read("prevention/crisis_infrastructure.csv") |
|
|
|
|
| |
| |
| |
| @st.cache_data(show_spinner=False) |
| def hie_participation() -> pd.DataFrame: |
| return _read("technology/hie_participation.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def ehr_modernization() -> pd.DataFrame: |
| return _read("technology/ehr_modernization.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def bed_registry() -> pd.DataFrame: |
| return _read("technology/bed_registry.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def bh_bed_wait_time() -> pd.DataFrame: |
| return _read("technology/bh_bed_wait_time.csv") |
|
|
|
|
| @st.cache_data(show_spinner=False) |
| def dashboard_usage() -> pd.DataFrame: |
| return _read("technology/dashboard_usage.csv") |
|
|