Skip to content

Core Functions

calculate

solweig.calculate(surface, weather, location=None, *, output_dir, config=None, human=None, precomputed=None, use_anisotropic_sky=None, conifer=False, physics=None, materials=None, wall_material=None, max_shadow_distance_m=None, tile_size=None, outputs=None, heat_thresholds_day=None, heat_thresholds_night=None, progress_callback=None)

Calculate mean radiant temperature (Tmrt).

Single entry point for all SOLWEIG calculations. SVF and shadow matrices must already be on surface (via :meth:SurfaceData.prepare) or in precomputed. The anisotropic sky model is on by default.

Parameters:

Name Type Description Default
surface SurfaceData

Prepared surface data from :meth:SurfaceData.prepare.

required
weather Weather | list[Weather]

One or more Weather objects. A single Weather is auto-wrapped.

required
location Location | None

Geographic location. If None, extracted from surface CRS.

None
config ModelConfig | None

Model settings. Explicit keyword args override config values.

None
human HumanParams | None

Human body parameters (posture, absorption, etc.).

None
precomputed PrecomputedData | None

Alternative source for SVF/shadow matrices (advanced).

None
use_anisotropic_sky bool | None

Anisotropic (True) or uniform (False) sky diffuse radiation. Default True.

None
conifer bool

Treat vegetation as evergreen (always leaf-on).

False
physics SimpleNamespace | None

Physics parameters from load_physics().

None
materials SimpleNamespace | None

Material properties from load_materials().

None
wall_material str | None

Wall material type ("brick", "concrete", "wood", "cobblestone").

None
max_shadow_distance_m float | None

Maximum shadow reach in metres (default 1000.0).

None
tile_size int | None

Core tile side in pixels for tiled processing. If None (default), auto-calculated from available resources. Minimum 256.

None
output_dir str | Path

Working directory for all output. Summary grids are always saved to output_dir/summary/. Per-timestep GeoTIFFs are saved when outputs is specified.

required
outputs list[str] | None

Which per-timestep outputs to save as GeoTIFFs (e.g., ["tmrt", "shadow"]). If None, only summary grids are saved.

None
heat_thresholds_day list[float] | None

Daytime UTCI thresholds for exceedance grids.

None
heat_thresholds_night list[float] | None

Nighttime UTCI thresholds for exceedance grids.

None
progress_callback Callable[[int, int], None] | None

Called as progress_callback(current, total) per tile-timestep.

None

Returns:

Type Description
TimeseriesSummary

TimeseriesSummary with per-pixel grids (mean/max/min Tmrt and UTCI,

TimeseriesSummary

sun/shade hours, heat-stress exceedance).

Notes

Modelled downwelling longwave (L↓) carries a known +18 to +55 W/m² positive bias inherited from the UMEP Jonsson et al. (2006) formulation. The bias is steady across hours and grows with reduced sky-view; see VALIDATION.md § Ldown overestimation. K↓ at any single pixel is shadow-edge-sensitive and may spike on a single mis-aligned hour; spatially-averaged K↓ has much lower error.

Example::

surface = solweig.SurfaceData.prepare(dsm="dsm.tif", working_dir="cache/")
weather = solweig.Weather.from_epw("weather.epw")

summary = solweig.calculate(
    surface=surface,
    weather=weather,
    output_dir="output/",
)

validate_inputs

solweig.api.validate_inputs(surface, location=None, weather=None, use_anisotropic_sky=False, precomputed=None)

Validate inputs before calculation (preflight check).

Call this before expensive operations to catch errors early. Raises exceptions for fatal errors, returns warnings for potential issues.

Parameters:

Name Type Description Default
surface SurfaceData

Surface data to validate.

required
location Location | None

Location to validate (optional).

None
weather Weather | list[Weather] | None

Weather data to validate (optional, can be single or list).

None
use_anisotropic_sky bool

Whether anisotropic sky will be used.

False
precomputed PrecomputedData | None

Precomputed data to validate.

None

Returns:

Type Description
list[str]

List of warning messages (empty if all valid).

Raises:

Type Description
GridShapeMismatch

If surface grid shapes don't match DSM.

MissingPrecomputedData

If required precomputed data is missing.

WeatherDataError

If weather data is invalid.

