Outputs

This guide explains the output files generated by SOLWEIG-GPU and how to interpret and visualize the results.

Output Structure

After running a simulation, outputs are saved in the output_folder/ directory within your base_path. To write outputs elsewhere, set base_path to the desired directory and pass complete paths for the input rasters (Building DSM, DEM, Trees, land cover); see Configuration. The structure is organized by tile key (origin coordinates in the raster grid):

base_path/
└── output_folder/
    ├── 0_0/
    │   ├── UTCI_0_0.tif
    │   ├── TMRT_0_0.tif
    │   └── SVF_0_0.tif
    ├── 0_1000/
    │   ├── UTCI_0_1000.tif
    │   ├── TMRT_0_1000.tif
    │   └── SVF_0_1000.tif
    └── 1000_0/
        ├── UTCI_1000_0.tif
        ├── TMRT_1000_0.tif
        └── SVF_1000_0.tif

Each subfolder is named by the tile key (e.g., 0_0, 0_1000, 1000_0). File names use TMRT (not Tmrt) to match the written rasters.

Output Files

Universal Thermal Climate Index (UTCI)

Filename: UTCI_X_Y.tif
Format: Multi-band GeoTIFF
Units: °C
Description: The Universal Thermal Climate Index, representing the “feels like” temperature.

UTCI is always computed and saved. It provides a comprehensive measure of thermal comfort that accounts for air temperature, mean radiant temperature, wind speed, and humidity.

Interpretation:

UTCI Range (°C)

Thermal Stress Category

> 46

Extreme heat stress

38 to 46

Very strong heat stress

32 to 38

Strong heat stress

26 to 32

Moderate heat stress

9 to 26

No thermal stress

0 to 9

Slight cold stress

-13 to 0

Moderate cold stress

-27 to -13

Strong cold stress

-40 to -27

Very strong cold stress

< -40

Extreme cold stress

Mean Radiant Temperature (Tmrt)

Filename: TMRT_X_Y.tif
Format: Multi-band GeoTIFF
Units: °C
Description: The mean radiant temperature in a standing position.

Tmrt represents the uniform temperature of an imaginary enclosure in which the radiant heat exchange with the human body equals the radiant heat exchange in the actual environment.

Saved when: save_tmrt=True

Sky View Factor (SVF)

Filename: SVF_X_Y.tif (single-band; X_Y is the tile key)
Format: Single-band GeoTIFF
Units: Dimensionless (0-1)
Description: The fraction of the sky hemisphere visible from each point.

SVF is a geometric parameter that quantifies the openness of a location to the sky. It affects both shortwave and longwave radiation exchange.

Saved when: save_svf=True

!!! Note: Unlike other outputs, SVF is a geometric property that doesn’t change with time. It is saved as a single-band raster, not multi-band.

Downwelling Shortwave (Kdown)

Filename: Kdown_X_Y.tif
Format: Multi-band GeoTIFF
Units: W/m²
Description: Incoming shortwave (solar) radiation at the surface.

Saved when: save_kdown=True

Upwelling Shortwave (Kup)

Filename: Kup_X_Y.tif
Format: Multi-band GeoTIFF
Units: W/m²
Description: Reflected shortwave radiation from surfaces.

Saved when: save_kup=True

Downwelling Longwave (Ldown)

Filename: Ldown_X_Y.tif
Format: Multi-band GeoTIFF
Units: W/m²
Description: Incoming longwave (thermal) radiation.

Saved when: save_ldown=True

Upwelling Longwave (Lup)

Filename: Lup_X_Y.tif
Format: Multi-band GeoTIFF
Units: W/m²
Description: Outgoing longwave radiation from the surface.

Saved when: save_lup=True

Shadow Maps

Filename: Shadow_X_Y.tif
Format: Multi-band GeoTIFF
Units: unitless (varies from 0 to 1) Description: Shadow/sunlit classification for each pixel.

Saved when: save_shadow=True

Multi-Band Structure

Most outputs (except SVF) are saved as multi-band GeoTIFFs, where each band represents one hour of the simulation.

Example: For a 24-hour simulation starting at 00:00:

  • Band 1: Hour 0 (00:00)

  • Band 2: Hour 1 (01:00)

  • Band 3: Hour 2 (02:00)

  • Band 24: Hour 23 (23:00)

Visualizing Outputs

Using QGIS

  1. Open QGIS and add the GeoTIFF file

  2. Multi-band rasters will appear with all bands listed

  3. Select a specific band to visualize a particular hour

  4. Apply color ramp for better visualization:

    • For UTCI/Tmrt: Use a thermal color ramp (blue-red)

    • For SVF: Use a grayscale or inverted grayscale

    • For radiation: Use a sequential color ramp

