Skip to main content

High-performance SOLWEIG urban microclimate model (Rust + Python)

Project description

SOLWEIG

High-performance urban microclimate model for computing Mean Radiant Temperature (Tmrt) and thermal comfort indices (UTCI, PET).

Rust + Python performance-critical algorithms with GPU and tiled processing support.

This package is currently in testing as a proof of concept. Please open an issue if you have any feedback or suggestions.

Documentation

Original Code

This package is adapted from the GPLv3-licensed UMEP-processing by Fredrik Lindberg, Ting Sun, Sue Grimmond, Yihao Tang, and Nils Wallenberg.

Licensed under GNU General Public License v3.0. See LICENSE for details.

Citation:

Adapted from UMEP (Urban Multi-scale Environmental Predictor) by Fredrik Lindberg, Sue Grimmond, and contributors. If you use this plugin in research, please cite:

Lindberg F, Grimmond CSB, Gabey A, Huang B, Kent CW, Sun T, Theeuwes N, Järvi L, Ward H, Capel-Timms I, Chang YY, Jonsson P, Krave N, Liu D, Meyer D, Olofson F, Tan JG, Wästberg D, Xue L, Zhang Z (2018) Urban Multi-scale Environmental Predictor (UMEP) - An integrated tool for city-based climate services. Environmental Modelling and Software 99, 70-87 doi:10.1016/j.envsoft.2017.09.020

Installation

# Clone and install
git clone https://github.com/UMEP-dev/solweig.git
cd solweig
uv sync                  # Install Python dependencies
maturin develop          # Build Rust extension

Quick Start

import solweig
from datetime import datetime

# Create surface from DSM array
surface = solweig.SurfaceData(dsm=my_dsm_array, pixel_size=1.0)

# Define location and weather
location = solweig.Location(latitude=57.7, longitude=12.0)
weather = solweig.Weather(
    datetime=datetime(2024, 7, 15, 12, 0),
    ta=25.0,        # Air temperature (°C)
    rh=50.0,        # Relative humidity (%)
    global_rad=800.0  # Global radiation (W/m²)
)

# Calculate Tmrt
result = solweig.calculate(surface, location, weather)
print(f"Tmrt: {result.tmrt.mean():.1f}°C")

Loading from GeoTIFFs

import solweig

# Load and prepare surface data (auto-computes walls/SVF)
surface = solweig.SurfaceData.prepare(
    dsm="data/dsm.tif",
    working_dir="cache/",       # Walls/SVF cached here
    cdsm="data/cdsm.tif",       # Optional: vegetation
)

# Load weather from EPW file
weather_list = solweig.Weather.from_epw(
    "data/weather.epw",
    start="2023-07-01",
    end="2023-07-03",
)

# Calculate timeseries
results = solweig.calculate_timeseries(
    surface=surface,
    weather_series=weather_list,
    output_dir="output/",
)

Post-Processing (UTCI/PET)

Thermal comfort indices can be computed directly from results:

# Single timestep: compute directly from result
result = solweig.calculate(surface, location, weather)
utci = result.compute_utci(weather)  # Fast polynomial
pet = result.compute_pet(weather)    # Slower iterative solver

# Batch processing: from saved Tmrt files
solweig.compute_utci(tmrt_dir="output/", weather_series=weather_list, output_dir="utci/")
solweig.compute_pet(tmrt_dir="output/", weather_series=weather_list, output_dir="pet/")

Input Validation

Validate inputs before expensive calculations:

try:
    warnings = solweig.validate_inputs(surface, location, weather)
    for w in warnings:
        print(f"Warning: {w}")
    result = solweig.calculate(surface, location, weather)
except solweig.GridShapeMismatch as e:
    print(f"Grid mismatch: {e.field}")
except solweig.MissingPrecomputedData as e:
    print(f"Missing data: {e}")

Demos

Complete working examples are in the demos/ folder:

QGIS Plugin

SOLWEIG is available as a QGIS Processing plugin for interactive spatial analysis:

  1. Open QGIS → PluginsManage and Install Plugins
  2. Go to Settings tab → Check "Show also experimental plugins"
  3. Search for "SOLWEIG" in the All tab
  4. Click Install Plugin

See qgis_plugin/ for source code and development details.

Build & Test

maturin develop          # Build Rust extension
pytest tests/            # Run all 353 tests
poe verify_project       # Full verification (format, lint, test)

Development

Project Structure

pysrc/solweig/              # Python source (modular architecture)
  api.py                    # Public API re-exports
  models/                   # Dataclass package (~3,080 lines)
  components/               # Modular component functions
  computation.py            # Core orchestration logic
  timeseries.py             # Batch time series processing
  tiling.py                 # Large raster tiling support
