Skip to main content

Adaptive classification of complex savanna landscapes into management-relevant land-system classes

Project description

Savana: A Geosptaial Intelligence for Savannah Landscapes

savana logo

PyPI Downloads License Stars Forks YouTube

Adaptive classification of complex savanna landscapes into management-relevant land-system classes.

Conventional LULC (land use / land cover) products typically collapse the internal structure of savanna landscapes into one or two undifferentiated "grass/shrub" classes which is too coarse to be useful for protected-area management, grazing planning, or fire regime analysis. savana implements a validated, fully adaptive classification method (Sentinel-2 + Google AlphaEarth satellite embeddings + rainfall-normalised phenology) that resolves savanna landscapes into ecologically meaningful classes such as Core Woodland, Open Woodland, Shrub-Transition Savanna, Grassland, Riparian/Wetland Vegetation, and Anthropogenic Disturbance, and does it for any AOI, with no hardcoded thresholds: every cutoff is derived from that landscape's own index percentiles.

This package started as the Google Earth Engine implementation behind a land-system classification study of West African protected areas (Kogyae, Old Oyo, and others). It's designed as a foundation, the four-model ablation (KNN baseline / RF-embeddings / RF-phenology / RF-embeddings+phenology), the RUE-validated conservative change detection, and the adaptive thresholding are all built as independent, composable modules so new sensors, feature stacks, and classification schemes can be added without breaking the existing API.

Install

pip install savana
# or, for local vector file (shapefile/geopackage) AOI support:
pip install "savana[vector]"

You'll also need an Earth Engine account with a registered Cloud project (https://code.earthengine.google.com/register).

Quick start

import savana

clf = savana.classify_landscape(
    aoi="path/to/my_area.geojson",   # or an EE asset ID, ee.Geometry, or geopandas GeoDataFrame
    epochs=[2019, 2021, 2024],
    park_name="My Study Area",
)

clf.show()                  # interactive map in Jupyter (geemap)
clf.accuracy_summary()      # pandas.DataFrame — one row per model (A/B/C/D)
clf.class_areas()           # pandas.DataFrame — area (km2) per class per epoch
clf.show_change()           # conservative + RUE-validated change map

clf.export(drive_folder="MyProject")   # push results to Google Drive

Using an Earth Engine parks database with multiple features, filtered by name (as in the original manuscript workflow):

clf = savana.classify_landscape(
    aoi="projects/ee-desmond/assets/NewParkMerged",
    name_filter="Kogyae",
    park_name="Kogyae",
    epochs=[2017, 2019, 2021, 2024],
)

Why it's adaptive

Every classification threshold (canopy density cutoffs, moisture cutoffs, seasonal amplitude cutoffs) is derived from percentiles of that AOI's own spectral index distribution at run time — nothing is hardcoded to one park's spectral range. Point this at a different savanna landscape and it recalibrates automatically.

Method overview

  1. Composites (savana.composites): cloud-masked Sentinel-2 annual/seasonal/percentile composites + AlphaEarth annual embeddings (64-dim).
  2. Indices (savana.indices): NDVI/NDMI/NDBI/MNDWI across annual, dry-season, wet-season, and percentile composites; a 14-band phenological feature stack.
  3. RUE (savana.rue): Rain Use Efficiency — integrated NDVI normalised by rainfall, with valid-month normalisation to remove Sentinel-2 tile-boundary bias.
  4. Thresholds (savana.thresholds): fully adaptive, percentile-derived cutoffs.
  5. Masks (savana.masks): six mutually exclusive land-system masks.
  6. Sampling (savana.sampling): unsupervised k-means stratified candidate sampling → rule-based provisional labels → confidence-margin filter → class balancing.
  7. Classifiers (savana.classifiers): 4-model ablation (KNN baseline, RF-embeddings, RF-phenology [diagnostic only — circular], RF-embeddings+phenology [primary]) and multi-epoch mapping, with automatic fallback to embeddings-only for years lacking reliable seasonal Sentinel-2 coverage.
  8. Change (savana.change): conservative change detection cross-validated against RUE inter-annual variability, separating genuine structural change from rainfall-driven apparent change.
  9. Accuracy / Exports (savana.accuracy, savana.exports): confusion matrices, accuracy summaries, and Drive/Asset/CSV export helpers.

Roadmap

This is the first module of a larger package. Planned additions include:

  • Additional class schemes / configurable taxonomies for other savanna biomes
  • Alternative embedding backbones (e.g. other foundation models) as drop-in options
  • Local (non-GEE) inference for pre-exported imagery
  • A CLI

Contributions and issues welcome.

Citation

If you use this package in your research, please cite the associated manuscript (citation to be added on publication).

License

Savana is free and open source software, licensed under the MIT License.

Acknowledgments

We gratefully acknowledge the support of the following organizations:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

savana-0.1.6.tar.gz (37.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

savana-0.1.6-py3-none-any.whl (40.9 kB view details)

Uploaded Python 3

File details

Details for the file savana-0.1.6.tar.gz.

File metadata

  • Download URL: savana-0.1.6.tar.gz
  • Upload date:
  • Size: 37.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for savana-0.1.6.tar.gz
Algorithm Hash digest
SHA256 be6aa45c832cf9d4b3d92e287aa6877bed4dd29ab2b2fe7efe53b7d1cc2d1e67
MD5 f92d5ebe19faa22ac3358647672d0d41
BLAKE2b-256 d4d315ade6c6e9d888345e25f3531b6a697e2a1528d857b8fc600b85deeaa565

See more details on using hashes here.

Provenance

The following attestation bundles were made for savana-0.1.6.tar.gz:

Publisher: publish.yml on desmond-lartey/savana

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file savana-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: savana-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 40.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for savana-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 8ca9615835ad2005bb3b2e0be78e85b64c340dde5416cb9b8ad6c8d496b8a342
MD5 9032369a176d8b56cf2631133cf7cd87
BLAKE2b-256 73c03c3223c6eed86fc2a5a6445b450f323e37aaba906b07bf186933f266999d

See more details on using hashes here.

Provenance

The following attestation bundles were made for savana-0.1.6-py3-none-any.whl:

Publisher: publish.yml on desmond-lartey/savana

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page