{
  "markdown": "# NWAU Calculator\n\n[![PR CI](https://github.com/edithatogo/mchs/actions/workflows/pr-ci.yml/badge.svg?branch=master)](https://github.com/edithatogo/mchs/actions/workflows/pr-ci.yml)\n[![Docs Site](https://github.com/edithatogo/mchs/actions/workflows/docs-site.yml/badge.svg?branch=master)](https://github.com/edithatogo/mchs/actions/workflows/docs-site.yml)\n[![PyPI](https://img.shields.io/pypi/v/nwau-py.svg)](https://pypi.org/project/nwau-py/)\n[![Python](https://img.shields.io/pypi/pyversions/nwau-py.svg)](https://pypi.org/project/nwau-py/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\n[Contributing](CONTRIBUTING.md) | [Security](SECURITY.md) | [Code of Conduct](CODE_OF_CONDUCT.md) | [Citation](CITATION.cff)\n\nThis project provides Python translations of the IHACPA SAS funding\ncalculators. Modules cover acute, emergency department, mental health,\nsubacute and outpatient activity along with HAC and AHR adjustment\nlogic. The implementation is being brought into explicit parity with the\nofficial SAS calculators, but validation is tracked per calculator and year\nrather than claimed as complete across the whole repository. The current\nimplementation still uses pandas-based paths, while the longer-term data\nstack is moving toward Arrow-backed interchange and Polars where parity work\nallows it. A lightweight command line interface is available via the\n`funding-calculator` script.\n\nThe public documentation site is published from the Starlight scaffold in\n`docs-site/` and serves as the canonical docs front door.\nThe GitHub Pages deployment path is wired through\n[`.github/workflows/docs-site.yml`](.github/workflows/docs-site.yml).\nOpen the docs at <https://edithatogo.github.io/mchs/>.\n\n## Releases\n\nReleases are tag-driven and start from `v0.2.0`-style tags.\nThe repo uses release drafts for notes and a release workflow to build\ndistributions and publish GitHub Releases from tagged commits.\nTagged releases also trigger Python package publishing to PyPI through\ntrusted publishing.\nThe Rust GA workflow also publishes Rust artifacts to GitHub Releases,\nbut crates.io submission is not wired in this repository yet.\nThe conda-forge recipe draft is maintained under `conda/recipe/`; new conda\npackages are currently recipe-only until a staged-recipes PR is accepted and\nthe package appears on the public channel; users should treat conda-forge as\nunpublished until that registry record exists.\nAll release claims still depend on the CI and validation gates passing for the\ntagged source.\n\n### Maven Central readiness\n\nThe JVM binding has repo-side Maven publishing metadata and a manual GitHub\nActions workflow. Maven Central publication is still not claimed because the\nexternal Central Portal account gates remain open:\n\n- a registered Central Portal namespace for the publishable JVM coordinates;\n- `CENTRAL_PORTAL_DEPLOY_URL`, `CENTRAL_PORTAL_USERNAME`, and\n  `CENTRAL_PORTAL_PASSWORD` provisioned in the release secret store;\n- `MAVEN_SIGNING_KEY` and `MAVEN_SIGNING_PASSWORD` provisioned in the release\n  secret store.\n- Local JVM readiness checks use exact Gradle commands:\n  - `gradle -p bindings/jvm tasks --all`\n  - `gradle -p bindings/jvm publishAllPublicationsToCentralPortalRepository --dry-run --console=plain`\n- Real publish attempts fail closed unless deploy URL, credentials, and signing\n  secrets are supplied; dry-runs are intentionally credential-free.\n\n## Package registry status\n\nAs of 2026-05-26:\n\n| Surface | Distribution evidence | Registry state |\n| --- | --- | --- |\n| Python package (`nwau-py`) | `pyproject.toml`, release workflow, and PyPI badge links | **Published** on PyPI at `nwau-py 0.2.2` |\n| Conda package (`nwau-py`) | `conda/recipe/meta.yaml` | **Recipe-only** (not yet conda-forge published) |\n| MCP stdio server (`mchs-mcp`) | `nwau_py/mcp_server.py`, `contracts/mcp/registry/server.json`, `.github/workflows/publish-mcp-registry.yml` | **Published** to the official MCP Registry as `io.github.edithatogo/mchs` version `0.2.2`; Rust formula execution is opt-in for MCP acute 2025 only |\n| Rust crates (`nwau-core`, `nwau-c-abi`, `nwau-py`) | `rust/crates/*/Cargo.toml` | `nwau-core` **Published** on crates.io at `0.1.0`; `nwau-c-abi` and `nwau-py` remain local/private scaffolds |\n| `@edithatogo/mchs-wasm-binding` package manifest | `wasm-binding/package.json` | **Published** on npm at `0.1.0` |\n| R / Julia / Scala / Spark / Swift / Stata / MATLAB / Kotlin-Native / Power Platform | Track specs in `conductor/tracks/*` | **Private** / roadmap-only; no registry artifacts claimed |\n\nDo not state registry submission success (including crates.io, npm, CRAN, NuGet,\netc.) unless a registry page exists and is linked in evidence.\n\nThe repository also contains a Rust workspace scaffold for calculator-core\nmigration. Python remains the current validated runtime path until Rust parity\nis proven calculator by calculator.\nThe intended architecture is a polyglot library: a shared Rust calculator core\nwith thin bindings or adapters for Python, Rust, R, Julia, C#/.NET, Go,\nTypeScript/WASM, Java/JVM, C ABI, SQL/DuckDB, SAS interoperability, CLI/file\nworkflows, web demos, and Power Platform orchestration. Those surfaces must\nconsume shared contracts and validation fixtures rather than duplicating formula\nlogic.\n\nThe CLI exposes an explicit runtime selector for calculation commands:\n`--runtime python|rust|auto`, with `NWAU_RUNTIME` available for CI or automation\noverrides. Python remains the default. The only Rust-backed CLI slice currently\npromoted is opt-in acute 2025 CSV execution; unsupported Rust requests fail\nclosed rather than falling back silently. See\n`docs/roadmaps/rust-cli-runtime-boundary.md` for the support boundary.\n\nThe MCP stdio server keeps its Python transport shim for registry-compatible\nlocal execution, but `mchs.calculate` can opt into the same Rust acute 2025\nformula slice with `options.runtime = \"rust\"`. MCP support-status resources\ndistinguish the Python stdio transport from Rust-backed formula execution.\nNo CLI or MCP Rust-default claim is made; the promotion matrix in\n`contracts/runtime/rust-cli-mcp-promotion-matrix.json` keeps Rust default\npromotion blocked until cross-surface evidence covers unsupported calculators,\nyears, formats, diagnostics, and rollback.\n\n## Calculator modules\n\nEach module below mirrors a SAS program from the IHACPA package.\n\n| Module | SAS source | Notes |\n|-------|-----------|-------|\n|`acute`|`NWAU25_CALCULATOR_ACUTE.sas`|Calculates NWAU25 for acute admitted episodes. Implements ICU hour logic, length of stay categories and private patient adjustments using the current tabular Python execution paths.|\n|`ed`|`NWAU25_CALCULATOR_ED.sas`|Handles Emergency Department/Service activity. Supports UDG and AECC classifications with remoteness and indigenous adjustments.|\n|`mh`|`NWAU25_CALCULATOR_MH.sas`|Implements the mental health consumer model. Applies private patient services and accommodation adjustments.|\n|`subacute`|`NWAU25_CALCULATOR_SUBACUTE.sas`|Calculates NWAU25 for subacute admitted activity based on SNAP.|\n|`outpatients`|`NWAU25_CALCULATOR_OUTPATIENTS.sas`|For non‑admitted clinic activity. Applies remoteness and indigenous adjustments.|\n|`adjust`|`Calculate Adjusted NWAU.sas`|Combines base NWAU with Hospital Acquired Complication (HAC) and Avoidable Hospital Readmission (AHR) adjustments.|\n\nHistorical SAS calculators from IHACPA should be extracted to\n`archive/sas/<YEAR>/`. Rename the downloaded directory so only the year\nremains (for example `archive/sas/2025`). Each folder then contains the\noriginal SAS programs and data tables for that pricing year.\n\n## Calculators\n\nThe project includes Python versions of each funding calculator. The table\nbelow lists the corresponding SAS programs and shows which pricing years have\nvalidated weights and formulas.\n\n| Calculator | SAS program | Python | 2014 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 |\n|-----------|------------------------------|--------|------|------|------|------|------|------|------|------|------|------|------|------|\n| Acute | `NWAU25_CALCULATOR_ACUTE.sas` | ✓ | | | | | | | | | | | ✓ | ✓ |\n| ED | `NWAU25_CALCULATOR_ED.sas` | ✓ | | | | | | | | | | | ✓ | ✓ |\n| MH | `NWAU25_CALCULATOR_MH.sas` | ✓ | | | | | | | | | | | ✓ | ✓ |\n| Subacute | `NWAU25_CALCULATOR_SUBACUTE.sas` | ✓ | | | | | | | | | | | ✓ | ✓ |\n| Outpatients | `NWAU25_CALCULATOR_OUTPATIENTS.sas` | ✓ | | | | | | | | | | | ✓ | ✓ |\n| Adjustment | `Calculate Adjusted NWAU.sas` | ✓ | | | | | | | | | | | ✓ | ✓ |\n| Readmission | `Avoidable Hospital Readmission Grouper 030.sas` | ✓ | | | | | | | | | | | ✓ | ✓ |\n\nWeights and formulas are currently verified for 2024 and 2025. Earlier years\nremain in progress until their outputs are validated against trusted reference\nmaterial.\n\n## Installation\n\nThe preferred development workflow uses `uv`:\n\n```bash\nuv sync --locked --group dev --group test --group coverage --group typing --group property --group mutation --group profiling --group docs\n```\n\nPublished releases are available from PyPI:\n\n```bash\npython -m pip install nwau-py\n```\n\nAfter the conda-forge staged-recipes submission is accepted and the package is publicly available, conda users can\ninstall with:\n\n```bash\nconda install -c conda-forge nwau-py\n```\n\nExtract the official SAS calculators under `archive/sas/<YEAR>/` so the\nPython modules can load the reference tables for each year.\n\n### Dependencies\n\nThe calculators rely on several core Python packages:\n\n- **NumPy** for numerical helpers\n- **Pandas** for legacy tabular paths that remain under parity validation\n- **Polars** and **PyArrow** for Arrow/Parquet interoperability and the newer bundle layer\n- **LightGBM** for readmission risk scoring\n\nThe active development stack also uses:\n\n- **uv** for environment and dependency management\n- **Ruff** for linting and formatting\n- **ty** for type checking\n- **pytest** and **Codecov** for test execution and coverage reporting\n- **Hypothesis** for property-based tests\n- **mutmut** for mutation testing\n- **Scalene** for profiling\n\nUse `uv run` to execute tools inside the project environment:\n\n```bash\nuv run pytest\nuv run ruff check .\nuv run ty check\n```\n\n### Maintenance automation\nDependency updates are reviewed through Renovate, and documentation or\nvalidation claims are checked with Vale before they are merged.\n\n## Historical data\n\nPlace each year's SAS calculator under `archive/sas/<YEAR>/` and ensure the\nfolder name is just the year.  After extraction the directory should contain the\nSAS programs and reference tables for that pricing year.\n\nThe Excel workbooks may also be archived under\n`excel_calculator/archive/<year>` for historical comparison.  A helper script\n(`excel_calculator/scripts/extract_all.py`) can recreate `weights.csv` and\n`formula.json` from the workbooks but this is only required when reproducing the\noriginal spreadsheets.\n\n\nDirectory layout\n----------------\n```\narchive/\n  sas/<YEAR>/        # SAS reference tables\nexcel_calculator/\n  data/\n    weights.csv      # default (current year)\n    formula.json\n    <YEAR>/weights.csv\n    <YEAR>/formula.json\n```\nDropping the SAS folder and matching `weights.csv`/`formula.json` files for a\nnew edition is all that's required to add support for that year.\n\nThe repository currently includes verified weights and formulas for the 2024\nand 2025 editions. Additional years can be added once their outputs are\nvalidated.\n\n### Data availability matrix\n\n| Year | SAS archive | Verified weights | Validated Python |\n|------|-------------|------------------|-----------------|\n|2014|✅|❌|❌|\n|2015|✅|❌|❌|\n|2016|✅|❌ (sample only)|❌|\n|2017|✅|❌|❌|\n|2018|✅|✅ (sample)|❌|\n|2019|✅|✅ (sample)|❌|\n|2020|✅|❌|❌|\n|2021|✅|❌|❌|\n|2022|✅|❌|❌|\n|2023|✅|❌|❌|\n|2024|✅|✅|✅|\n|2025|✅|✅|✅|\n\n### Adding a new pricing year\n\n1. Extract the SAS calculator for the new edition under\n   `archive/sas/<YEAR>/`. Rename the folder so only the year remains.\n2. Copy the Excel workbook to `excel_calculator/archive/<YEAR>` and run\n   `python excel_calculator/scripts/extract_all.py`. This writes\n   `weights.csv` and `formula.json` to `excel_calculator/data/<YEAR>/`.\n3. If the remoteness classification year changes update\n   `nwau_py/utils.RA_VERSION` accordingly.\n4. Each calculator can then be invoked with ``--year <YEAR>`` or by\n   passing ``year=\"<YEAR>\"`` when calling the Python functions.\n\n## SAS program mapping\n\nThe original SAS calculators are archived under\n`archive/sas/<YEAR>/calculators`.  Each Python module in\n`nwau_py` mirrors one of these programs.  The table below lists the main\nequivalences.\n\n| SAS program | Python module | Notes |\n|-------------|---------------|-------|\n|`NWAU##_CALCULATOR_ACUTE.sas`|`nwau_py/calculators/acute.py`|Matches SAS acute logic|\n|`NWAU##_CALCULATOR_ED.sas`|`nwau_py/calculators/ed.py`|Equivalent ED calculations|\n|`NWAU##_CALCULATOR_MH.sas`|`nwau_py/calculators/mh.py`|Mental health consumer model|\n|`NWAU##_CALCULATOR_SUBACUTE.sas`|`nwau_py/calculators/subacute.py`|SNAP based calculator|\n|`NWAU##_CALCULATOR_OUTPATIENTS.sas`|`nwau_py/calculators/outpatients.py`|Non-admitted activity|\n|`Calculate Adjusted NWAU.sas`|`nwau_py/calculators/adjust.py`|Applies HAC and AHR adjustments|\n|`Avoidable Hospital Readmission Grouper.sas`|`nwau_py/groupers/ahr.py`|Readmission grouper|\n|`Hospital Acquired Complication Grouper.sas`|`nwau_py/groupers/hac.py`|HAC grouper|\n|`Scorer_v3.py`|`src/nwau_py/scoring/scorer.py`|LightGBM readmission model|\n\n## Usage\nWeights and the pricing formula are stored in `excel_calculator/data`.\nEach pricing year has its own subdirectory, e.g. `excel_calculator/data/2025`.\nThe top-level files remain as the default for 2025 so existing scripts\ncontinue to work.\nFunding calculators can be executed directly via ``python -m nwau_py.cli.main``.\nFor example, to process acute activity:\n\n```bash\npython -m nwau_py.cli.main acute patient_data.csv --output funding.csv\n```\n\nReplace `acute` with `ed` or `non-admitted` for other activity types. The\n`--year` option selects which SAS release to use.\n\nAfter installing the development environment you can run the tests, linting,\ntype checking, property tests, mutation testing, and profiling entry points\nwith `uv run`. Coverage reports are generated locally for Codecov upload in CI.\n\n```bash\nuv sync --locked --group dev --group test --group coverage --group typing --group property --group mutation --group profiling --group docs\nuv run pytest\nuv run pytest --cov=nwau_py --cov-report=term-missing --cov-report=xml --cov-fail-under=80\nuv run ty check\nuv run pytest -m hypothesis\nuv run mutmut run\nuv run scalene nwau_py/cli/main.py\n```\n\nSee `nwau_py/docs/calculators.md` for an overview of each calculator module.\nThe `nwau_py` package exposes both a command line interface and functions for\nuse within Python.\n\n## Validation Status\n\nValidation claims in this repository are intentionally specific. Prefer\ncalculator- and year-scoped statements backed by fixture packs, parity tests,\nor archived source artifacts. Avoid broad claims about project-wide or\nall-years validation unless the supporting evidence is committed alongside the\nclaim.\n\n## Remoteness classification\n\nThe calculators rely on the IHACPA remoteness area (RA) classification. The\nedition used varies by pricing year. `nwau_py.utils.RA_VERSION` maps each year\nto its RA edition and the helper function `ra_suffix(year)` returns the suffix\nused in dataset column names.\n\n```python\nfrom nwau_py.utils import ra_suffix\n\nassert ra_suffix(\"2025\") == \"ra2021\"\n```\n\n### Handling missing demographics\n\nWhen remoteness or Indigenous status is missing from the input data the\ncalculators can impute adjustment values using population distributions. Pass\na dictionary of proportions to the parameter dataclass:\n\n```python\nfrom nwau_py.calculators import AcuteParams, calculate_acute\n\nrem_dist = {\"RA1\": 0.55, \"RA2\": 0.25, \"RA3\": 0.15, \"RA4\": 0.04, \"RA5\": 0.01}\nind_dist = {0: 0.8, 1: 0.2}\nparams = AcuteParams(\n    remoteness_distribution=rem_dist,\n    indigenous_distribution=ind_dist,\n)\nresult = calculate_acute(df, params)\n```\n\nMissing adjustments are replaced by the weighted average of the relevant table\nusing the provided distribution.\n\n### Command line\n\nAfter installation the `funding-calculator` entry point is available. You can\nselect a specific pricing year with `--year`:\n\n```bash\nfunding-calculator --year 2024 patient_data.csv > funding.csv\n```\n\nThe `--year` option selects the data directory for that pricing year. The\nexample above uses the 2024 weights but you can also choose `--year 2025` once\nverified data is available. `patient_data.csv` should contain the columns\nreferenced in `excel_calculator/data/2024/formula.json` and the output will\ninclude a `NWAU24` column.\n\nTo calculate funding using an older edition simply pass the relevant year.\nFor example, to run the 2024 calculator use:\n\n```bash\nfunding-calculator --year 2024 patient_data.csv > funding.csv\n```\n\nThis instructs the tool to load weights and the formula from\n`excel_calculator/data/2024/`.\n\nThe `nwau_py` package also exposes a lightweight command line interface via\n`python -m nwau_py.cli.main`. The `--year` flag works with any supported\nedition (currently 2024 and 2025). The subcommands `acute`, `ed` and\n`non-admitted` mirror the SAS calculators:\n\n```bash\npython -m nwau_py.cli.main acute INPUT.csv --output out.csv --year 2025\n```\n\nCommon options allow the weights directory to be overridden with `--params`\nand enable or disable adjustments using `--icu/--no-icu` and\n`--covid/--no-covid`.\n\n### Python modules\n\nThe calculators can also be called directly from Python:\n\n```python\nfrom nwau_py.calculators import AcuteParams, calculate_acute\n\npatient_df = ...  # tabular episode-level data frame\nresult = calculate_acute(patient_df, AcuteParams())\n```\n\nPass ``year=\"2024\"`` (for example) to use a different pricing edition.\n\nAdditional modules under `nwau_py.calculators` provide helpers for acute, emergency, mental health and other activity types. See `examples/run_acute.py` for a minimal demonstration.\n\n#### Calculator examples\n\nThe individual calculators can be invoked directly when you need fine grained control. Each function expects a tabular input frame and returns the input with an additional `NWAU25` column.\n\n```python\nfrom nwau_py.calculators import AcuteParams, calculate_acute\nresult = calculate_acute(acute_df, AcuteParams())\n```\n\n```python\nfrom nwau_py.calculators import EDParams, calculate_ed\nresult = calculate_ed(ed_df, EDParams())\n```\n\n```python\nfrom nwau_py.calculators import MHParams, calculate_mh\nresult = calculate_mh(mh_df, MHParams())\n```\n\n```python\nfrom nwau_py.calculators import SubacuteParams, calculate_subacute\nresult = calculate_subacute(sa_df, SubacuteParams())\n```\n\n```python\nfrom nwau_py.calculators import OutpatientParams, calculate_outpatients\nresult = calculate_outpatients(op_df, OutpatientParams())\n```\n\n```python\nfrom nwau_py.calculators import calculate_adjusted_nwau\nresult = calculate_adjusted_nwau(weight_df)\n```\n",
  "bytes": 19041,
  "sha": "94ceafb95ebee8b81ef36f4802af0e0b24cd78cdb5e5b8d815b57a48229a9f8c",
  "repo_slug": "edithatogo/mchs",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_edithatogo_mchs_f519d1ba/readme"
}