Metadata-Version: 2.4
Name: climaclass
Version: 0.3.0
Summary: Classical climate classification (Koppen-Geiger, Holdridge, Thornthwaite) from monthly climatologies - pure Python, no Earth Engine required.
Project-URL: Homepage, https://github.com/DarriEy/Climate_Classifications
Project-URL: Source, https://github.com/DarriEy/Climate_Classifications
Author: Darri Eythorsson
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: classification,climate,climatology,holdridge,hydrology,koppen,thornthwaite
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
Requires-Python: >=3.9
Provides-Extra: dev
Requires-Dist: numpy; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Provides-Extra: symfluence
Requires-Dist: geopandas>=0.12; extra == 'symfluence'
Requires-Dist: netcdf4>=1.6; extra == 'symfluence'
Requires-Dist: numpy; extra == 'symfluence'
Requires-Dist: rasterstats>=0.18; extra == 'symfluence'
Requires-Dist: xarray>=2023.1; extra == 'symfluence'
Provides-Extra: viz
Requires-Dist: matplotlib>=3.6; extra == 'viz'
Description-Content-Type: text/markdown

# climaclass

**Classical climate classification from monthly climatologies — pure Python, no Earth Engine required.**

`climaclass` turns a 12-month climatology of temperature and precipitation into a
climate class under three classical schemes:

| Scheme | Reference | Output |
|--------|-----------|--------|
| **Köppen–Geiger** | Peel et al. (2007); legend of Beck et al. (2018) | code (`Csb`) + zone 1–30 |
| **Holdridge life zones** | Holdridge (1967) | life-zone name + belt/province |
| **Thornthwaite** | Thornthwaite (1948) | moisture + thermal province |

It grew out of the [`Climate_Classifications`](https://github.com/DarriEy/Climate_Classifications)
Earth-Engine notebooks, but reimplements the *algorithms* as dependency-free
Python so they run anywhere — a laptop, a CI job, or inside a hydrological model
pipeline — without a Google Earth Engine account.

## Install

```bash
pip install climaclass                 # core: zero dependencies
pip install "climaclass[symfluence]"   # + SYMFLUENCE attribute-processor plugin
```

## Use

```python
from climaclass import MonthlyClimate, classify

reykjavik = MonthlyClimate(
    temp=[0.1, 0.4, 0.9, 3.3, 6.8, 9.4, 10.9, 10.5, 7.7, 4.5, 1.7, 0.4],   # °C, Jan..Dec
    precip=[76, 72, 82, 58, 44, 50, 52, 62, 67, 86, 73, 79],               # mm,  Jan..Dec
    latitude=64.1,
)

results = classify(reykjavik)
print(results["koppen"].code)        # 'Cfc'  (subpolar oceanic)
print(results["holdridge"].name)     # e.g. 'Boreal moist forest'
print(results["thornthwaite"].code)  # moisture/thermal province code
print(results["koppen"].details)     # MAT, MAP, Pthreshold, ... for QA
```

Run a single scheme directly:

```python
from climaclass import koppen
koppen.classify(reykjavik).zone      # 16  (Beck et al. legend)
```

### Input

Everything keys off one small record, `MonthlyClimate`:

- `temp` — 12 monthly **mean** temperatures (°C), January → December *(required)*
- `precip` — 12 monthly **total** precipitation (mm), January → December *(required)*
- `latitude` — optional; refines Thornthwaite PET day-length and fixes hemisphere
- `tmin` / `tmax` — optional, reserved for future scheme variants

## SYMFLUENCE plugin

The optional `symfluence` extra ships an attribute processor that emits climate
classes as **per-HRU** catchment attributes (`climate.koppen_code`,
`climate.holdridge_zone`, `climate.thornthwaite_code`, …), registered via the
`symfluence.attribute_processors` entry point and discovered automatically. Use
them as a regionalization / PUB grouping variable.

**Two data sources, in order of preference:**

1. **Remapped forcing store** (`data/model_ready/forcings/*_remapped_*.nc`) —
   the meteorology already areal-weighted to each HRU. This is the preferred
   path: true HRU resolution, consistent with what the model runs on, no ~1 km
   ceiling. Temperature/precip are auto-detected (CF standard names) and a
   12-month climatology is built per HRU; per-HRU latitude drives Thornthwaite.
2. **WorldClim fallback** — zonal statistics over the monthly rasters when no
   forcing store is present.

With a DEM present, per-HRU mean elevation enables the **Holdridge altitudinal
refinement** (`climate.holdridge_altitudinal_belt`, `…_latitudinal_region`,
`…_is_altitudinal`). No Earth Engine anywhere.

The integration is fully decoupled: importing `climaclass` never imports
SYMFLUENCE, and the engines (`classify_forcing_store`, `classify_catchment`,
`record_to_attributes`) are testable without it.

## Maps

The `viz` extra renders per-HRU classifications onto catchment geometry, with
the official Köppen-Geiger colours:

```python
from climaclass.viz import plot_classifications
plot_classifications(catchment_shp, attributes, out_path="climate_maps.png")
```

```bash
pip install "climaclass[symfluence,viz]"
```

## Develop

```bash
pip install -e ".[dev]"
pytest -q
ruff check src/
```

## License

Apache License 2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE). The
classification algorithms were prototyped in the author's
`Climate_Classifications` Earth-Engine notebooks and relicensed by the
copyright holder.
