Automatic wetland detection, dynamics classification, and Wetland Cover Type characterisation from multispectral time-series data.
Project description
WetlandMapper
Automatic wetland detection, temporal dynamics classification, and Wetland Cover Type characterisation from multispectral satellite time-series data.
WetlandMapper is a Python library that operationalises two peer-reviewed remote-sensing frameworks:
| Module | Method | Output |
|---|---|---|
classify_dynamics |
MNDWI time-series aggregation (Singh & Sinha 2022, RSL) | 6 temporal dynamics classes |
classify_wct / classify_wct_ema |
MNDWI + NDVI + NDTI combination (Singh et al. 2022, EMA) | 5 biophysical cover types |
Both methods work on any multispectral archive (Landsat 4–9, Sentinel-2, etc.) and require no labelled training data. Data can be supplied by the user or fetched directly from Google Earth Engine using any Landsat mission or Sentinel-2.
Wetland Dynamics Classes
| Code | Class | Description |
|---|---|---|
| 10 | Persistent | Wet ≥ threshold % of all observations |
| 6 | Intermittent | Wet enough, but no directional trend |
| 5 | Intensifying | Increasing wet frequency over time |
| 4 | Diminishing | Decreasing wet frequency over time |
| 3 | Lost | Wet historically, dry in recent period |
| 2 | New | Dry historically, wet in recent period |
| 0 | Non-wetland | Below minimum wet-frequency threshold |
Wetland Cover Types (WCTs)
| Code | Class | Key Signal |
|---|---|---|
| 1 | Open Clear Water | High MNDWI, low NDVI, low NDTI |
| 2 | Turbid / Sediment-laden Water | High MNDWI, low NDVI, high NDTI |
| 3 | Submerged Aquatic Vegetation | High MNDWI, moderate NDVI |
| 4 | Emergent / Floating Vegetation | Moderate MNDWI, high NDVI |
| 5 | Moist / Waterlogged Soil | Low–moderate MNDWI, low NDVI |
| 0 | Non-wetland | Below water threshold |
Installation
Install using conda (recommended):
conda install -c conda-forge wetlandmapper
Using pip:
pip install wetlandmapper
With optional dependencies:
pip install "wetlandmapper[gee]" # Google Earth Engine support
pip install "wetlandmapper[plot]" # matplotlib, hvplot, bokeh
pip install "wetlandmapper[all]" # everything
Full development install:
git clone https://github.com/manudeo/wetlandmapper
cd wetlandmapper
pip install -e ".[all]"
Documentation:
https://wetlandmapper.readthedocs.io/en/latest/
Quick Start
Wetland Dynamics from your own data
import xarray as xr
from wetlandmapper import compute_mndwi, classify_dynamics
# Load a multi-temporal multispectral stack (any xarray-compatible format)
ds = xr.open_dataset("landsat_timeseries.nc")
# Step 1: compute MNDWI (Landsat 8/9 bands: green=B3, swir1=B6)
mndwi = compute_mndwi(ds, green_band="B3", swir_band="B6")
# Step 2: classify into dynamics classes
dynamics = classify_dynamics(
mndwi,
nYear=3, # years/scenes per temporal window
thresholdWet=25, # minimum wet-frequency (%) to count as wetland
thresholdPersis=75, # wet-frequency (%) for Persistent class
)
dynamics.rio.to_raster("wetland_dynamics.tif")
Wetland Cover Types from your own data
from wetlandmapper import compute_indices, classify_wct_ema
indices = compute_indices(
ds_composite,
green_band="B3", red_band="B4",
nir_band="B5", swir_band="B6", # Landsat 8/9
)
wct = classify_wct_ema(indices)
wct.rio.to_raster("wetland_cover_types.tif")
Retrieve data from Google Earth Engine
from wetlandmapper.gee import fetch
from wetlandmapper import classify_dynamics, classify_wct_ema
# AOI accepts a shapefile path, GeoJSON file path, or GeoJSON dict
aoi = "study_area/chilika.shp" # shapefile
# aoi = "study_area/chilika.geojson" # GeoJSON file
# aoi = {"type": "Polygon", ...} # GeoJSON dict
# Long-record annual composites — merges all available Landsat missions
mndwi = fetch(
aoi, start="1984-01-01", end="2023-12-31",
sensor="LandsatAll",
temporal_aggregation="annual",
use_slc_off=False, # exclude Landsat 7 post-SLC-failure images
)
dynamics = classify_dynamics(mndwi, nYear=3, thresholdWet=25, thresholdPersis=75)
# Single-sensor post-monsoon WCT composite
indices = fetch(
aoi, start="2022-10-01", end="2022-12-31",
sensor="Landsat8", index=["MNDWI", "NDVI", "NDTI"],
)
wct = classify_wct_ema(indices.isel(time=0))
Temporal aggregation
from wetlandmapper import aggregate_time
mndwi_annual = aggregate_time(mndwi_ts, freq="annual", method="median")
mndwi_seasonal = aggregate_time(mndwi_ts, freq="seasonal", method="median")
mndwi_monthly = aggregate_time(mndwi_ts, freq="monthly", method="median")
Visualisation
from wetlandmapper.plotting import plot_dynamics, plot_wct
fig, ax = plot_dynamics(dynamics)
fig.savefig("dynamics_map.png", dpi=150, bbox_inches="tight")
fig, ax = plot_wct(wct)
fig.savefig("wct_map.png", dpi=150, bbox_inches="tight")
Google Earth Engine — Sensor Reference
All Landsat collections are Collection 2 Level-2 surface reflectance.
sensor= |
GEE collection | Operational dates | Note |
|---|---|---|---|
"Landsat4" |
LT04/C02/T1_L2 | 1982–1993 | TM |
"Landsat5" |
LT05/C02/T1_L2 | 1984–2013 | TM |
"Landsat7" |
LE07/C02/T1_L2 | 1999–2022 | ETM+; SLC failure 2003-06-01 |
"Landsat8" |
LC08/C02/T1_L2 | 2013–present | OLI (default) |
"Landsat9" |
LC09/C02/T1_L2 | 2021–present | OLI-2 |
"LandsatAll" |
all 5 merged | 1982–present | auto-harmonised band names |
"Sentinel2" |
S2_SR_HARMONIZED | 2015–present | MSI |
"Landsat" is a backward-compatible alias for "Landsat8".
Use use_slc_off=False (default) to exclude Landsat 7 post-SLC-failure images.
Use use_slc_off=True to include them (covers the 2003–2012 gap before Landsat 8).
Band Name Reference (for local data)
| Sensor | Green | Red | NIR | SWIR1 |
|---|---|---|---|---|
| Landsat 4/5/7 TM/ETM+ (C02 L2) | SR_B2 |
SR_B3 |
SR_B4 |
SR_B5 |
| Landsat 8/9 OLI (C02 L2) | SR_B3 |
SR_B4 |
SR_B5 |
SR_B6 |
| Sentinel-2 L2A | B3 |
B4 |
B8 |
B11 |
| MODIS MOD09GA | sur_refl_b04 |
sur_refl_b01 |
sur_refl_b02 |
sur_refl_b06 |
Running Tests
pip install -e ".[dev]"
pytest
pytest --cov=wetlandmapper --cov-report=term-missing
Citing
If you use WetlandMapper in your research, please cite the two underlying methods and the software:
Dynamics classification:
Singh, M., & Sinha, R. (2022). A basin-scale inventory and hydrodynamics of floodplain wetlands based on time-series of remote sensing data. Remote Sensing Letters, 13(1), 1–13. https://doi.org/10.1080/2150704X.2021.1980919
Wetland Cover Types:
Singh, M., Allaka, S., Gupta, P. K., Patel, J. G., & Sinha, R. (2022). Deriving wetland-cover types (WCTs) from integration of multispectral indices based on Earth observation data. Environmental Monitoring and Assessment, 194(12), 878. https://doi.org/10.1007/s10661-022-10541-7
Software (JOSS paper — pending publication):
Singh, M. (2026). WetlandMapper: A Python package for automatic wetland mapping, dynamics classification, and cover-type characterisation. Journal of Open Source Software. https://doi.org/10.5281/zenodo.18967176
License
GPL-3.0-or-later — see LICENSE. The software is provided as-is with no warranties or guarantees of any kind.
Contact
Manudeo Singh
Department of Geography and Earth Sciences, Aberystwyth University, Aberystwyth, Wales, UK
manudeo.singh@aber.ac.uk · ORCID: 0000-0002-3511-8362
Project details
Release history Release notifications | RSS feed
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 wetlandmapper-1.0.6.tar.gz.
File metadata
- Download URL: wetlandmapper-1.0.6.tar.gz
- Upload date:
- Size: 2.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e0c2ddd537008a653c091171d2fad7775f324a98893430b8b8c10553cf144b4
|
|
| MD5 |
373cd8dc7598acc7d90114b158508b42
|
|
| BLAKE2b-256 |
c826e6dcbe8bfa2bc0584a63a5c10c6b7e695efe9d6e4e7b53fad812ee3fcbbf
|
Provenance
The following attestation bundles were made for wetlandmapper-1.0.6.tar.gz:
Publisher:
publish.yml on manudeo/wetlandmapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wetlandmapper-1.0.6.tar.gz -
Subject digest:
7e0c2ddd537008a653c091171d2fad7775f324a98893430b8b8c10553cf144b4 - Sigstore transparency entry: 1191493731
- Sigstore integration time:
-
Permalink:
manudeo/wetlandmapper@2fff77ccdf41fe7840ac864ebb14fc2b3c168422 -
Branch / Tag:
refs/tags/v1.0.6 - Owner: https://github.com/manudeo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2fff77ccdf41fe7840ac864ebb14fc2b3c168422 -
Trigger Event:
release
-
Statement type:
File details
Details for the file wetlandmapper-1.0.6-py3-none-any.whl.
File metadata
- Download URL: wetlandmapper-1.0.6-py3-none-any.whl
- Upload date:
- Size: 36.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6eaa04813f33e1b0938bc8a0e7199c4d558738c9339dae58ed5e6f03e5fef246
|
|
| MD5 |
606a997b9727cb778711c3901df4029b
|
|
| BLAKE2b-256 |
a34c90b1923fa00e965fb202916b9f718f30c62a173655ef002dff2193db3221
|
Provenance
The following attestation bundles were made for wetlandmapper-1.0.6-py3-none-any.whl:
Publisher:
publish.yml on manudeo/wetlandmapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wetlandmapper-1.0.6-py3-none-any.whl -
Subject digest:
6eaa04813f33e1b0938bc8a0e7199c4d558738c9339dae58ed5e6f03e5fef246 - Sigstore transparency entry: 1191493734
- Sigstore integration time:
-
Permalink:
manudeo/wetlandmapper@2fff77ccdf41fe7840ac864ebb14fc2b3c168422 -
Branch / Tag:
refs/tags/v1.0.6 - Owner: https://github.com/manudeo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2fff77ccdf41fe7840ac864ebb14fc2b3c168422 -
Trigger Event:
release
-
Statement type: