Land use and land cover change (LUCC) modeling, raster-only,
script-first, on top of dissmodel.
LuccME's components -- demand, potential, allocation -- in Python:
continuous (CLUE-like), discrete (CLUE-S-like), spatial-lag potential,
saturation, and demand computed from land-use layers. It is an alternative
that you can run next to TerraME/LuccME, not a replacement for them.
Agreement with TerraME/LuccME (iteration counts, per-year error, timings, 10 of the 21 LuccME labs so far) is checked in LambdaGeo/disslucc-benchmark, which pins the release of disslucc it ran against. This repository is the package and the examples to learn it with.
disslucc is migrating from two separately maintained repositories
(disslucc-continuous, disslucc-discrete) into one single
repository, mirroring how the original
terrame/luccme is itself one
repository with continuous and discrete components side by side,
instead of split by paradigm. Two reasons:
- Efficiency. As more Demand/Potential/Allocation strategies are developed, maintaining two parallel implementations (vector + raster, continuous repo + discrete repo, each with its own Demand/validation code duplicated) doesn't scale and gets confusing fast. Consolidating into one raster-only package, with Demand and Pontius & Millones validation shared across both paradigms, removes that duplication.
- One clear reference. A single repository is a much stronger "LuccME in Python" story than pointing people at two packages that together replicate it.
This repository is moving from github.com/LambdaGeo/disslucc to
github.com/DisSModel/disslucc, alongside dissmodel,
disslucc-continuous, and disslucc-discrete. The two source
repositories will be released, tagged, archived, and kept citable once
this migration completes — see
docs/decisions.md for the full reasoning,
status, and what's still pending (this does not happen before
dissmodel's JOSS review concludes, so existing citations aren't
disrupted mid-review).
pip install -e ".[examples]"from dissmodel.core import Environment
from disslucc import DemandInline, PotentialLinearRegression, AllocationClueLike
from disslucc.schemas import RegressionSpec, AllocationSpec
demand = DemandInline(values=[...], land_use_types=["forest", "urban"])
potential = PotentialLinearRegression(backend=backend, demand=demand, ...)
allocation = AllocationClueLike(backend=backend, demand=demand, potential=potential, ...)
Environment(end_time=7).run()No ModelExecutor, no TOML, no CLI — the script is the complete
experiment, reproducible with git clone && pip install -e . && python3 script.py.
When automatic provenance matters more than simplicity (production,
CI), disslucc.executors brings ModelExecutor/ExperimentRecord
back as a second entry point — same math, identical result, see
api.md. This is also
the entry point registered in
dissmodel-configs
to run on dissmodel-platform, and it comes with a CLI, via
dissmodel.executor.cli.run_cli:
python -m disslucc.executors.continuous run \
--toml examples/dissmodel-configs/lucc_continuous.toml \
--input data/input/csAC.zip \
--param demand_csv=data/input/examples_demand_lab1.csv \
--output outputs/result.tif # local path or s3://bucket/key (MinIO)
python -m disslucc.executors.discrete run \
--toml examples/dissmodel-configs/lucc_discrete.toml \
--input data/input/cs_moju.zip \
--param demand_csv=data/input/demand_moju.csv \
--output outputs/result.tif--output writes a GeoTIFF with one band per land-use class (+ mask),
georeferenced from the input's CRS/extent -- open it directly in QGIS,
locally or straight from MinIO.
Both commands above run end-to-end as written -- pyproject.toml pins
dissmodel>=0.6.4, which merges [model]-level spec into
record.parameters for local --toml runs (this used to require an
unreleased fix; see docs/decisions.md for that history if you're
curious).
examples/dissmodel-configs/ has a TOML config per executor
(continuous,
discrete), each
encoding the same coefficients as its examples/run_*_executor.py
counterpart — see api.md
for the full explanation.
- quickstart.md — installing, the first model, ready-made examples
- api.md — reference for every class and parameter
- architecture.md — what's faithful to the original repositories, what was simplified, what's new
- validation.md — where the comparison with TerraME lives: disslucc-benchmark
- decisions.md — full history of decisions and tests throughout development
Wider ecosystem context: chapter 26 (Land Use and Cover Change Modeling) of the Geospatial Modeling with Python book (LambdaGeo) -- still a draft, but where "DisSLUCC" as a family name is documented for the first time.
pip install -e ".[dev]"
mypy src/disslucc
pytest tests/ -vCI (.github/workflows/tests.yml) runs ruff, mypy and the tests on every push
and pull request. tests/ covers the demand components and checks that each
example TOML, run through the CLI, produces the same output file as the
equivalent hand-built experiment. Agreement with TerraME/LuccME is not tested
here: it is the job of
disslucc-benchmark, which pins
the disslucc release it ran against.
Use the DOI of the release you used (Zenodo, badge above once published) and
CITATION.cff.
disslucc/
├── src/disslucc/
│ ├── protocols.py, schemas.py
│ ├── components/ # same convention as the original repositories
│ │ ├── demand/ # shared continuous + discrete
│ │ ├── potential/ # linear.py (continuous) + logistic.py (discrete)
│ │ └── allocation/ # clue.py (continuous) + clue_s.py (discrete)
│ ├── validation/ # Pontius & Millones metrics, naive baseline (outside components/, see architecture.md)
│ └── executors/ # ModelExecutor -- automatic provenance, second entry point
├── examples/ # ready-made scripts: synthetic, real data, executor, TOML configs
├── data/input/ # vendored example inputs (csAC, cs_moju) and demand CSVs
├── tests/ # pytest suite: demand components, TOML == executor
└── docs/