!!! tip “Temporal Animation” In QGIS, you can use the Temporal Controller to animate the multi-band raster and see how UTCI changes throughout the day.

Using Python

from osgeo import gdal
import matplotlib.pyplot as plt
import numpy as np

# Open the UTCI file
ds = gdal.Open('output_folder/0_0/UTCI_0_0.tif')

# Read a specific hour (e.g., hour 12 = noon)
band = ds.GetRasterBand(12)
utci = band.ReadAsArray()

# Plot
plt.figure(figsize=(10, 8))
plt.imshow(utci, cmap='RdYlBu_r', vmin=20, vmax=45)
plt.colorbar(label='UTCI (°C)')
plt.title('UTCI at Noon')
plt.axis('off')
plt.tight_layout()
plt.savefig('utci_noon.png', dpi=300)
plt.show()

Using ArcGIS

  1. Add the GeoTIFF to your map

  2. Access band properties through the raster properties dialog

  3. Create a mosaic if you have multiple tiles

  4. Apply symbology using the Symbology pane

  5. Export maps for publication or presentation

Merging Tiles

If your simulation generated multiple tiles, you may want to merge them into a single raster for easier visualization and analysis.

UTCI tile merging example

import os
import glob
import numpy as np
from tempfile import TemporaryDirectory
from osgeo import gdal

base_dir = r"path_to_base/output_folder"  # Locate the simulation output (base_path/output_folder)
pattern  = os.path.join(base_dir, "**", "UTCI*.tif") # Merging UTCI but this works for other variables as well
inputs   = glob.glob(pattern, recursive=True)
assert inputs, "No input tiles found!"

ds0 = gdal.Open(inputs[0])
n_bands = ds0.RasterCount
ds0 = None

out_dir = r"output_folder/UTCI" # Provide the folder where the merged files should be saved
os.makedirs(out_dir, exist_ok=True)

with TemporaryDirectory() as tmpdir:
    for b in range(1, n_bands + 1):
        print(f"Merging band {b}/{n_bands}")

        vrt_path = os.path.join(tmpdir, f"band{b:02d}.vrt")
        vrt_opts = gdal.BuildVRTOptions(
            bandList=[b],          # <- pick this band only
            srcNodata=-999,
            VRTNodata=np.nan       # nodata in the VRT
        )
        vrt_ds = gdal.BuildVRT(vrt_path, inputs, options=vrt_opts)
        if vrt_ds is None:
            raise RuntimeError(f"Failed to build VRT for band {b}")
        vrt_ds = None  # flush to disk

        out_tif = os.path.join(out_dir, f"merged_band{b:02d}_900.tif")
        tr_opts = gdal.TranslateOptions(
            format="GTiff",
            outputType=gdal.GDT_Float32,
            noData=np.nan,
            creationOptions=[
                "TILED=YES"  
            ]
        )
        gdal.Translate(out_tif, vrt_path, options=tr_opts)

Data Analysis

Computing Statistics

import numpy as np
from osgeo import gdal

# Open UTCI file
ds = gdal.Open('output_folder/0_0/UTCI_0_0.tif')

# Compute statistics for each hour
for hour in range(1, ds.RasterCount + 1):
    band = ds.GetRasterBand(hour)
    utci = band.ReadAsArray()
    
    print(f"Hour {hour-1}:")
    print(f"  Mean UTCI: {np.mean(utci):.1f}°C")
    print(f"  Max UTCI: {np.max(utci):.1f}°C")
    print(f"  Min UTCI: {np.min(utci):.1f}°C")
    print(f"  Std UTCI: {np.std(utci):.1f}°C")

Extracting Time Series

import numpy as np
from osgeo import gdal

# Open UTCI file
ds = gdal.Open('output_folder/0_0/UTCI_0_0.tif')

# Define a point of interest (pixel coordinates)
x, y = 500, 500

# Extract time series
utci_timeseries = []
for hour in range(1, ds.RasterCount + 1):
    band = ds.GetRasterBand(hour)
    utci = band.ReadAsArray()
    utci_timeseries.append(utci[y, x])

# Plot time series
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 4))
plt.plot(range(24), utci_timeseries, marker='o')
plt.xlabel('Hour of Day')
plt.ylabel('UTCI (°C)')
plt.title('UTCI Time Series at Point (500, 500)')
plt.grid(True)
plt.tight_layout()
plt.savefig('utci_timeseries.png', dpi=300)
plt.show()