Analyse and design fluvial ecosystems.
River Architect supports river engineers and ecologists in planning habitat-enhancing river restoration features: their expected lifespans, the dimensions they need to be stable, where they belong in the terrain, and what they are worth ecologically.
This is the open-source release. The geoprocessing runs on GDAL, rasterio, numpy and scipy; map production runs on QGIS print layouts. No Esri software or licence is required, and River Architect v2+ runs on Linux, macOS and Windows.
The methods are documented in:
- Schwindt, Larrieu, Pasternack, Rabone, 2020. River Architect. SoftwareX 11, 100438. doi: 10.1016/j.softx.2020.100438
- Larrieu, Pasternack, Schwindt, 2021. Automated analysis of lateral river connectivity and fish stranding risks-Part 1: Review, theory and algorithm. Ecohydrology 14, e2268. doi: 10.1002/eco.2268
- Phillips, Pasternack, Larrieu, 2025. Development and testing of a mechanistic potential niche model of riparian tree seedling recruitment. Ecological Modelling 501, 110986. doi: 10.1016/j.ecolmodel.2024.110986
git clone https://github.com/RiverArchitect/riverarchitect.git
cd riverarchitect
mamba env create -f environment.yml
mamba activate ra-env
pip install -e ".[all]"The geospatial stack installs far more reliably through conda-forge than through pip, because GDAL and its bindings come as prebuilt binaries. mamba comes with Miniforge. River Architect is not on PyPI yet, so install from a clone as above.
Map production additionally needs QGIS with its Python bindings, which cannot come from PyPI:
sudo apt install qgis python3-qgis # Debian / Ubuntu
python -c "from qgis.core import Qgis; print(Qgis.QGIS_VERSION)"Everything except the mapping module works without QGIS. Per-platform instructions are in the quick installation guide; the dependency background, project directory layout and troubleshooting are in the detailed installation guide.
Launch the graphical interface:
./runRiverArchitectLinux.sh # Linux and macOS
runRiverArchitectWin.bat # WindowsThe launchers find the environment themselves and, with no argument, open the sample data bundled in sample-data/. From an activated environment:
riverarchitect # or: python -m riverarchitect
riverarchitect /path/to/project # start with a project directoryThe interface renders with Qt (PySide6, or the PyQt5 that comes with QGIS) and falls back to tkinter when no Qt binding is installed, so it always opens. See the interface guide.
Or use the modules directly:
from riverarchitect import raster
dem, dem_profile = raster.read("sample-data/01_Conditions/2100_sample/dem.tif")
depth, depth_profile = raster.read("sample-data/01_Conditions/2100_sample/h001000.tif")
# Rasters of differing extent must be aligned explicitly - the silent
# alternative is a spatially meaningless result.
depth = raster.align(depth, depth_profile, dem_profile)
# Water surface elevation where the bed is wet; the false branch is NoData, not zero.
wse = raster.con(depth > 0, dem + depth)
raster.write("wse.tif", wse, dem_profile)Earthworks quantities between a pre- and post-project DEM:
from riverarchitect.volume_assessment import VolumeAssessment
result = VolumeAssessment("dem.tif", "dem_modified.tif", unit="us").run()
print(result["fill_volume"], result["excavation_volume"], result["volume_unit"])Fish stranding risk from disconnected wetted areas:
import numpy as np
from riverarchitect import raster
depth, profile = raster.read("sample-data/01_Conditions/2100_sample/h000300.tif")
mask, n_pools = raster.disconnected_mask(np.nan_to_num(depth) > 0)
dx, dy = raster.cell_size(profile)
print(f"{n_pools} pools, {mask.sum() * dx * dy:.0f} sqft stranded")A real gravel-cobble reach ships in sample-data/ - 60 discharges of depth and velocity, a DEM, grain sizes and a DEM of difference, so there is nothing else to download. The tutorial runs a lifespan and design map for angular boulders and a fish stranding assessment over a receding hydrograph on it. Both scripts are in examples/ and need no arguments:
mamba run -n ra-env python examples/lifespan_rocks.py
mamba run -n ra-env python examples/stranding_risk.pyMore building blocks in the quickstart guide.
| Module | Purpose |
|---|---|
riverarchitect.raster |
Raster I/O, alignment, map algebra, interpolation (IDW, kriging, nearest neighbour), connectivity, zonal statistics |
riverarchitect.condition |
Reading a condition folder and its input_definitions.inp |
riverarchitect.preprocessing |
Detrended DEM, water levels, morphological units, bed shear stress, condition setup |
riverarchitect.shear |
Regime-aware dimensionless bed shear stress (Shields stress) |
riverarchitect.lifespan |
Lifespan and design mapping for restoration features |
riverarchitect.maxlifespan |
Best-feature assessment across several lifespan maps |
riverarchitect.sharc |
Habitat suitability indices and Seasonal Habitat Area |
riverarchitect.stranding |
Fish stranding risk from disconnecting wetted areas |
riverarchitect.recruitment |
Riparian seedling recruitment potential |
riverarchitect.volume |
Triangulated-surface volume integration |
riverarchitect.volume_assessment |
Earthworks quantities from a pair of DEMs |
riverarchitect.mapping |
QGIS print layouts and multi-page PDF map series |
riverarchitect.config |
Paths, units, canonical NoData value |
riverarchitect.gui |
Desktop interface: Qt front end with a tkinter fallback |
riverarchitect.tools |
reconcile_nodata, lyrx2qml command-line tools |
The original River Architect was built on arcpy and required ArcGIS Pro with a Spatial Analyst licence. If you are porting scripts, read Migrating from arcpy first. Two differences silently produce wrong results if code is ported naively:
arcpy.env.extentdid implicit alignment. numpy does not. Useraster.align().- Two-argument
Con()yields NoData on the false branch, not zero.
Two migration tools ship with the package:
# normalise inconsistent NoData sentinels in a condition (the mask is preserved exactly)
python -m riverarchitect.tools.reconcile_nodata sample-data/01_Conditions/2100_sample --dry-run
# convert ArcGIS layer symbology (.lyrx, which is CIM JSON) to a QGIS style (.qml)
python -m riverarchitect.tools.lyrx2qml LifespanRasterSymbology.lyrxDetailed documentation is available at https://riverarchitect.readthedocs.io/
git clone https://github.com/RiverArchitect/riverarchitect.git
cd riverarchitect
mamba env create -f environment.yml
mamba activate ra-env
pip install -e ".[all,test,docs]"
pytest # test suite
python -m sphinx -b html docs docs/_build/html # documentationSample data lives in sample-data/; it is sourced by the former (now archived) SampleData repository.
Contributions are welcome. Please open an issue before starting on a major change.
Schwindt, S., Larrieu, K., Pasternack, G.B., Rabone, G. (2020). River Architect. SoftwareX 11, 100438. https://doi.org/10.1016/j.softx.2020.100438
Developed in the Pasternack Lab at the University of California, Davis, Department of Land, Air and Water Resources, with funding from the Yuba Water Agency (Awards #201016094 and #10446) and the USDA National Institute of Food and Agriculture (Hatch project CA-D-LAW-7034-H).
BSD 3-Clause. See LICENSE.