Metadata-Version: 2.4
Name: hydroseason
Version: 0.2.0
Summary: Remote-sensing-first hydro-year detection from monthly surface-water extent
Author-email: "Thiaggo C. Tayer" <thiaggo.tayer@uwa.edu.au>
License-Expression: MIT
Project-URL: Homepage, https://github.com/tayerthiaggo/hydroseason
Project-URL: Documentation, https://tayerthiaggo.github.io/hydroseason/
Project-URL: Repository, https://github.com/tayerthiaggo/hydroseason
Project-URL: Issues, https://github.com/tayerthiaggo/hydroseason/issues
Project-URL: Changelog, https://github.com/tayerthiaggo/hydroseason/blob/main/CHANGELOG.md
Keywords: hydrology,hydrological-year,remote-sensing,surface-water,water-mask,water-resources,geospatial
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: GIS
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Requires-Python: <3.14,>=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas>=2.0
Requires-Dist: numpy>=1.24
Provides-Extra: raster
Requires-Dist: xarray>=2023.8; extra == "raster"
Requires-Dist: rioxarray>=0.15; extra == "raster"
Requires-Dist: rasterio>=1.3; extra == "raster"
Requires-Dist: geopandas>=0.14; extra == "raster"
Requires-Dist: shapely>=2.0; extra == "raster"
Requires-Dist: affine>=2.4; extra == "raster"
Requires-Dist: dask[array]>=2024.1; extra == "raster"
Requires-Dist: zarr<3,>=2.16; extra == "raster"
Requires-Dist: numcodecs<0.16; extra == "raster"
Requires-Dist: h5netcdf>=1.3; extra == "raster"
Requires-Dist: h5py>=3.10; extra == "raster"
Requires-Dist: s3fs>=2024.6; extra == "raster"
Requires-Dist: scipy>=1.11; extra == "raster"
Requires-Dist: dask-image>=2024.5.3; extra == "raster"
Provides-Extra: stac
Requires-Dist: hydroseason[raster]; extra == "stac"
Requires-Dist: pystac>=1.12; extra == "stac"
Requires-Dist: pystac-client>=0.8; extra == "stac"
Requires-Dist: odc-stac>=0.5; extra == "stac"
Requires-Dist: psutil>=5.9; extra == "stac"
Requires-Dist: tqdm>=4.65; extra == "stac"
Provides-Extra: all
Requires-Dist: hydroseason[raster,stac]; extra == "all"
Provides-Extra: case-study
Requires-Dist: hydroseason[stac]; extra == "case-study"
Provides-Extra: docs
Requires-Dist: mkdocs<2,>=1.6; extra == "docs"
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.25; extra == "docs"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: ruff<1,>=0.12; extra == "dev"
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: twine>=6.1; extra == "dev"
Requires-Dist: check-wheel-contents>=0.6; extra == "dev"
Requires-Dist: tomli>=2.0; python_version < "3.11" and extra == "dev"
Requires-Dist: playwright>=1.40; extra == "dev"
Dynamic: license-file

# HydroSeason

