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
Open QGIS and add the GeoTIFF file
Multi-band rasters will appear with all bands listed
Select a specific band to visualize a particular hour
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
Add the GeoTIFF to your map
Access band properties through the raster properties dialog
Create a mosaic if you have multiple tiles
Apply symbology using the Symbology pane
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()