Skip to content

Landschaft

Fast, exact landscape analysis for Python. Map habitat structure, measure fragmentation, compute landscape metrics and model ecological connectivity, from a single raster on a laptop to continental maps larger than memory.

Python 3.10+ · C++17 / OpenMP core · numpy · xarray · dask · GPL-3.0-or-later

What you can do

  • Habitat patterns

    Split habitat into cores, edges, bridges, loops and islets; classify objects by size; describe the shape and texture of every patch.

  • Fragmentation

    Habitat density at many observation scales, fragmentation classes, landscape mosaics, contagion and spatial entropy, as maps and statistics.

  • Landscape metrics

    130+ patch, class and landscape metrics, sample plots, moving windows, time series, spatial signatures and rasters larger than memory.

  • Habitat networks

    Patches and distances as a graph: equivalent connected area, probability of connectivity, node and link importance, protected-area connectivity.

  • Circuit connectivity

    Current flow between habitat areas and omnidirectional connectivity across whole landscapes, on rasters and on networks.

  • Distance & restoration

    Distance maps, cost surfaces, least-cost paths and corridors, restoration priorities and travel-time (isochrone) maps.

  • Routes on grids

    Travel-time surfaces, least-cost and random-walk distances, randomised shortest paths and the overlap of dispersal routes.

  • Change detection

    Compare two dates: simple and morphological change, shifts between fragmentation classes and heat maps of landscape change.

  • Surface texture

    Roughness, height distribution and texture of continuous rasters (ISO 25178) such as NDVI or elevation, terrain indices of DEMs and protected hilltops.

  • Neutral landscapes

    Simulated landscapes as null models: random maps, gradients, fractal surfaces, Gaussian fields, clusters and mosaics.

  • Biodiversity analysis

    Species records in grid cells: richness, endemism, phylogenetic diversity and endemism, randomisations and regions.

  • Conservation priorities

    Rank whole landscapes for many species: performance curves, costs, reserves, connectivity and impact assessment.

  • Species distributions

    Clean occurrence records, choose predictors and background points, fit and evaluate models with spatial folds, and project them to new climates.

  • Land change simulation

    Project land use from two maps: demand, transition potential and allocation, validation against the observed change, calibration, scenarios with replicates, and roads and stocks that change with the model.

  • Watershed simulation

    The SWAT+ model from a DEM, land use and soils: daily water balance, streamflow, soil loss on the map and land use scenarios.

  • Large data & batch

    Folders of rasters in parallel, tiles for maps larger than memory, streaming tables with millions of rows.

A taste

import landschaft as ls

forest = ls.load_raster(ls.example_data("input"))  # 0 missing, 1 background, 2 forest
morph = ls.mspa(forest, edge_width=2)              # cores, edges, bridges, loops...
ls.mspa_stats(morph)                                # area of every class
import landschaft as ls

landcover = ls.load_raster(ls.example_data("clc"))
ls.landscape_metrics(landcover, level="landscape", metric=["shdi", "contag", "ed"])
import landschaft as ls

landcover = ls.load_raster(ls.example_data("clc"))
graph = ls.HabitatGraph.from_raster(
    landcover, habitat=[23, 24, 25],          # forest classes
    distance="edge", max_distance=2000,       # edge-to-edge distances, metres
    landscape_area=landcover.size * 25 * 25,  # 25 m cells
)
graph.overall(["PC", "IIC"], distance=1000, probability=0.5)
import landschaft as ls

landcover = ls.load_raster(ls.example_data("clc"))[:600, :600]
resistance = ls.reclassify(landcover, {23: 1.0, 24: 1.0, 25: 1.0},   # forest is easy to cross
                           others=25.0, dtype="float64")
flow = ls.omniscape(resistance, radius=30, block_size=5)
ls.plot(flow)                     # on an interactive map over satellite imagery

Why Landschaft

Fast

A C++17 core with OpenMP, cache-friendly algorithms and exact sparse solvers. Typical runs take seconds where the original tools take minutes or hours. See the benchmarks

Exact

The tools are checked against the reference implementations of their methods, to the last bit where the method allows it and to the solver's precision where it does not. How each tool is checked

Pythonic

numpy arrays, georeferenced xarray.DataArrays, dask, GeoTIFFs, GeoDataFrames and pandas tables in and out. No GUI, no temporary files, no other language to install.

Scales

Rasters larger than memory by tiles or row blocks, collections of maps in parallel within a memory budget, and all cores but one by default.

Validated against established tools

Landschaft reproduces the methods of GuidosToolbox (MSPA, fragmentation, accounting, restoration planning), the R package landscapemetrics and FRAGSTATS (landscape metrics), Conefor Sensinode and Makurhini (habitat networks), Circuitscape and Omniscape (circuit connectivity), gdistance (routes on grids), geodiv and spatialEco (surface metrics), NLMR (neutral landscape models), Zonation 5 (spatial prioritization), the R packages for species distributions (CoordinateCleaner, usdm, dismo, blockCV, ENMeval, predicts, ecospat, maxnet) and the land change models (lulcc, CLUMondo, FUTURES, MOLUSCE, Dinamica EGO) and SWAT+ (watershed simulation), and is tested against their outputs.

You do not need to know any of them to use it: the tutorials start from scratch, and the Learn course explains the landscape ecology behind every tool.