[![Tests](https://github.com/tayerthiaggo/hydroseason/actions/workflows/test.yml/badge.svg)](https://github.com/tayerthiaggo/hydroseason/actions/workflows/test.yml)
[![Docs](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://tayerthiaggo.github.io/hydroseason/)
[![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](https://github.com/tayerthiaggo/hydroseason)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/tayerthiaggo/hydroseason/blob/main/LICENSE)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21866898.svg)](https://doi.org/10.5281/zenodo.21866898)

HydroSeason reads a monthly surface-water extent record (for example, from
Digital Earth Australia Water Observations) and tells you whether the
catchment floods and dries on a reliable annual cycle. If it does, you get
per-year boundaries and wet/dry phases. If it doesn't, you get flood events
and low-water spells instead of a forced calendar.

> **Scope:** HydroSeason measures surface-water **extent**. It does not
> estimate discharge, depth, volume, or groundwater.

**Documentation:** [tayerthiaggo.github.io/hydroseason](https://tayerthiaggo.github.io/hydroseason/)

## What you get

[![HydroSeason report preview](https://raw.githubusercontent.com/tayerthiaggo/hydroseason/main/docs/assets/report-preview.png)](https://tayerthiaggo.github.io/hydroseason/examples/fitzroy-river-wa.html)

One call writes a self-contained HTML report, four CSVs (`_monthly`,
`_hydro_years`, `_wet_event`, `_low_spells`), and a run manifest that
records the method version and input checksums.

Open a real report (no install needed):

- [Fitzroy River (WA)](https://tayerthiaggo.github.io/hydroseason/examples/fitzroy-river-wa.html) — seasonal: per-year boundaries
- [Lachlan River (NSW)](https://tayerthiaggo.github.io/hydroseason/examples/lachlan-river-nsw.html) — aseasonal: events and dry spells
- [Fitzroy River + rainfall](https://tayerthiaggo.github.io/hydroseason/examples/fitzroy-river-wa-rainfall.html) — rainfall shown as context only

Browse a complete output folder (no install needed):
[`docs/examples/fitzroy-river-wa/`](https://github.com/tayerthiaggo/hydroseason/tree/main/docs/examples/fitzroy-river-wa)
— the HTML report, the four CSVs
([monthly](https://github.com/tayerthiaggo/hydroseason/blob/main/docs/examples/fitzroy-river-wa/fitzroy-river-wa_monthly.csv),
[hydro years](https://github.com/tayerthiaggo/hydroseason/blob/main/docs/examples/fitzroy-river-wa/fitzroy-river-wa_hydro_years.csv),
[wet events](https://github.com/tayerthiaggo/hydroseason/blob/main/docs/examples/fitzroy-river-wa/fitzroy-river-wa_wet_event.csv),
[low spells](https://github.com/tayerthiaggo/hydroseason/blob/main/docs/examples/fitzroy-river-wa/fitzroy-river-wa_low_spells.csv)),
and the [run manifest](https://github.com/tayerthiaggo/hydroseason/blob/main/docs/examples/fitzroy-river-wa/fitzroy-river-wa_manifest.json).

## Install

```bash
pip install hydroseason              # CSV input (pandas + numpy only)
pip install "hydroseason[raster]"    # + NetCDF/Zarr/xarray input and SILO rainfall
pip install "hydroseason[stac]"      # + fetch DEA Water Observations directly
pip install "hydroseason[all]"       # everything: all inputs, DEA fetch, rainfall
```

Python 3.10–3.13. Run `hydroseason doctor` to check which inputs your
environment supports.

## Quickstart

From a monthly extent CSV (`date`, `extent_pct`, optional `invalid_pct`):

```python
from hydroseason import run_hydroseason

result = run_hydroseason(
    "monthly_extent.csv",
    output_dir="output/report",
    aoi_name="My AOI",
)
print(result.analysis.regime.regime)  # "seasonal", "aseasonal", or "insufficient_record"
print(result.analysis.route)          # "per_year_detection", "event_characterisation", ...
print(result.artifacts.html)
```

Or fetch DEA data for a polygon, from the command line:

```bash
hydroseason run --aoi catchment.geojson --aoi-name "My catchment" \
  --start-date 2005-01-01 --end-date 2025-12-01 \
  --output-dir output/report --cache-dir cache
```

The same function also takes NetCDF/Zarr rasters, optional rainfall, and —
through `run_hydroseason_many` — many AOIs at once. See the
[Usage Guide](https://tayerthiaggo.github.io/hydroseason/guide/) and the
[notebooks](https://github.com/tayerthiaggo/hydroseason/tree/main/notebooks/).

## How it works

1. **Screen** — on a DEA fetch, one read of the all-time WOfS statistics
   checks the AOI holds recurrent water before any monthly data is downloaded.
2. **Test seasonality** — circular Kuiper tests ask whether annual peaks
   *and* troughs recur in the same calendar months (at least five detectable
   years required).
3. **Route** — a seasonal record with at least seven resolved cycles gets
   per-year boundaries, refined with a robust (Huber) profile fit. Anything
   else gets flood-event and low-spell analysis.
4. **Report** — rainfall, if added, annotates the report but never changes
   the answer, which is decided from water alone.

Every run uses one frozen method, `hydroseason-v0.2.0`, recorded in the run
manifest. Details: [Methods Reference](https://tayerthiaggo.github.io/hydroseason/methods/).

## Case studies

Three reproducible studies on five Australian catchments (DEA 30 m,
2005–2025): the [main workflow](https://tayerthiaggo.github.io/hydroseason/case-studies/main-workflow/),
[resolution sensitivity](https://tayerthiaggo.github.io/hydroseason/case-studies/resolution-and-acquisition/),
and [rainfall context](https://tayerthiaggo.github.io/hydroseason/case-studies/rainfall-context/).

## Citation

Please cite the software release ([`CITATION.cff`](https://github.com/tayerthiaggo/hydroseason/blob/main/CITATION.cff)):

```bibtex
@software{tayer_hydroseason,
  author  = {Tayer, Thiaggo C.},
  title   = {HydroSeason: Remote-sensing-first hydrological year and season detection},
  year    = {2026},
  url     = {https://github.com/tayerthiaggo/hydroseason},
  doi     = {10.5281/zenodo.21866898}
}
```

See [Citation](https://tayerthiaggo.github.io/hydroseason/citation/) for version-specific DOIs.

## License

MIT — see [LICENSE](https://github.com/tayerthiaggo/hydroseason/blob/main/LICENSE).