Example

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


SurfaceData.prepare

The most common entry point for building a SurfaceData from rasters or in-memory arrays — see the class page for the full method list. Documented here because every quick-start uses it before calculate().

solweig.SurfaceData.prepare(dsm, working_dir=None, cdsm=None, dem=None, tdsm=None, land_cover=None, wall_height=None, wall_aspect=None, svf_dir=None, bbox=None, pixel_size=None, trunk_ratio=0.25, dsm_relative=False, cdsm_relative=True, tdsm_relative=True, min_object_height=1.0, smooth_quantized_dem=True, dem_smooth_sigma=3.0, force_recompute=False, tile_size=None, feedback=None) classmethod

Prepare surface data for SOLWEIG calculations.

Loads inputs, computes walls, SVF, and shadow matrices, and returns a ready-to-use :class:SurfaceData. This is the only setup step needed before calling :func:calculate.

Accepts either file paths (GeoTIFF) or numpy arrays:

  • File mode (dsm is a path): loads and aligns rasters, caches results in working_dir for fast reuse.
  • Array mode (dsm is an ndarray): works in memory. pixel_size is required; working_dir is not needed.

Parameters:

Name Type Description Default
dsm str | Path | NDArray[floating]

DSM as a GeoTIFF path or numpy array (required).

required
working_dir str | Path | None

Cache directory (required for file mode).

None
cdsm str | Path | NDArray[floating] | None

Canopy height model (tree tops). Optional.

None
dem str | Path | NDArray[floating] | None

Ground elevation model. Optional.

None
tdsm str | Path | NDArray[floating] | None

Trunk height model. Optional; auto-generated from CDSM if not provided (using trunk_ratio).

None
land_cover str | Path | NDArray[integer] | None

Land cover classification grid. Optional.

None
wall_height str | Path | NDArray[floating] | None

Pre-computed wall heights. Optional; computed from DSM if not provided.

None
wall_aspect str | Path | NDArray[floating] | None

Pre-computed wall aspects. Optional; computed from DSM if not provided.

None
svf_dir str | Path | None

Directory with existing SVF files (file mode only).

None
bbox list[float] | None

Bounding box [minx, miny, maxx, maxy] (file mode only).

None
pixel_size float | None

Pixel size in meters. Required for array mode; extracted from GeoTIFF in file mode.

None
trunk_ratio float

Trunk-to-canopy height ratio for auto TDSM. Default 0.25.

0.25
dsm_relative bool

DSM values are height above ground (not elevation). Default False.

False
cdsm_relative bool

CDSM values are height above ground. Default True.

True
tdsm_relative bool

TDSM values are height above ground. Default True.

True
min_object_height float

Minimum nDSM height (m) for shadow casting. DSM pixels below this height above DEM are flattened to remove kerbs, street furniture, and LiDAR noise. Default 1.0. Set to 0 to disable. Requires DEM.

1.0
smooth_quantized_dem bool

Apply Gaussian smoothing to the DEM when it is detected to be integer-quantized (e.g. int16 with 1 m precision). Default True. Integer-stored DEMs produce visible stair-step contour artifacts in SVF over gently sloped open terrain because each 1 m terrain step casts a discrete shadow at low-altitude sky patches; smoothing recovers the sub-metre variation that was lost at storage time. Disable to preserve bit-exact legacy behaviour or when your terrain has genuine 1 m steps (e.g. agricultural terraces).

True
dem_smooth_sigma float

Gaussian standard deviation in pixel units at target resolution. Default 3.0 — FWHM ≈ 7 px gives bulletproof elimination of the stair-step artifact across all sky patches including the lowest (3°). Softens real terrain features smaller than ~15 m horizontal scale; below that scale, a 1 m-quantized DEM has no physically meaningful information anyway (the sharp transitions are storage truncation, not real features). Override to 1.5–2.0 for high-resolution non-quantized DEMs or when 10 m-scale terrain features must be preserved. Only used when smooth_quantized_dem=True and a quantized DEM is detected.

3.0
force_recompute bool

Recompute walls/SVF even if cached (file mode only).

False
tile_size int | None

Core tile side length in pixels for SVF tiling. If None (default), auto-calculated from available resources. Minimum 256.

None
feedback Any

