Skip to content

CNR-ISMAR/spatial-connect

Repository files navigation

SpatialConnect

QGIS plugin and standalone Python library that propagates a spatial raster through a Lagrangian connectivity / transition matrix for n time steps:

$$x(t + n \cdot dt) = x(t) \cdot T^n \quad \text{(discrete)}$$

$$x(t + n \cdot dt) = x(t) \cdot e^{nT} \quad \text{(continuous)}$$

where x is a row vector of cell values and T is the transition matrix (T[i,j] = probability that a particle in cell i moves to cell j in one dt).


Repository structure

spatial-connect/
├── plugin/                     - QGIS plugin (self-contained, zippable)
│   ├── __init__.py             - QGIS classFactory
│   ├── metadata.txt            - QGIS plugin metadata
│   ├── spatial_connect.py      - plugin lifecycle (registers Processing provider)
│   ├── processing_provider.py  - Processing Toolbox algorithm
│   ├── dependencies.py         - auto-install missing packages at load time
│   └── core/                   - standalone propagation library
│       ├── __init__.py
│       ├── matrix_loader.py     - load .mtx / .npz transition matrices
│       ├── propagator.py        - SpatialPropagator (discrete + continuous)
│       └── raster_utils.py      - read/write GeoTIFF, compute_cell_ids
├── tests/
│   ├── conftest.py
│   ├── test_propagator.py
│   ├── test_matrix_loader.py
│   ├── test_raster_utils.py
│   └── test_integration.py
├── examples/
├── build_plugin_zip.py          - creates dist/SpatialConnect-<version>.zip  (cross-platform)
├── build_plugin_zip.sh          - same, bash shortcut for Linux/macOS
├── requirements.txt
├── pytest.ini
└── README.md

Installation

Standalone library

git clone https://github.com/CNR-ISMAR/spatial-connect.git
cd spatial-connect
pip install -r requirements.txt

QGIS plugin

Option A - Download from GitHub Releases (recommended for end users)

Go to the Releases page and download SpatialConnect-<version>.zip.

Then in QGIS: Plugins -> Manage and Install Plugins -> Install from ZIP -> select the file.

Option B - Build the ZIP locally (if you have the repo cloned)

python build_plugin_zip.py        # cross-platform (Linux / macOS / Windows)
# or on Linux/macOS:
./build_plugin_zip.sh

The file is created in dist/SpatialConnect-<version>.zip - install it as above.

Option C - Symlink (recommended for developers)

Symlink plugin/ into the QGIS plugins directory as SpatialConnect:

# Linux / macOS
ln -sfn $(pwd)/plugin \
  ~/.local/share/QGIS/QGIS3/profiles/default/python/plugins/SpatialConnect

# Windows (run as administrator)
mklink /D "%APPDATA%\QGIS\QGIS3\profiles\default\python\plugins\SpatialConnect" plugin

Then in QGIS: Plugins -> Manage and Install Plugins -> Installed -> SpatialConnect -> Enable.

Changes to the source files are reflected immediately (reload plugin to pick them up).


Quick start (Python API)

import sys
sys.path.insert(0, "path/to/spatial-connect/plugin")   # adds core/ to the path

from core import SpatialPropagator, MatrixLoader, RasterUtils

# 1. Load raster
array, meta = RasterUtils.read_raster("initial_distribution.tif")

# 2. Load transition matrix  (.mtx = MatrixMarket, .npz = scipy sparse)
T = MatrixLoader().load("sparse_transition_matrix.mtx")

# 3. Propagate  (10 discrete steps, x·T convention)
p = SpatialPropagator(mode="discrete")
result = p.run(array, T, iterations=10)

# 4. Save
RasterUtils.write_raster("output.tif", result.output, meta)

Matrix formats

Format Extension How to produce
MatrixMarket .mtx scipy.io.mmwrite() (e.g. from OpenDrift)
NumPy sparse .npz scipy.sparse.save_npz(path, matrix)

Propagation options

Parameter Default Description
mode "discrete" "discrete" = iterative multiplication; "continuous" = matrix exponential
normalise False Row-normalise T -> Markov chain (conserves total mass)
transpose_connectivity True True = x·T convention (Lagrangian); False = C·x legacy
clip_negative True Clip negative output values to 0
nodata_value None Cells with this value are masked during propagation
cell_ids None Masked-domain support - from RasterUtils.compute_cell_ids()

Processing Toolbox

The plugin registers the algorithm "Propagate Raster" under the SpatialConnect provider. Scriptable from PyQGIS:

import processing
result = processing.run("spatialconnect:propagate_raster", {
    "INPUT":          "/data/distribution.tif",
    "MATRIX":         "/data/sparse_transition_matrix.mtx",
    "ITERATIONS":     10,
    "MODE":           0,        # 0=discrete, 1=continuous
    "NORMALISE":      False,
    "CLIP_NEGATIVES": True,
    "OUTPUT":         "/tmp/output.tif",
})

Tests

pytest tests/ -v

Dependencies

Package Required for
numpy all
scipy matrix operations, sparse I/O
rasterio GeoTIFF read/write
fiona RasterUtils.vector_to_raster() only

Future works

  • Propagate Vector - a dedicated Processing algorithm that accepts a vector layer (point/polygon) as initial distribution, rasterises it onto a reference grid via RasterUtils.vector_to_raster() (requires fiona), runs the propagation, and returns a GeoTIFF output. Parameters would include the burn attribute, fill value, and all_touched option.
  • Multi-band raster input - propagate each band independently through the same matrix (e.g. one band per species, pollutant, or time snapshot) and return a multi-band output with identical spatial metadata.
  • Batch / multi-scenario mode (loop over a folder of rasters or matrix time-slices).
  • Time-series output (store all n intermediate steps as a multi-band raster).

License

GNU General Public License v3 - see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors