Metadata-Version: 2.4
Name: landschaft
Version: 1.50.1
Summary: Fast, exact landscape pattern, fragmentation, landscape-metric and connectivity analysis for Python.
Keywords: landscape ecology,landscape metrics,fragmentation,connectivity,MSPA,circuit theory,conservation planning,species distribution,land use change,raster,GIS
Author: Eduardo Lacerda
License-Expression: GPL-3.0-or-later
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: C++
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: GIS
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Hydrology
Project-URL: Homepage, https://sacridini.github.io/landschaft/
Project-URL: Documentation, https://sacridini.github.io/landschaft/
Project-URL: Source, https://github.com/sacridini/landschaft
Project-URL: Changelog, https://github.com/sacridini/landschaft/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/sacridini/landschaft/issues
Requires-Python: >=3.10
Requires-Dist: numpy>=1.24
Requires-Dist: pandas>=1.5
Requires-Dist: rasterio>=1.3
Requires-Dist: rioxarray>=0.15
Requires-Dist: scipy>=1.10
Requires-Dist: xarray>=2023.1
Requires-Dist: dask[array]>=2023.1
Requires-Dist: geopandas>=0.12
Requires-Dist: pyarrow>=10
Requires-Dist: openpyxl>=3
Requires-Dist: matplotlib>=3.5
Requires-Dist: folium>=0.15
Requires-Dist: plotly>=5
Requires-Dist: xyzservices
Requires-Dist: Pillow
Requires-Dist: contextily>=1.3
Requires-Dist: pywebview>=5
Requires-Dist: anywidget>=0.9
Requires-Dist: h3>=4
Requires-Dist: dendropy>=4
Requires-Dist: cryptography>=3.4
Provides-Extra: test
Requires-Dist: pytest>=7; extra == "test"
Requires-Dist: threadpoolctl; extra == "test"
Provides-Extra: docs
Requires-Dist: mkdocs<2,>=1.6; extra == "docs"
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.26; extra == "docs"
Requires-Dist: ruff; extra == "docs"
Requires-Dist: matplotlib>=3.5; extra == "docs"
Description-Content-Type: text/markdown

<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/sacridini/landschaft/main/assets/logos/landschaft_ridge_stacked_dark.svg">
    <img alt="Landschaft" src="https://raw.githubusercontent.com/sacridini/landschaft/main/assets/logos/landschaft_ridge_stacked_light.svg" width="320">
  </picture>
</p>

<p align="center">
  <b>Fast, landscape analysis for Python.</b><br>
  Habitat patterns, fragmentation, landscape metrics and ecological connectivity,<br>
  from a single raster to maps larger than memory.
</p>

<p align="center">
  <a href="https://pypi.org/project/landschaft/"><img alt="PyPI" src="https://img.shields.io/pypi/v/landschaft"></a>
  <img alt="Python 3.10+" src="https://img.shields.io/badge/python-3.10%2B-3776ab">
  <img alt="C++17 / OpenMP" src="https://img.shields.io/badge/core-C%2B%2B17%20%C2%B7%20OpenMP-00599c">
  <img alt="License: GPL-3.0-or-later" src="https://img.shields.io/badge/license-GPL--3.0--or--later-2e7d32">
</p>

---

Landschaft brings the established methods of landscape ecology together in one
Python package, with a C++17/OpenMP core behind a numpy / xarray / dask / rasterio
API. It reproduces the reference tools of each method, checked against their outputs
in the test suite, and runs from a few to several hundred times faster.