QGIS QgsProcessingFeedback for progress/cancellation.

None

Returns:

Type Description
SurfaceData

SurfaceData ready for :func:calculate.

Example::

# From GeoTIFF files
surface = SurfaceData.prepare(dsm="dsm.tif", working_dir="cache/")

# From numpy arrays
surface = SurfaceData.prepare(dsm=dsm_array, pixel_size=1.0)

GPU helpers

Runtime toggles and observability for the wgpu compute path. The GPU is enabled by default when available; these helpers let scripts inspect, override, or measure GPU usage. From b87 onwards, enable_gpu / disable_gpu toggle all three Rust GPU paths (shadows, anisotropic sky, GVF) in a single call.

is_gpu_available

solweig.is_gpu_available()

Check if GPU acceleration is available at runtime.

Returns True if: - GPU support was compiled into the Rust extension - A GPU device was successfully detected and initialized

Use this to check GPU status before running compute-intensive operations.

Returns:

Type Description
bool

True if GPU acceleration is available, False otherwise.

get_compute_backend

solweig.get_compute_backend()

Get the current compute backend.

Returns:

Type Description
str

"gpu" if GPU acceleration is available and enabled, "cpu" otherwise.

enable_gpu

solweig.enable_gpu()

Enable GPU acceleration on every Rust path (shadows, anisotropic sky, GVF).

The counterpart to :func:disable_gpu. Each Rust pipeline starts enabled by default at import time, so the common use of this function is re-enabling after an explicit :func:disable_gpu call (for instance, between benchmark scenarios).

Has no effect if GPU support wasn't compiled in or no GPU device is available — both :func:is_gpu_available and the per-path fallbacks continue to govern actual execution.

disable_gpu

solweig.disable_gpu()

Disable GPU acceleration on every Rust path (shadows, anisotropic sky, GVF), falling back to CPU.

Useful for debugging, CPU-only benchmarks, or when GPU results need to be compared against the CPU reference. The change takes effect immediately for subsequent calculations.

Note: Prior to b87 this function only flipped the shadow path; the anisotropic sky and GVF paths kept running on GPU. It now toggles all three so a single call genuinely produces a CPU-only run.

get_gpu_limits

solweig.get_gpu_limits()

Query GPU limits from the wgpu adapter.

Returns a dict with keys
  • max_buffer_size: int — raw adapter-reported maximum buffer size in bytes
  • backend: str — GPU backend name ("Metal", "Vulkan", "Dx12", "Gl", etc.)
  • gpu_memory_budget: int — resolved GPU memory budget in bytes (only present when real VRAM is detectable via DXGI/sysfs/Metal)

Returns None if GPU is not available or not compiled in. Lazily initialises the GPU context on first call.

gpu_dispatch_count

solweig.gpu_dispatch_count()

Cumulative count of successful GPU dispatches since process start (or since the last :func:reset_gpu_metrics call).

Reads a thread-safe atomic counter incremented on the success branch of every GPU kernel call across the three GPU paths (shadows, SVF, anisotropic sky, GVF). Pair with :func:gpu_fallback_count to distinguish "GPU is disabled" (both zero after a run) from "GPU tried and fell back" (dispatch=0, fallback>0).

Use in tests to assert "the GPU path actually ran":

import solweig solweig.reset_gpu_metrics()

... run a calculation ...

assert solweig.gpu_dispatch_count() > 0, "GPU path never executed"

gpu_fallback_count

solweig.gpu_fallback_count()

Cumulative count of GPU→CPU fall-backs since process start (or since the last :func:reset_gpu_metrics call).

A non-zero value during a "should be GPU" run indicates either a GPU device problem (driver crash, OOM, unsupported shape) or a per-dispatch failure mode worth investigating. Zero after a CPU-only run just means no fall-back happened because the GPU branch was never entered.

See also: :func:gpu_dispatch_count, :func:reset_gpu_metrics.

reset_gpu_metrics

solweig.reset_gpu_metrics()

Reset :func:gpu_dispatch_count and :func:gpu_fallback_count to 0.

Typical use in tests:

solweig.reset_gpu_metrics()

... run a calculation ...

dispatched = solweig.gpu_dispatch_count() fellback = solweig.gpu_fallback_count()