Anisotropic least-cost path, corridor (LCC), From-Everywhere-To-Everywhere (FETE), stochastic (probabilistic) paths, sensitivity analysis and route validation (Path Deviation Index + buffer overlap) for QGIS — built for archaeological movement modelling.
No external pip packages required: the numerics use numpy and scipy, both bundled with QGIS. Raster I/O uses GDAL (also bundled).
| Component | Form | Status |
|---|---|---|
| Slope cost surface (accumulated) | Processing | working |
| Friction cost surface (accumulated) | Processing | working |
| Composite friction (multi-criteria) | Processing | working |
| Accessibility / cost catchment | Processing | working |
| Least-cost path | Processing | working |
| Stochastic LCP (probabilistic corridor) | Processing | working |
| Least-cost corridor (LCC) | Processing | working |
| FETE | Processing | working |
| Randomized shortest paths (RSP) | Processing | working |
| Circuit current density / pinch points | Processing | working |
| Connectivity barriers / restoration | Processing | working |
| Sensitivity analysis (cost fn × connectivity) | Processing | working |
| PDI validation | Processing | working |
| Buffer-overlap validation | Processing | working |
| Resample DEM (block mean) | Processing | working |
| DEM error realisation | Processing | working |
| Interactive two-click LCP | Toolbar tool | working (cost fn + neighbourhood selectable) |
Each cell becomes a graph node; edges connect neighbouring cells (4/8/16).
Edge weight is a directional cost function (slope = rise/run signed by
travel direction), so the conductance matrix is asymmetric = true
anisotropy. Paths are solved with scipy.sparse.csgraph.dijkstra.
- Corridor: sum of two accumulated surfaces — one from the origin, one from the destination grown on the reversed graph (correct for anisotropy).
- FETE: LCPs between all
n(n-1)directed ordered pairs (both directions, for anisotropy), traversal frequency per cell (White & Barber 2012). Cost scales ~O(n²) in the number of points. - PDI (Jan et al. 2000): area between modelled and reference polyline /
straight-line O–D distance = mean lateral deviation in map units (endpoints
snapped to the reference O/D first, per
leastcostpath). - Buffer-overlap validation (Goodchild & Hunter 1997): for each tolerance distance, the share (%) of the modelled path within that distance of the reference — a multi-distance similarity table beside the PDI.
- Sensitivity analysis: sweeps the selected cost functions × connectivities for one O/D pair → an agreement raster (per-cell path frequency), a per-configuration summary table, optional individual paths, and a route-stability scalar (mean pairwise buffer-overlap).
- Friction: a cost-per-metre raster (vegetation, wadis, geology) drives the surface directly (isotropic), or — with an optional DEM — acts as a dimensionless multiplier on the anisotropic slope cost (combined mode).
- Composite friction (multi-criteria) — a generic Itinera heuristic combiner (in the spirit of Herzog 2022; Litvine 2024, not a reproduction of their domain-calibrated models): merges several penalty rasters (hydrology, wetness, land cover, viewshed masks) into one friction multiplier — each min-max normalised, optionally inverted, weighted, and combined by a weighted sum or product; NoData → impassable. Note min-max normalisation makes the result extent-dependent. Feed it into the slope tools as the barrier/multiplier raster.
- Accessibility / cost catchment (Verhagen 2019): cost-distance from source point(s) — a movement-potential surface — plus an optional catchment mask (reachable within a cost budget) and isochrone bands.
- Barrier / multiplier: an optional raster on the slope-based algorithms (slope cost surface, LCP, LCC, FETE) scales edge cost by the mean of its two cells (>1 discourages, <1 prefers known roads); NoData/≤0 cells are impassable (cliffs, deep wadis).
- Stochastic LCP (Lewis 2021): N Monte-Carlo realisations adding a spatially-correlated DEM error (RMSE-scaled) and/or randomly dropping edges, accumulating how often each cell lies on the least-cost path → a probabilistic corridor in [0, 1]. The error field is a variogram Gaussian random field (exponential/spherical/gaussian + nugget, FFT spectral simulation) — an Itinera construction in the spirit of the correlated DEM-error literature (Hunter & Goodchild 1997 use an autoregressive model; Lewis 2021 uses filtered noise + sink-fill), not a reproduction of either — with a fast Gaussian-filter option; a standalone DEM error realisation tool outputs a single perturbed DEM. The corridor also propagates cost-model uncertainty (Herzog 2022): each realisation can sample a cost function from a weighted set and jitter its parameters. An optional convergence criterion (stabilisation or precision) stops the Monte-Carlo loop early once the corridor has settled, reporting the live metric. Set a seed for reproducibility.
- Randomized shortest paths (RSP) (Panzacchi 2015; van Etten 2017): a single
parameter θ tunes between the least-cost path (θ→∞) and the random-walk /
circuit current density (θ→0), with realistic exploratory movement in between.
Output is a movement-density surface plus the RSP free-energy distance, solved
in pure
scipy.sparseover the existing conductance matrix. - Circuit theory (McRae 2008, 2012): movement as electrical current flow —
solve the graph Laplacian (
Lv = i) for current density (where movement concentrates), pinch points (high current within the least-cost corridor), and barriers / restoration (McRae 2012 moving-window improvement score). Circuit theory is undirected, so the conductance is symmetrised — for the anisotropic current use RSP at small θ.
Cost functions included (ten): Tobler (on/off-path), Herzog, Naismith,
Llobera & Sluckin, Irmischer & Clarke (GPS-calibrated speed), Minetti
(cost of transport), Pandolf (load-aware metabolic rate with the
Santee/Yokota downhill correction), and the movement-mode presets Wheeled
(cart) and Pack animal — experimental Itinera heuristics (anisotropic
critical-slope functions with illustrative default thresholds; the critical-slope
concept is from Herzog 2013 / Verhagen 2019, but Herzog's vehicle function is
symmetric and no validated pack-animal function exists — set the thresholds to
your own evidence). Pandolf reads optional
body-mass / load / terrain parameters, threaded from the GUI via cost_params
on every conductance-building algorithm. Add your own in core/cost_functions.py
(signature (slope, distance, **_) -> cost) and register it in the
COST_FUNCTIONS dict + labels list.
- User manual — concepts, per-algorithm guide with parameters, a worked example, performance/memory notes and troubleshooting.
- References / references.bib — the literature behind each cost function and method.
- Python library — the GUI-free numerics are also on PyPI
(
pip install itinera); seeREADME-pypi.md.
From the QGIS Plugin Repository (recommended): the plugin is published at plugins.qgis.org/plugins/itinera. In QGIS → Plugins → Manage and Install Plugins, search for Itinera and click Install. (It is currently flagged experimental, so tick Settings → Show also experimental plugins if it doesn't appear.)
From a ZIP (alternative):
- Download
itinera-<version>.zipfrom the Releases page — or build it yourself withmake zip(wrapsscripts/package-plugin.sh, which packages only the committed runtime files, dev/CI files stripped). - QGIS → Plugins → Manage and Install Plugins → Install from ZIP.
- Enable Itinera – Least-Cost Pathways.
- Algorithms appear in the Processing Toolbox under Itinera – Least-Cost Pathways. The interactive tool and its settings appear as two buttons on the Plugins toolbar (View → Toolbars → Plugins Toolbar if it's hidden) and also under Plugins → Itinera.
Requires QGIS ≥ 3.28 and runs on QGIS 4.0 (Qt6) as well — Qt access goes
through the qgis.PyQt compatibility layer. Use a projected CRS in metres
(e.g. EPSG:32637 / EPSG:28191) for DEM and points so slope and distance are
metric.
The GUI-free core/ numerics have a pytest suite that runs outside QGIS (no
qgis/GDAL needed):
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements-dev.txt
pytestIt gates on the project invariants — the conductance matrix stays asymmetric,
edge/path costs are finite and positive, friction-only surfaces are symmetric,
and the corridor's transpose contract holds. CI runs the same suite
(.github/workflows/tests.yml).
- The interactive map tool's cost function and neighbourhood are set via the "Interactive LCP settings…" button on the Plugins toolbar (or Plugins → Itinera); defaults are Tobler, 8-neighbour.
- The full conductance matrix is held in memory (~
cells × neighboursedges). The graph algorithms warn above ~4M cells; for very large DEMs, clip or run Resample DEM (block mean) first (cuts cells byfactor²). A true tiled builder with cross-tile path stitching is out of scope for now. - 16-neighbour reduces grid metric distortion but quadruples edge count.
- FETE on many points is expensive; start small.
The original roadmap is complete. Possible future directions — built as needed and in response to user feedback, not committed milestones:
- a true tiled conductance builder with cross-tile path stitching (for DEMs too large to hold in memory);
- a FETE-style stochastic network (probabilistic all-pairs corridors);
- additional cost functions.
Have a use case that needs one of these, or something else? Please open an issue — priorities follow demand.
Versions follow Semantic Versioning; metadata.txt
version= is the single source of truth. Release notes live in
CHANGELOG.md.
Licensed under the MIT License — see LICENSE.