Epidemiology Forecast
Domain: health_medicine — Public Health & Epidemiology

Summary: Reproduce the 2021-22 CDC FluSight influenza-hospitalization end-of-season scorecard and per-cell scoring table from staged forecast and truth data.

Task prompt:
You are working on a Linux VM to produce the 2021-22 CDC FluSight influenza-hospitalization forecast skill scorecard.

Visible task files:
- `base/input/forecasts_2021-22.parquet`
- `base/input/truth_2021-22.csv`
- `base/input/runtime_env/pyproject.toml`
- `base/input/runtime_env/uv.lock`

Write exactly these outputs under `base/output`:
- `base/output/submission.csv`
- `base/output/per_cell_scores.csv`

Implementation rules:
- Use IEEE 754 double precision throughout.
- Keep only `forecast_date` in the closed interval `[2022-02-21, 2022-06-20]`.
- Keep only targets `1 wk ahead inc flu hosp` through `4 wk ahead inc flu hosp`.
- Keep only `type == "quantile"`.
- Drop every row with `location == "US"` before aggregation.
- Join truth on `(location, target_end_date)` using `base/input/truth_2021-22.csv` exactly as staged.
- Quantile levels are the 23 values:
  `0.010, 0.025, 0.050, 0.100, 0.150, 0.200, 0.250, 0.300, 0.350, 0.400, 0.450, 0.500, 0.550, 0.600, 0.650, 0.700, 0.750, 0.800, 0.850, 0.900, 0.950, 0.975, 0.990`.
- Round quantile levels to 3 decimals before matching.
- Apply the round-outward rule to forecast values before scoring:
  `q < 0.5 -> floor(value)`, `q > 0.5 -> ceil(value)`, `q == 0.5 -> round half to even`.
- A model is eligible iff its non-US quantile-row count is at least 75% of `Flusight-baseline`'s count after the window/type filters.
- For each eligible `(model, location, target_end_date, target)` cell, compute:
  `wis`, `ae_median`, `cov50_hit`, `cov95_hit`.
- Use the proper-score WIS normalization `1 / (K + 1/2)` with `K = 11` and alphas
  `0.02, 0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90`.
- If any required quantile is missing for a cell, treat that cell's `wis` and `ae_median` as NaN, then aggregate with `fillna(0).mean()`.
- Aggregate per model into `wis`, `mae`, `cov50`, and `cov95`.
- Compute `rel_wis` from pairwise overlapping-cell WIS ratios using the geometric mean over all eligible models, including the self-ratio of 1, then normalize by `Flusight-baseline`.

Output requirements:
- `per_cell_scores.csv` columns:
  `model, location, target_end_date, target, wis, ae_median, cov50_hit, cov95_hit`
- `submission.csv` columns:
  `model, wis, rel_wis, mae, cov50, cov95`
- `submission.csv` must contain exactly one row per eligible model.
- `per_cell_scores.csv` must contain exactly one row per eligible scored cell.

Runtime guidance:
- The staged `input/runtime_env/` folder is the agent-facing dependency manifest.
- If you need `numpy`, `pandas`, or `pyarrow`, install them from the staged UV project rather than relying on global packages.
- You may materialize the task-local runtime by running the canonical entry point `base/software/bootstrap_runtime.sh`, which invokes `uv sync --project input/runtime_env` and writes the venv under `input/runtime_env/.venv`.


Required actions:
Read the staged forecast parquet and truth CSV from `input/`.
Install any needed task-local dependencies from `input/runtime_env/`.
Reproduce the per-cell WIS, median-absolute-error, and coverage calculations for the eligible models.
Write both required CSV outputs into `output/` with the exact required schemas.

Software: Python
uv
pandas
numpy
pyarrow

Input files:
name: forecasts_2021-22.parquet
format: Parquet
description: Long-format quantile forecasts for the 2021-22 FluSight hospitalization round.
name: truth_2021-22.csv
format: CSV
description: Observed weekly hospitalization counts aligned to the scored target_end_date values.
name: runtime_env/
format: uv Python environment manifest
description: Agent-installable dependency manifest for the scoring workflow.