rust/                       # Rust extensions via maturin
qgis_plugin/                # QGIS Processing plugin
tests/                      # 353 tests (100% pass rate)
  golden/                   # Reference data validation
  spec/                     # Physical property tests
docs/                       # MkDocs documentation site
specs/                      # Markdown specifications

Development Setup

# Install dependencies
uv sync

# Build Rust extension for development
maturin develop

# Run tests with coverage
pytest tests/ --cov=pysrc/solweig

# Format and lint
ruff format pysrc/ tests/
ruff check pysrc/ tests/ --fix

# Type checking
ty pysrc/

# Full verification pipeline
poe verify_project

Building Documentation

# Serve docs locally
mkdocs serve

# Build static site
mkdocs build

QGIS Plugin Bundle Preparation

The easiest way is to let GitHub Actions build the package — push a version tag (e.g. v0.1.0) or trigger the workflow manually. Download the universal ZIP from the release artifacts and upload it to the QGIS Plugin Repository.

The plugin source lives in qgis_plugin/solweig_qgis/ and is built using the qgis_plugin/build_plugin.py script, which compiles the Rust extension, bundles it with the Python library, and creates a distributable ZIP.

1. Update Plugin Metadata

Edit qgis_plugin/solweig_qgis/metadata.txt and increment the version.

2. Build the Plugin

# Build for current platform (builds Rust extension + bundles Python library)
python qgis_plugin/build_plugin.py

# Build and create a distributable ZIP for the current platform
python qgis_plugin/build_plugin.py --package

# Create a universal multi-platform ZIP from pre-built wheels in dist/
# (this is what GitHub Actions uses)
python qgis_plugin/build_plugin.py --universal

3. Test Plugin Locally

# Symlink for development (macOS)
ln -s "$(pwd)/qgis_plugin/solweig_qgis" ~/Library/Application\ Support/QGIS/QGIS3/profiles/default/python/plugins/solweig_qgis

Then:

  1. Open QGIS
  2. PluginsManage and Install PluginsInstalled
  3. Enable SOLWEIG
  4. Test in Processing ToolboxSOLWEIG

4. Upload to QGIS Plugin Repository

  1. Register at https://plugins.qgis.org/
  2. Log in → My PluginsUpload a plugin
  3. Select the ZIP from qgis_plugin/solweig-qgis-*-universal.zip
  4. Check "Experimental" for pre-release versions
  5. Add changelog/release notes
  6. Click Upload

Release Checklist

  • Version incremented in qgis_plugin/solweig_qgis/metadata.txt
  • All tests passing (pytest tests/)
  • Documentation updated
  • CHANGELOG.md updated
  • Plugin tested in QGIS locally
  • ZIP bundle created and validated
  • Uploaded to plugins.qgis.org

Tooling Preferences

Tool Use For Instead Of
uv Package management pip, poetry, pipenv
ruff Linting and formatting black, isort, flake8, pylint
ty Type checking mypy, pyright

Code Metrics

  • api.py: 403 lines (simplified from 3,976)
  • models/ package: ~3,080 lines (6 modules)
  • Component functions: All ≤ 455 lines
  • Test count: 353 tests (100% pass rate)
  • Legacy code removed: 6,100 lines

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

solweig-0.1.0b16.tar.gz (238.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

solweig-0.1.0b16-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.4 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

solweig-0.1.0b16-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.4 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

solweig-0.1.0b16-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.4 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

solweig-0.1.0b16-cp39-abi3-win_amd64.whl (3.3 MB view details)

Uploaded CPython 3.9+Windows x86-64

solweig-0.1.0b16-cp39-abi3-musllinux_1_2_x86_64.whl (3.7 MB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ x86-64

solweig-0.1.0b16-cp39-abi3-musllinux_1_2_aarch64.whl (3.6 MB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ ARM64

solweig-0.1.0b16-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

solweig-0.1.0b16-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

solweig-0.1.0b16-cp39-abi3-macosx_11_0_arm64.whl (2.7 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

solweig-0.1.0b16-cp39-abi3-macosx_10_12_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file solweig-0.1.0b16.tar.gz.

File metadata

  • Download URL: solweig-0.1.0b16.tar.gz
  • Upload date:
  • Size: 238.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for solweig-0.1.0b16.tar.gz
Algorithm Hash digest
SHA256 e9bb47a4c06187989f54428ed64ce9e7b845975c083b5ac69d9bee77c7e05d1c
MD5 48f00c511654f1fcc4385894789baf97
BLAKE2b-256 243b50a6b3815f4d413f37fc1f8707264d9c2118f3d066d7dee2106a93ce54f6

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b16.tar.gz:

Publisher: python-publish.yml on UMEP-dev/solweig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file solweig-0.1.0b16-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b16-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 8b2aeb097232c6a20a6fc0bdfd6f511a04273db8c220efb02d37b447b1e69160
MD5 18bcd8d0791e8630df6eed310c7beff6
BLAKE2b-256 30b27f29fc336c21d37d411a53477c5c80a2f5c2f5df819cafaa504736d74dab

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b16-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: python-publish.yml on UMEP-dev/solweig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file solweig-0.1.0b16-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b16-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 9b869d650dc91b43b556b9265633a076739fd468e31bff9274ad8d519963e42c
MD5 748e53087b6d7fe7cb35c296d65f6be7
BLAKE2b-256 edc9193ee07b0be6d7097a276af37fb7f86d9f347e6e0512f2d773c80348864b

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b16-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: python-publish.yml on UMEP-dev/solweig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file solweig-0.1.0b16-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b16-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e5c1345cab5aff6dfe10b7b05b7255ec9567f5b861fbfb856444e78d5ee14965
MD5 f894179849e1255f21c07975781d2970
BLAKE2b-256 311781c0a254eaad7a23b5ea40025d9fc8e892dc6866f511e859fc87e577558b

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b16-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: python-publish.yml on UMEP-dev/solweig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file solweig-0.1.0b16-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: solweig-0.1.0b16-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 3.3 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for solweig-0.1.0b16-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 fb6ca376b40c71ffdcc28a0a0a69d2759ba2e429e5438c0318e0792967b124d7
MD5 7fb188eb30b894d3ab61b2e5a1ebe8d1
BLAKE2b-256 0a2033c5d419096ae6f675179f7b2a6bf66eefac65513e25ea3c2cd21beceb62

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b16-cp39-abi3-win_amd64.whl:

Publisher: python-publish.yml on UMEP-dev/solweig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file solweig-0.1.0b16-cp39-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b16-cp39-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 0fe96a378fdc15233fa6bff498b7abb1aa21b5744498d4668f61f5821c4c2465
MD5 2ec1e08cf86504a71003b6a255be3100
BLAKE2b-256 a8d546206cb372fce960567b06c66aa6869ba38ff71746343c38a1e61c828e50

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b16-cp39-abi3-musllinux_1_2_x86_64.whl:

Publisher: python-publish.yml on UMEP-dev/solweig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file solweig-0.1.0b16-cp39-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b16-cp39-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 afa4135f8c8c6d04f154b251465e74f0a0f98948999f714f64c790cdd61a8fb9
MD5 64a7c02edaf72e60f1d79ebcc7b18f8f
BLAKE2b-256 4b638d03602a63f3c410ae72652d95972e616ff5909ecfabe83c5cdeaa52ce59

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b16-cp39-abi3-musllinux_1_2_aarch64.whl:

Publisher: python-publish.yml on UMEP-dev/solweig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file solweig-0.1.0b16-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b16-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 85fed4c59649ac08b772bdf41a2f9fe891e5e96d20176052d86fd2610f97b1e3
MD5 18a9532d7c92b59804fa92ad7faa6905
BLAKE2b-256 9187f46dd29149f4648dd6e0d771e6b97a3eadcbe1773483bbfb4963cdb1c630

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b16-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: python-publish.yml on UMEP-dev/solweig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file solweig-0.1.0b16-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b16-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 355691106d2e93f8129fcc38c28ac571ed625e5b85b79feae7496ed381c9e390
MD5 34a3ad4bca00fb0ee949e4bf098ce3bb
BLAKE2b-256 315bc462e322cc3e7a25e102105db56e0923098e9d441fa6fc816b099ecf3891

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b16-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: python-publish.yml on UMEP-dev/solweig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file solweig-0.1.0b16-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b16-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 44c7ba14051c7e848d6f7dc561af85b8772b9fac1d3e28d4fa39800e34d8b5f6
MD5 5430878151c4b6e302f2aa56f58b3ba2
BLAKE2b-256 b978b9b0f33280a4f449ff953ec6566d480802310a72d78239d080a20dee9326

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b16-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: python-publish.yml on UMEP-dev/solweig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file solweig-0.1.0b16-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b16-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 ca4cbd6cf9885fab3aac296057b6d05b2008e84553c61ea1eb18bc47c45757f2
MD5 5b028d04ee8d6329e3d86cf1045cb354
BLAKE2b-256 f2af588d167a0add228191b644a0e4ef4198ff286aa22b7ae374a4f8d3d45d50

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b16-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: python-publish.yml on UMEP-dev/solweig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page