Chapter 32: Migrating from TerraME/LUCCME to DisSModel¶
Part VII — Scaling, Migration & Reference
Learning Objectives¶
By the end of this chapter you will be able to:
- Translate TerraME/LUCCME concepts to their DisSModel equivalents
- Know what numerical equivalence guarantees already exist in the ecosystem
- Plan an incremental migration of an existing model, and validate it properly before trusting it
# Standard imports
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
This chapter is for one specific reader: someone who already has a working TerraME or LUCCME model, written in Lua, and is deciding whether — and how — to bring it into the ecosystem the rest of this book has spent twenty-eight chapters building. Nothing here requires new code from you to follow along; it's a map, meant to be read once before a real migration starts, then kept open beside the model you're actually moving.
Why Migrate¶
TerraME is C++/Lua, its most recent release from 2020, installed through OS-specific installers. That alone is a real cost: every year since, the surrounding Python scientific ecosystem — the one this book has built fluency in since Chapter 1 — has kept moving, and a TerraME model can't import geopandas or hand its state to pandas for analysis without leaving its own language entirely first.
DisSModel's pitch is narrow and specific, not "newer is better" in the abstract: pip install, the same code running from a single notebook (Chapter 22) to a distributed platform (Chapter 29) with no rewrite in between, and — where a DisSModel port exists — numerically validated against the original TerraME output, not just "inspired by" it. That last property is the one Existing Validation Cases returns to directly, because it's the difference between a migration you can trust and one you're merely hoping matches.
General Equivalence Table¶
| TerraME/LUCCME concept | DisSModel equivalent |
|---|---|
| TerraME (the framework itself) | dissmodel |
| LUCCME (continuous allocation) | disslucc-continuous |
| CLUE-S-like discrete allocation | disslucc-discrete |
| TerraLib (data I/O) | geopandas / rasterio (Chapters 7–8) |
fillCellularSpace |
disscube (Chapter 30) |
Agent / Society |
dissmodel-abm's AgentModel / Society (Chapter 25) |
init(self) |
setup() (Chapter 21) |
execute(self) |
execute() (Chapter 21) |
explicit past/present CellularSpace copies |
implicit, via CellularAutomaton.execute() (Chapters 21, 24) |
Every row here has already come up once in this book, in a different context — this table's real job is just to collect them in one place, indexed by the TerraME term you'd actually search for.
Step-by-Step Incremental Migration¶
1. Identify the original model's paradigm. A TerraME CellularSpace with a per-cell rule maps onto Chapter 24's CellularAutomaton; a stock-and-flow model maps onto Chapter 23's plain Model; an Agent/Society model maps onto Chapter 25's AgentModel. A LUCCME-style continuous allocation and a CLUE-S-like discrete allocation each have their own dedicated satellite package, and a coupled raster/vector domain model — BR-MANGUE's coastal dynamics being the ecosystem's own worked example — maps directly onto the SpatialModel/RasterModel pair from Chapter 21.
2. Choose the corresponding satellite package, or build directly on dissmodel.core/dissmodel.geo if none fits — exactly what dissmodel-ca and dissmodel-sysdyn themselves do. Install it the same way every extension package in this book has been installed since Chapter 22: straight from GitHub, no PyPI release yet.
3. Map the input data. Wherever TerraME used TerraLib to read a CellularSpace's data, DisSModel uses geopandas/rasterio directly — a shapefile or GeoPackage becomes a GeoDataFrame (Chapter 7), a GeoTIFF becomes a RasterBackend (Chapter 8). If the original data needs aligning to a modeling grid first — resampling, zonal aggregation, deriving driver variables from a raw source — that step belongs to disscube (Chapter 30), not to the model executor itself.
4. Validate outputs against the original model, before trusting the migration in production. This is the step Existing Validation Cases exists to make concrete — never skip it, and never treat "the migrated model runs without an error" as evidence it's correct.
Existing Validation Cases in the Ecosystem¶
The ecosystem doesn't just claim numerical fidelity to TerraME/LUCCME — several packages bake the comparison directly into their own automated tests, in two distinct styles depending on what kind of output is being compared:
- Tolerance-based, for continuous output. A migrated model's own benchmark suite runs the DisSModel version and a TerraME/LUCCME reference dataset side by side, and asserts the mean absolute error and root-mean-square error between them stay below a configurable tolerance. This is the right bar for anything fractional — a percentage, a continuous allocation weight — where "close" is a meaningful, expected outcome and exact bit-for-bit agreement isn't.
- Exact parity, for categorical output. A discrete land-use allocation model instead asserts 100% cell-level agreement against the original reference — accuracy, Cohen's κ, and F1 score all equal to exactly 1.0, not "close enough." Land use is categorical: a cell is forest or it isn't, and a tolerance band doesn't mean anything for a label that has no notion of "almost correct."
The rule this splits into: pick the validation style that matches your migrated variable's type, not the other way around. Forcing a categorical variable through a tolerance check hides real disagreements; forcing a continuous variable through exact-parity checking will fail on harmless floating-point noise that was never the point. Wherever the ecosystem's own packages do this today, the check runs automatically in continuous integration — every code change gets re-validated against the TerraME reference immediately, not just once at migration time.
Exercises¶
- Sketch a skeleton. Take a hypothetical TerraME model whose
CellularSpacelooks only at each cell's 4 cardinal neighbors inexecute(self). Using the equivalence table and Chapter 24'sFireModelas a reference, write the class skeleton — imports, base class, neighborhood strategy — you'd start a DisSModel port from. You don't need to implementrule()itself, just the setup. - Pick the right validation style. A colleague migrating a LUCCME model asks whether to validate with a tolerance-based benchmark or an exact-parity check. What single fact about their model's output — from Existing Validation Cases — actually answers that question?
- Where does disscube enter? Chapter 30 noted that
disscubehas no direct code dependency on the LUCC-style packages — the connection is a sharedRasterBackendcontract, not an import. If you were migrating a TerraME model whose driver variables came from a raw MapBiomas raster, at which numbered step in Step-by-Step Incremental Migration woulddisscubeactually enter the picture — and why not a step earlier or later? - Weigh the urgency. Given Why Migrate's note that TerraME's most recent release dates to 2020, what does that fact alone tell you about migration urgency for an inherited TerraME model — compared to a model built on some other framework that's simply unfamiliar to you, but still actively maintained?
# Your code here
Summary¶
Key concepts introduced¶
- Migrating from TerraME/LUCCME is a mapping exercise more than a rewrite:
init/executebecomesetup/executeon the identical four-hook lifecycle from Chapter 21, and every TerraME concept in the equivalence table already has a DisSModel home - A four-step incremental migration path: identify the paradigm, choose the satellite package, map the input data (with
disscubehandling grid alignment specifically), then validate - Two validation styles, chosen by output type — tolerance-based (MAE/RMSE) for continuous variables, exact parity (accuracy, Cohen's κ, F1 all equal to 1.0) for categorical ones — never the reverse
- "Runs without an error" is necessary but never sufficient; the real bar is measured numerical agreement with the original TerraME/LUCCME output on a known dataset
- Even where a satellite package already exists, it may not cover every feature the original TerraME model used — Chapter 25 documented
dissmodel-abm's own gaps as one concrete example; checking a package's stated scope before assuming full coverage is part of the migration itself, not a separate step
Chapter 33 closes the book with the ecosystem's own architecture and contribution process — useful reading whether your migration surfaces a gap worth filling, or you simply want to understand how the pieces you've spent this book learning actually fit together.
Further Reading¶
- TerraME on GitHub: https://github.com/TerraME/terrame
- LuccME documentation (INPE): http://www.dpi.inpe.br/luccme/
- disslucc-continuous and disslucc-discrete on GitHub: https://github.com/DisSModel
- brmangue-dissmodel on GitHub: https://github.com/DisSModel/brmangue-dissmodel