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.0b30.tar.gz (256.0 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.0b30-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.0b30-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.4 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

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

Uploaded PyPymanylinux: glibc 2.17+ ARM64

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

Uploaded CPython 3.9+Windows x86-64

solweig-0.1.0b30-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.0b30-cp39-abi3-musllinux_1_2_aarch64.whl (3.6 MB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ ARM64

solweig-0.1.0b30-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.0b30-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.0b30-cp39-abi3-macosx_11_0_arm64.whl (2.8 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

solweig-0.1.0b30-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.0b30.tar.gz.

File metadata

  • Download URL: solweig-0.1.0b30.tar.gz
  • Upload date:
  • Size: 256.0 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.0b30.tar.gz
Algorithm Hash digest
SHA256 4bbb94569053f25970bec2884aa4d2c86cc2ff7ca77fa08f6b49f504329c1293
MD5 04c2f2bdaed3fd89574f6a8208a4c005
BLAKE2b-256 bd1414f8addad9b5cc3eb08fb037b46f507a6a72b12046b3c9c521f090784fee

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for solweig-0.1.0b30-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e5e3caa0a44ba63a7c2b8f2c9d5bc95fe269d3ddc3302df2affb2803b0babb0c
MD5 169427e5d909f3a17afd16d638b6fa4d
BLAKE2b-256 7e8261ec7c25964b7706c85ac8072edafe843508b8d509edd449893dc20df94f

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for solweig-0.1.0b30-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 195cc690bfdbd04424e660fc2f7cb69e96ccac6b1ed314d5177e2495a2a4a018
MD5 dc33ef036585009ba3bcb5358bef0d5a
BLAKE2b-256 c2fa7187ca78046587133f9740c292792210f917864ea7fd75ea900a984c065d

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for solweig-0.1.0b30-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4d34b5ba54e11f5965ce63a0a101cba29171cd7fb817c8e3064d1f7fb31937c9
MD5 d37834cf6d6a06494bfb36c1f27732a1
BLAKE2b-256 9c048a7c57de89e0a1f66eac2d9d514138438024992cb6b3ef31026237195985

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: solweig-0.1.0b30-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.0b30-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 1550c39a16239328757678b9e44bb15d93afaefb18da4749fbf6bdefe08eea07
MD5 692e2dc76668905268ddfc51c6e81538
BLAKE2b-256 f78253d02285baee40b3220c7f13d6584aa71cc8203071693971f2c107431317

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for solweig-0.1.0b30-cp39-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 1020246ef81f6335e0294b272a16ea387193796cd7bb7ecca0da17a8f47bd629
MD5 6af5d17014d84172d3e6376dadcf1c99
BLAKE2b-256 a0789d4f29430cdf84499c6526a44e1b09022313b646312b86b7eed7f47a5ecb

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for solweig-0.1.0b30-cp39-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 24ef3d9d3340a42761e0b72ae340d7bede0054e8beedab016905392c7d2b99ff
MD5 51128bc5920bb4503638b0e7e37a4e18
BLAKE2b-256 9e460e95bf232017348a010c10accc3fbbff384ccc1e8cc28b40fa603879e996

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for solweig-0.1.0b30-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e000d875ca9ff2886439e14a213e4d1b30a37835707faa547998c2f50a4726a6
MD5 d3693e935148c5b6bc5ebd909a764e62
BLAKE2b-256 259b4dc5a8eca491c6a1e98e02846e8377f7a4f4f4716f3b7ec78d81ded5f0b3

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for solweig-0.1.0b30-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e391cf637d3b39302394cb187175ecc9ad0d0558c5398c31c7c63d0e0215dc20
MD5 5d51a35fe93acca22d1e233a3dcbf929
BLAKE2b-256 b5b56a8040fe6c72e86964e873c705a6509d6614a7ac4bb76eb29346449af022

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for solweig-0.1.0b30-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bf78544e654ef4c5727e9d63343e6ce64a4a6f28ffd490732234e34fddfa36fe
MD5 d1a25e188e208f7ddd7ebb1891514e81
BLAKE2b-256 a7db023d41976f44a30e895ce6d4d9bb4ccc5bbdcd0e9cab4e26a6f5214b3ad9

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for solweig-0.1.0b30-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 a01dba9d58b98b2447cdffa1415a6941f849242d93df9bba595cdc505cf1d6c3
MD5 eba6cf926a970cec8da26127301b417c
BLAKE2b-256 c1f580b53ee84f834444425bd3129bb4ffaa8ea48707058a4720c19b57dd70c2

See more details on using hashes here.

Provenance

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