lsdtt3 QGIS plugin
The plugin adds an lsdtt3 group to the QGIS Processing Toolbox. Each algorithm runs one of the lsdtt3 command-line tools, so you install two things: the plugin and a backend (the command-line tools for your system).
Installation
1. Download the plugin and the backend for your system. These links always fetch the latest release:
| What | Download |
|---|---|
| Plugin (all systems) | lsdtt3-qgis-plugin.zip |
| Backend, Windows | lsdtt3-backend-win64-qgis.zip |
| Backend, macOS Apple Silicon (M1 and later) | lsdtt3-backend-macos-arm64-qgis.tar.gz |
| Backend, macOS Intel | lsdtt3-backend-macos-x86_64-qgis.tar.gz |
| Backend, Linux | lsdtt3-backend-linux-x86_64-core.tar.gz |
Download both from GitHub, not from another copy you come across: the plugin
and the backend must come from the same X.Y series (plugin 0.9.x works with
any 0.9.x backend; see Versioning). Older
releases are on the list of releases.
2. Unpack the backend into a folder of its own, for example in your Documents folder. Do not unpack the plugin zip.
- Windows: right-click the zip, Extract All…
- macOS: double-click the
.tar.gz, then, in Terminal, clear the quarantine flag the browser set, or macOS blocks the tools:xattr -dr com.apple.quarantine <unpacked folder>. The backend's ownREADME.mdhas the details. - Linux:
tar -xzf lsdtt3-backend-linux-x86_64-core.tar.gz
3. Install the plugin in QGIS: Plugins → Manage and Install Plugins… →
Install from ZIP, choose lsdtt3-qgis-plugin.zip, and click Install
Plugin.
4. Point the plugin at the backend: open lsdtt3 → LSDTT Backend
Settings and select the unpacked backend's root folder, the one containing
bin/, share/ and manifest.json (not bin/ itself). Saving checks the
folder for every tool the plugin uses.
5. Check it works: run Raster Preprocessing from the lsdtt3 group of the Processing Toolbox on a small DEM, with hillshade switched on.
To update later, repeat steps 1–4: Install from ZIP replaces the plugin in place, and the new backend goes in a new folder, which you then select in the settings. More on that, and on fixing errors, is in Updating to a new version and Backend command-line tools below.
Developers: how the plugin, its backend bundle and their version checks fit
together, and the loop for changing them, is in
QGIS plugin development
on the documentation site. Packaging commands are in
tools/README.md.
Algorithms
The plugin adds an lsdtt3 group to the Processing Toolbox. Every algorithm writes a parameter file next to the input DEM and runs one backend CLI, so any run can be repeated from the command line (the parameter file's header gives the command).
| Algorithm | Backend CLI | What it does |
|---|---|---|
| Raster Preprocessing | lsdtt-raster-preprocessing |
Reproject, mask, fill nodata, edge-preserving smoothing, pixel replacement, breach or fill depressions (with flat resolution and sink candidates), vertical-unit checks, hillshade |
| Clip Raster to Polygon | lsdtt-raster-preprocessing |
Crop a raster to a polygon, optionally masking outside it |
| Clip Vector to Raster Extent | lsdtt-raster-preprocessing |
Clip a vector layer to a raster's bounding box (any CRS) |
| Mosaic Rasters | lsdtt-raster-preprocessing |
Merge pixel-aligned rasters on the same grid into one |
| Sample Rasters at Points | lsdtt-raster-preprocessing |
Sample a list of rasters at each point of a point layer |
| Channel Extraction | lsdtt-channel-extraction |
Channel sources (threshold or Wiener), network lines, points and junctions |
| Chi Analysis | lsdtt-chi-analysis |
Chi extraction, chi-network fitting with an m/n sweep, k_sn maps |
| Basin Extraction | lsdtt-basin-extraction |
Basins by junction, outlet, nesting, order or crossing line, with filters |
| Side Tributary Basins | lsdtt-basin-extraction |
Basins draining into the side of one main channel |
| Basin Statistics | lsdtt-basin-stats |
Per-basin relief, hypsometry, shape and channel statistics |
| Surface Metrics | lsdtt-surface-metrics |
Hillshade, relief, polyfit slope, aspect and curvature, roughness; Frangi, Otsu, Hough, curvature skeletons and adaptive VEC thresholding |
| Channel Network Analysis | lsdtt-channel-network-analysis |
Link bearings, junction angles, Strahler and Tokunaga layers, area ratios |
| Swath Profile | lsdtt-swath-profile |
Percentiles of a raster binned along a baseline line |
| Drainage Area | lsdtt-drainage-analysis |
D8, D-infinity and/or MFD drainage area |
| Topographic Wetness Index | lsdtt-drainage-analysis |
ln(a / tan b) from D-infinity or MFD routing |
| Sediment Connectivity Index | lsdtt-drainage-analysis |
Cavalli et al. (2013) index, with its D_up and D_down rasters |
| Height Above Channel | lsdtt-drainage-analysis |
Height of each pixel above the channel its flow path reaches |
| Soil Topographic Index | lsdtt-drainage-analysis |
Wetness index less a soil term from soil and land-use data |
Each algorithm's form shows the parameter help from the backend itself, and the full parameter lists are in the CLI reference pages.
Which CLIs the backend needs
The plugin uses the nine CLIs in the table. The qgis backend bundle ships
exactly these (the qgis profile in tools/cli_profiles.txt).
- When you save a backend folder in
lsdtt3 -> LSDTT Backend Settings, the plugin checks for all nine and warns, naming every one that is missing. The folder is still saved. - When you run an algorithm, only that algorithm's CLI must be present. An older bundle still runs the algorithms it has; the others stop before anything runs, with a message naming the missing CLI.
Bundles made before this release have no lsdtt-swath-profile or
lsdtt-drainage-analysis. Install a new bundle to use Swath Profile and the
five drainage algorithms.
Versioning (plugin and backend)
The plugin and the backend share one version number, the lsdtt3 version. It is
set in project(lsdtt3 VERSION ...) in the root CMakeLists.txt;
qgis_plugin/lsdtt_qgis/metadata.txt carries a copy, and tools/set_version.py
changes both together.
- Plugin version comes from
metadata.txt([general] version=...) and is used in the plugin zip name generated byqgis_plugin/package_plugin.py. - Backend version comes from the version passed to the packaging script and
is written into the backend bundle name and
manifest.json(backend_version).
The rule: a plugin X.Y.* accepts a backend X.Y.*. Major and minor must
match; the patch level is free, so a plugin-only or backend-only patch release
still works with the other. A minor version bump marks a change the other side
depends on, such as a renamed parameter the wrappers emit. A backend from
another series is refused before anything runs, with a message saying whether
to install the matching backend or upgrade the plugin.
The bundle's manifest.json also carries plugin_version_range. The packaging
scripts set it to the bundle's own series (>=X.Y.0 <X.(Y+1).0) unless
--plugin-version-range / -PluginVersionRange overrides it, and the plugin
refuses a bundle whose range excludes it.
Plugin 0.4.0 and older do not know this rule. With a 0.7 backend they report that the backend "supports plugin versions '>=0.7.0 <0.8.0'": upgrade the plugin.
Finding the latest backend version number
Use one of these from the repository root:
# latest git tag in this checkout (for example v0.2.2)
git describe --tags --abbrev=0
# latest GitHub release tag (requires gh auth)
gh release list --limit 1
Use the numeric part (for example 0.2.2) as the -Version argument for
packaging scripts.
Package plugin zip
From the repository root:
python3 qgis_plugin/package_plugin.py
This writes an installable zip to:
qgis_plugin/dist/lsdtt3-qgis-plugin-<version>.zip
where <version> is read from qgis_plugin/lsdtt_qgis/metadata.txt.
Installing a plugin zip you built
Install a zip from qgis_plugin/dist/ exactly as the downloaded one
(Installation, step 3). It must match the backend's X.Y
series like any other plugin.
Basin extraction: select all basins of one stream order
The QGIS Basin Extraction tool includes a selection mode:
All basins of stream order
When this mode is chosen, set the companion numeric parameter:
Selected stream order
This maps to CLI parameters select_all_basins_of_stream_order: true and
selected_stream_order: <n> and extracts every basin whose junction stream
order is exactly <n>.
Swath Profile
Bins every valid pixel within a half-width of a baseline line by its distance
along the line, and writes the pixel count, mean and 21 percentiles (p0, p5,
... p100) of each bin to <prefix>_swath_profile.csv. It profiles the DEM's
elevation unless you give another raster on the same grid.
- Baseline: the first selected feature of the line layer, or its first
feature if none is selected. The layer can be in any CRS: the plugin
reprojects the line to the DEM's CRS and saves it as
<prefix>_qgis_baseline.geojson, which the backend reads (the backend itself does not reproject vectors). A feature with more than one part is refused; split or merge it first. - Half-width 0 includes every valid pixel of the DEM.
- Distance rasters (optional): each pixel's distance along the baseline, its distance from it, and that distance signed by side.
Drainage algorithms
Drainage Area, Topographic Wetness Index, Sediment Connectivity Index, Height
Above Channel and Soil Topographic Index all run lsdtt-drainage-analysis,
one product each. They share the DEM, pit-filling and output options; the
advanced options include how flats are made drainable and the boundary
conditions. Each run writes only the outputs its own form asks for.
- Drainage Area writes any combination of D8, D-infinity and MFD drainage area, in square metres.
- Sediment Connectivity Index always writes the index and its D_up and D_down components. Channels, where downslope paths stop, are pixels whose drainage area reaches the threshold in square metres.
- Height Above Channel defines channels by contributing pixels instead.
- Soil Topographic Index takes soil-series and land-use polygon layers and
two tables: saturated conductivity profiles (needed for the STI raster and
the lookup CSV) and standard percentage runoff (needed for the proxy
raster, the lookup CSV, and spr mode). The tables follow the Scottish soil
data (Hutton series codes, SSKIB conductivities); see the
lsdtt-drainage-analysisreference for their columns. The plugin says which table is missing before anything runs.
Re-running an analysis
Every algorithm names its outputs <prefix>_<suffix> in the output folder, so
running it again with the same folder and prefix writes the same files. The
Overwrite existing outputs with the same prefix option (on by default)
makes that work:
- Before the run, the plugin closes any layer in the project that is loaded from one of those files. QGIS keeps a loaded layer's file open, and on Windows an open file cannot be replaced, so without this a re-run fails or keeps the old file. The log names each layer it closed; the new results are loaded in their place.
- With the option off, a run whose folder already holds
<prefix>_...files stops before anything runs, so earlier results are never replaced by accident. Use a new prefix to keep both. - An input that is itself one of this run's outputs (for example re-running
on
<prefix>_fill.tifwith the same prefix) is refused either way: choose another prefix. - After the run, every output is checked to have been written by this run. A file that another program still holds open, and so was not replaced, is reported rather than loaded as if it were new.
The run log (<prefix>_<tool>.log, replaced each run) and the numbered
parameter file next to the input DEM never count as outputs.
Updating to a new version
You usually do not need to manually uninstall first.
- Plugin update: download the new plugin zip from the latest release (or
build one) and install it again via
Install from ZIP. QGIS replaces the existing plugin files. - Backend update: unzip the new backend bundle to a new folder (recommended
to keep versioned folder names), then point the plugin to that folder in
lsdtt3 -> LSDTT Backend Settings.
Recommended update flow:
- Close QGIS.
- Install the new plugin zip (or reinstall over the old one).
- Unzip the new backend bundle.
- Open QGIS and update backend path in settings.
- Run a quick check (
lsdtt-raster-preprocessing --versionfrom that backend, or run a small tool in QGIS).
If QGIS still shows old behavior, restart QGIS once more; if needed, uninstall the plugin and reinstall from the new zip.
Backend command-line tools (required)
The plugin calls external lsdtt-* executables, so a backend must be
unpacked and selected before any algorithm runs
(Installation, steps 1, 2 and 4).
Checking a Windows backend outside QGIS
Developers build the Windows backend with
.\tools\package_windows_backend.ps1 -Version <version> (see
tools/README.md). To check an unpacked one works on its own, load its
runtime environment in PowerShell and ask a tool for its version:
cd C:\path\to\lsdtt3-backend-win64-qgis-v<version>
. .\setenv.ps1
.\bin\lsdtt-raster-preprocessing.exe --version
If --version works, the backend is ready. On Linux and macOS, run
bin/lsdtt-raster-preprocessing --version from the unpacked folder.
Troubleshooting PROJ / proj.db errors
If you see errors like:
proj_create_from_database ... proj.db contains DATABASE.LAYOUT.VERSION...input raster has no CRS definedimmediately after a PROJ error
then QGIS' own PROJ data is being used instead of the backend bundle's PROJ data. Usually this means the backend path is wrong.
Fix:
- In
lsdtt3 -> LSDTT Backend Settings, select the bundle root (containsbin/,share/,manifest.json), notbin/itself. - Save the settings again (the plugin then checks the bundle for every CLI it uses), and run a small preprocessing run.
The plugin now auto-corrects a .../bin selection to its parent bundle root
when possible, but selecting the root folder directly is still recommended.
Troubleshooting GDAL plugin DLL warnings on Windows
If processing succeeds but logs show messages like:
Can't load requested DLL ... gdal_GEOR.dll ... The specified procedure could not be found- similar lines for
ogr_FileGDB.dllorogr_OCI.dll
these usually come from QGIS GDAL plugin-driver paths leaking into the backend subprocess environment. They are typically noisy warnings (not fatal) when the output is still produced.
Recent plugin builds isolate backend GDAL by disabling external GDAL plugin autoload for subprocesses. If you still see this, update the plugin zip to the latest build and reinstall it.