| Area | What it covers | Reproduces |
|---|---|---|
| **Habitat patterns** | MSPA, SPA, object accounting, contortion | GuidosToolbox |
| **Fragmentation** | density at many scales (FAD, FOS), landscape mosaics, contagion, entropy | GuidosToolbox |
| **Landscape metrics** | 133 patch, class and landscape metrics, sample plots, moving windows, time series | landscapemetrics, FRAGSTATS |
| **Habitat networks** | PC, IIC, ECA, node and link importance, ProtConn | Conefor, Makurhini |
| **Circuit connectivity** | omnidirectional and pairwise current flow, rasters and networks | Circuitscape, Omniscape |
| **Distance & restoration** | cost surfaces, least-cost paths and corridors, isochrone maps | GuidosToolbox |
| **Change detection** | simple and morphological change, fragmentation transitions | GuidosToolbox |
| **Routes on grids** | transitions from any rule, travel-time surfaces, least-cost distances and paths, random walks, randomised shortest paths, route overlap | gdistance |
| **Surface metrics** | texture of continuous rasters (ISO 25178): roughness, height distribution, bearing area curve, slopes, peaks and valleys, autocorrelation, orientation, fractal dimension, trend surfaces, texture images; terrain indices (TPI, TRI, VRM, curvature, HLI...) | geodiv, spatialEco |
| **Terrain hydrology** | depression filling, D8, D-infinity and multiple flow directions, flow accumulation, streams, height above the nearest drainage (HAND), wetness, stream power and sediment transport indices | WhiteboxTools |
| **Neutral landscape models** | simulated landscapes as null models: random, percolation, gradients, fractal surfaces, Gaussian fields, mosaics, clusters, classification | NLMR |
| **Biodiversity analysis** | species records in grid cells: richness, endemism, phylogenetic diversity and endemism, randomisations, CANAPE, clustering | Biodiverse |
| **Spatial prioritization** | ranking of whole landscapes for many features (CAZ and ABF rules), weights, costs, hierarchic masks, connectivity transforms, performance curves, post-processing, impact assessment; maps larger than memory | Zonation 5 |
| **Species distributions** | cleaning and thinning occurrence records, accessible area, collinearity filters, background points, spatial cross-validation folds, evaluation (AUC, TSS, Boyce index), Maxent (MaxNet), ensembles of scikit-learn models, projection and extrapolation (MESS, MOP, ExDet) | CoordinateCleaner, spThin, usdm, dismo, blockCV, ENMeval, ecospat, predicts, maxnet, mop |
| **Land change simulation** | change analysis (intensity, components of difference, Markov chains), transition potential (weights of evidence, logistic regression, any scikit-learn model), allocation (CLUE-S, ordered, land systems, Expander/Patcher, random patch seeds, patch growing), dynamic variables, regional demands, validation at several resolutions, fuzzy similarity, calibration, scenarios with replicates | lulcc, OpenLand, diffeR, CLUMondo, FUTURES, MOLUSCE, Dinamica EGO, PLUS |
| **Ecosystem services** | carbon storage and sequestration with valuation, habitat degradation, quality and rarity | InVEST |
| **Large data** | out-of-core tiles and row blocks, parallel batches of rasters, tasks shared with the other computers of a lab (`landschaft worker`) | |

## Installation

```bash
pip install landschaft
```

Binary wheels are published for CPython 3.10 to 3.14 on Windows (x86-64), macOS (Apple
silicon and Intel, 11+) and Linux (x86-64, ARM64), with the OpenMP runtime included:
no compiler is needed, and everything every tool uses is installed with the package.
In a conda environment, install the geospatial libraries from conda-forge first and
Landschaft with pip:

```bash
conda create -n landschaft -c conda-forge python=3.12 rasterio rioxarray geopandas
conda activate landschaft
pip install landschaft
```

