Savana: A Geosptaial Intelligence for Savannah Landscapes
A geospatial intelligence ecosystem for savanna landscapes.
savana is a growing Python ecosystem for understanding, monitoring, and reasoning
about savanna landscapes. It's starting with a validated adaptive land-system
classification method, and built from the ground up so that every result it produces
can be queried, summarized, and acted on through natural language, not just read off
a map. Classification of landscapes from raw satellite data to actionalble insights is the foundation.
Statement of need
Savannas cover roughly a fifth of the Earth's land surface and support some of the highest concentrations of biodiversity, pastoralist livelihoods, and protected-area coverage anywhere in the world. Nowhere more so than across West and Central Africa, where savanna mosaics form the ecological backbone of national parks, wildlife corridors, and rangelands under mounting pressure from land conversion, fire regime change, and rainfall variability. But the land use / land cover (LULC) products most available to researchers and park managers in this region routinely collapse this entire structural complexity into one or two undifferentiated "grass/shrub" classes which is too coarse to answer the questions that actually matter for management: where is canopy genuinely closing versus opening, which areas show real structural degradation versus rainfall-driven greenness swings, and where should limited conservation and grazing-management resources actually go.
This gap is not just a mapping problem, it is also an access problem. Analysts in
under-resourced institutions often have the satellite data and the research question,
but not the specialized remote-sensing pipeline needed to turn one into the other,
nor the time to manually interrogate every output. savana addresses both halves at
once. That is, an adaptive classification method with no hardcoded thresholds, so it
recalibrates to any savanna landscape's own spectral distribution rather than
assuming one park's canopy density applies to another's; and a built-in AI layer that
lets anyone, not just remote-sensing specialists, ask what a result means, in plain
language, based on strictly in what was actually computed.
Current Key features
Adaptive land-system classification
- Resolves savanna landscapes into ecologically meaningful classes, Core Woodland, Open Woodland, Shrub-Transition Savanna, Grassland, Riparian/Wetland Vegetation, Anthropogenic Disturbance, for any AOI, with every threshold derived from that landscape's own index percentiles at run time. Classes are extendable.
- Four-model ablation (KNN baseline / RF-embeddings / RF-phenology / RF-embeddings+phenology) built on Sentinel-2, Google AlphaEarth satellite embeddings, and rainfall-normalised phenology
- Multi-epoch mapping with automatic fallback to embeddings-only classification for years lacking reliable seasonal Sentinel-2 coverage
Change detection
- Conservative change detection cross-validated against Rain Use Efficiency inter-annual variability, separating genuine structural change from rainfall-driven apparent change
Analytical insights
- Plain-English summaries and question-answering generated entirely from real computed results, every figure traces back to an actual pipeline output.
AI agent, SavanaGeoAgent
- Natural-language access to your results and your map in one place: ask about class areas, accuracy, or change; ask it to show years on the map, compare them, fly to locations, or add basemaps
- Built on real, proven infrastructure (Strands + any geoai map tooling) with savana's own evidence tools layered on top
- Ships with an inline chat + live-map UI (
agent.show_ui()) for exploring results without writing further code
Interactive visualization
geemap,geolibre-based maps in Jupyter, with year-toggle, swipe/split comparison against another year or the underlying basemap, and change-layer visualization- Optional GeoLibre backend for teams already working in that ecosystem
Data export
- Google Drive / Earth Engine Asset export for classified maps and change products;
confusion matrices and area statistics as
pandas.DataFrameor CSV
Install
pip install savana
# or, for local vector file (shapefile/geopackage) AOI support:
pip install "savana[vector]"
# or, for the AI agent:
pip install "savana[agents]"
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.summarize() # plain-English report, grounded in real computed results
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],
)
Ask your results questions
from savana.agents import SavanaGeoAgent
agent = SavanaGeoAgent(clf, model="anthropic", model_id="claude-sonnet-4-6")
agent.ask("How much core woodland is there in 2024?")
agent.ask("Show 2019 and 2024 on the map")
agent.ask("What changed between the years, and how much of it is genuine?")
agent.show_ui() # live map + chat, inline in the notebook
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.
Core classification pipeline
- Composites (
savana.composites): cloud-masked Sentinel-2 annual/seasonal/percentile composites + AlphaEarth annual embeddings (64-dim). - Indices (
savana.indices): NDVI/NDMI/NDBI/MNDWI across annual, dry-season, wet-season, and percentile composites; a 14-band phenological feature stack. - RUE (
savana.rue): Rain Use Efficiency, integrated NDVI normalised by rainfall, with valid-month normalisation to remove Sentinel-2 tile-boundary bias. - Thresholds (
savana.thresholds): fully adaptive, percentile-derived cutoffs. - Masks (
savana.masks): six mutually exclusive land-system masks. - Sampling (
savana.sampling): unsupervised k-means stratified candidate sampling → rule-based provisional labels → confidence-margin filter → class balancing. - Classifiers (
savana.classifiers): 4-model ablation and multi-epoch mapping. - Change (
savana.change): conservative, RUE-validated change detection. - Insights (
savana.insights): grounded facts, summaries, and Q&A. - Agents (
savana.agents): natural-language access to results and map control. - Accuracy / Exports (
savana.accuracy,savana.exports): confusion matrices, accuracy summaries, and Drive/Asset/CSV export helpers.
Roadmap
savana is the first module of a larger ecosystem. 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
- Deeper agent integration with map-hosted UIs, beyond the current notebook experience
- A CLI
Contributions and issues welcome.
Citation
If you use this package in your research, please cite the associated manuscript.
License
Savana is free and open source software, licensed under the MIT License.
Acknowledgments
We gratefully acknowledge the support of the following organizations:
- Irish Research Council: This research is supported by the Government of Ireland Postgraduate Scholarship through Grant No. GOIPG/2025/8306, awarded under the Reseearch Ireland Program.
- Department of Geography: This work is also partially supported by the department of Geography, Mary Immaculate College.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file savana-0.1.15.tar.gz.
File metadata
- Download URL: savana-0.1.15.tar.gz
- Upload date:
- Size: 95.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f225f39ab11306bf76b8be2cc57f338fa34f04c83903135fc1b1174223de2711
|
|
| MD5 |
1cd53480f6585aec2bb964a7d7e82231
|
|
| BLAKE2b-256 |
70121c7f909abedc3562b8c3c2017f3803251d299b18b880c4b51687ff35eda0
|
Provenance
The following attestation bundles were made for savana-0.1.15.tar.gz:
Publisher:
publish.yml on desmond-lartey/savana
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
savana-0.1.15.tar.gz -
Subject digest:
f225f39ab11306bf76b8be2cc57f338fa34f04c83903135fc1b1174223de2711 - Sigstore transparency entry: 2187755807
- Sigstore integration time:
-
Permalink:
desmond-lartey/savana@e2bc166dec8ae2b32fec7929bc118cecc39b3f2d -
Branch / Tag:
refs/tags/v0.1.15 - Owner: https://github.com/desmond-lartey
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e2bc166dec8ae2b32fec7929bc118cecc39b3f2d -
Trigger Event:
push
-
Statement type:
File details
Details for the file savana-0.1.15-py3-none-any.whl.
File metadata
- Download URL: savana-0.1.15-py3-none-any.whl
- Upload date:
- Size: 105.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac28163613dac10007788b96586d7cac948b8a5d93139eb73d09874a21693c2d
|
|
| MD5 |
ee3530199a32c4e12d0c4ab3946358c8
|
|
| BLAKE2b-256 |
99ebec7c9f2b295a36ea5d342bd2e5c79e66d7e65e9420f471e9a37eef8b847d
|
Provenance
The following attestation bundles were made for savana-0.1.15-py3-none-any.whl:
Publisher:
publish.yml on desmond-lartey/savana
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
savana-0.1.15-py3-none-any.whl -
Subject digest:
ac28163613dac10007788b96586d7cac948b8a5d93139eb73d09874a21693c2d - Sigstore transparency entry: 2187755828
- Sigstore integration time:
-
Permalink:
desmond-lartey/savana@e2bc166dec8ae2b32fec7929bc118cecc39b3f2d -
Branch / Tag:
refs/tags/v0.1.15 - Owner: https://github.com/desmond-lartey
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e2bc166dec8ae2b32fec7929bc118cecc39b3f2d -
Trigger Event:
push
-
Statement type: