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.0b33.tar.gz (270.5 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.0b33-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.5 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

solweig-0.1.0b33-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.5 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

solweig-0.1.0b33-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.5 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

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

Uploaded CPython 3.9+Windows x86-64

solweig-0.1.0b33-cp39-abi3-musllinux_1_2_x86_64.whl (3.8 MB view details)

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

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

Uploaded CPython 3.9+musllinux: musl 1.2+ ARM64

solweig-0.1.0b33-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.5 MB view details)

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

solweig-0.1.0b33-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.5 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

solweig-0.1.0b33-cp39-abi3-macosx_11_0_arm64.whl (2.8 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

solweig-0.1.0b33-cp39-abi3-macosx_10_12_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

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

File metadata

  • Download URL: solweig-0.1.0b33.tar.gz
  • Upload date:
  • Size: 270.5 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.0b33.tar.gz
Algorithm Hash digest
SHA256 118539f561703ce5e0c5ae7ab7992e527b29830415d0d2a541ec589a535ee407
MD5 3eefc964f7480dad7301fefde4053eae
BLAKE2b-256 130b0d921370cd348e4001276e99b9bce5086d149ffc950b485725d9b4bc3462

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b33.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.0b33-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b33-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 dcd52ba6c5410f544907b7c8e756bfc83daed85e8ad4eb0e06ed3732a72b1684
MD5 fdc555f8881ef0ce7d3fb34ed27d12eb
BLAKE2b-256 0d3a26c764398ac7d0fa6e7140ddbdc54b33e7b28b70b6017296485dc0775fc5

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b33-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.0b33-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b33-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a187f05ecb11f5ef1bcad1ee8c4c1af854ee2f4c665b8d3ec7e2542d1e8cb435
MD5 b0acf0f3aa7ffef47d89e9856c4fdd70
BLAKE2b-256 33316e6bf57e32cb51b188da4b363fa58621f82cdf08d63f3760a439311fdde0

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b33-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.0b33-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b33-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ffb680a2a2fa546293cfd024edfd0c2f617ca17ad0d0b9d2ecbf5041ee22064d
MD5 169dbc6bd8b1f854368425e25a0a5416
BLAKE2b-256 1c3a105670c5b60b8ab43e7f533a16bc5a3c3b0a1bc0f33b428453fdec392b96

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b33-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.0b33-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: solweig-0.1.0b33-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.0b33-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 9c1987c40d7fa47a12ce226163fbd7827a6af07382a2dbfd00e154aaa79616ce
MD5 501cb2dc691f16441d6578f9005c1133
BLAKE2b-256 bd3fa5fadbf1f38aa96305ef768b11c7712a974489178644d51d258655f672b9

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b33-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.0b33-cp39-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b33-cp39-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 196d1fd04a523cab87afd21c355a6aa4812d272e18f01cdae9bd78f28bf3edef
MD5 ae2e67717e3b8597521f04715a636a48
BLAKE2b-256 cf227ad07d03eb1f71f2a173080a90b0bfa4c911550a7f3e47975922899c5b97

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b33-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.0b33-cp39-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b33-cp39-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 ff9f103862cacf6bf044987411d6ffc7a01e589c6a1db47fa920e05925c9c7ce
MD5 e241e51ac6005dcca329cfa9662ab080
BLAKE2b-256 a9065490c957f43432386d96f368a85a1877d8ae44e2765e6bd01b1402def97c

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b33-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.0b33-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b33-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 76da10b653831be92782262e712ee1de7e2e2b9d9189a051fd7c32a80475a5fa
MD5 163e81e6b22feb2e581062b269e56354
BLAKE2b-256 10bc9d2722e72d315d6a15cbd28cb72273cea23bc3e2da47df8b3c8a5d2947ad

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b33-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.0b33-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b33-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a6356334e69573bbf171a50d56dcc35e07f30cc84d77870d35461a217d023ae9
MD5 f248fd04a6fd401101291d75389f5e43
BLAKE2b-256 626fd21543fc8128ee70aface2771e04227f25e7327d98ed1ddcdf0585ad9566

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b33-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.0b33-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b33-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 207f5e872a048761b5ebbe52769dc14beed1b59a7843aa623eb60e20ac5dec56
MD5 c1ee5a82f64c5663e645765e2c352a4b
BLAKE2b-256 d40699d03b8da6f819d7d706fc5fee46e415e497d8e13c4fd830b993adc84162

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b33-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.0b33-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for solweig-0.1.0b33-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 f1fe77997cc2683a910b376dca036dbd9cc61b48cfdc56478249921700a3290c
MD5 98a2892731f12057798f5e6c52e2cf0a
BLAKE2b-256 251a759de0052ea45bfdb89c8abff4160e27522bdb614d904bb7b4474aa86dee

See more details on using hashes here.

Provenance

The following attestation bundles were made for solweig-0.1.0b33-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