Building from source (other platforms, development) needs a C++17 compiler; see the
[installation guide](https://sacridini.github.io/landschaft/getting-started/installation.html).

### Docker

The image needs no compiler or Python on the host and includes every optional feature:

```bash
docker build -t landschaft .
docker run --rm -it -v "$PWD:/data" landschaft                 # Python shell
docker run --rm -v "$PWD:/data" landschaft python analysis.py  # run a script from the current folder
```

The current folder is mounted at `/data`, the working directory of the container.
`--build-arg PYTHON_VERSION=3.11` picks another Python, and
`docker build --target test -t landschaft:test . && docker run --rm landschaft:test`
runs the test suite in the container.

## Quick start

```python
import landschaft as ls

forest = ls.load_raster(ls.example_data("input"))    # bundled sample map
morph = ls.mspa(forest, edge_width=2)                # cores, edges, bridges, loops...
ls.write_raster(morph, "forest_mspa.tif")            # GeoTIFF with its colour table
print(ls.mspa_stats(morph))

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

Every function takes numpy arrays, georeferenced `xarray.DataArray`s or dask arrays,
and returns the same type; parallel functions use all cores but one unless given
`n_threads`.

## Documentation

The documentation website, **<https://sacridini.github.io/landschaft/>**, has a
getting-started guide, tutorials by topic, the full API reference with runnable
examples, and the benchmarks and accuracy report. It is built from `docs/` with
MkDocs and published with each release; to build it locally:

```bash
pip install -e ".[docs]"
mkdocs serve        # http://127.0.0.1:8000, or `mkdocs build` for a static site/
```

## Validation and performance

Each tool is compared in the test suite with the program it reproduces: pixel for
pixel where the output is a map, value for value (to the last bit where the original
arithmetic can be reproduced) for tables, and to the original's own precision for
floating-point solvers. Typical speed-ups on the benchmark cases:

| Tools | Compared with | Agreement | Speed-up |
|---|---|---|---|
| MSPA | GuidosToolbox `mspa` 2.3 | identical pixels | 10–17× |
| Landscape metrics | landscapemetrics 2.2.2 | identical bits | 35–500× |
| Habitat networks | Makurhini, Conefor | to 1e-12 | 13–620× |
| Omniscape, Circuitscape | Omniscape 0.7, Circuitscape 6.1 | to 2e-11 | 3–45× |
| Grid distances | gdistance 1.6 | identical bits (least cost); 1e-14 (random walks) | 3–400× |
| Neutral landscape models | NLMR 1.4 (same seed) | identical bits | 2–6000× |
| Spatial prioritization | Zonation 5 v2.4 | identical rank maps and output files | 4–11× |
| Species distributions | CoordinateCleaner, spThin, usdm, dismo, blockCV, ENMeval, predicts, maxnet | identical bits, random steps included (same seed) | maxnet 14×, kmeans 8×, weighted sampling 70× |
| Land change simulation | lulcc, OpenLand, diffeR, CLUMondo, r.futures, MOLUSCE; Dinamica EGO (measured) | identical bits (R's and NumPy's random numbers included); Dinamica to its 15 digits | 7–43× |

Methods, machines, full tables and the known differences are on the
[benchmarks and accuracy page](https://sacridini.github.io/landschaft/benchmarks.html). To run the tests:

```bash
pip install -e ".[test]"
pytest
```

## Versioning

Landschaft follows [Semantic Versioning](https://semver.org/): from 1.0 on, the public API
changes incompatibly only in a new major version. Changes are listed in the
[changelog](https://github.com/sacridini/landschaft/blob/main/CHANGELOG.md).

## License and credits

GPL-3.0-or-later. Landschaft ports code from GuidosToolbox and miallib,
© European Union (Joint Research Centre), authors Pierre Soille, Peter Vogt et al.,
both GPL-3.0-or-later; the example maps in `src/landschaft/data` come from the
[GTB repository](https://github.com/ec-jrc/GTB). GTB's `mspa` notes that its
interface is made available for non-commercial purposes: contact the JRC for
commercial use of MSPA.

Please cite the methods you use. For MSPA:

* Soille, P. & Vogt, P. (2009). Morphological segmentation of binary patterns.
  *Pattern Recognition Letters* 30(4), 456–459. doi:10.1016/j.patrec.2008.10.015
* Vogt, P. & Riitters, K. (2017). GuidosToolbox: universal digital image object
  analysis. *European Journal of Remote Sensing* 50(1), 352–361.
  doi:10.1080/22797254.2017.1330650
