Timeseries Calculations¶
For multi-timestep simulations (hours, days, or longer), pass a list of weather objects to calculate(). Thermal state is carried between timesteps, and results are saved to disk as they are computed.
Thermal State Management¶
Ground and wall temperatures depend on accumulated heating from previous hours (thermal inertia). When given multiple weather timesteps, calculate() manages this via a ThermalState object, producing accurate ground-level longwave radiation values.
Basic Timeseries¶
import solweig
# Load surface
surface = solweig.SurfaceData.prepare(
dsm="data/dsm.tif",
working_dir="cache/",
)
# Load weather from EPW file
weather_list = solweig.Weather.from_epw(
"data/weather.epw",
start="2025-07-01",
end="2025-07-03",
)
location = solweig.Location.from_epw("data/weather.epw")
# Calculate all timesteps — results saved to output/
summary = solweig.calculate(
surface=surface,
location=location,
weather=weather_list,
output_dir="output/",
outputs=["tmrt", "shadow"],
)
print(f"Processed {len(summary)} timesteps")
This creates timestamped GeoTIFFs and summary grids:
output/
├── tmrt/
│ ├── tmrt_20250701_0000.tif
│ ├── tmrt_20250701_0100.tif
│ └── ...
├── shadow/
│ ├── shadow_20250701_0000.tif
│ └── ...
├── summary/
│ ├── tmrt_mean.tif
│ ├── tmrt_max.tif
│ ├── utci_mean.tif
│ └── ...
└── run_metadata.json # All parameters for reproducibility
If only summary statistics are required (mean/max/min Tmrt, UTCI, sun hours), omit
outputs — no per-timestep files are written, but the summary grids are still
saved to output/summary/.
summary = solweig.calculate(
surface=surface,
location=location,
weather=weather_list,
output_dir="output/", # Summary grids + metadata saved here
)
Inspecting Results¶
Summary report¶
report() returns a text summary of the run:
summary = solweig.calculate(
surface=surface,
weather=weather_list,
output_dir="output/",
outputs=["tmrt", "shadow"],
)
print(summary.report())
In Jupyter notebooks, placing summary as the last expression in a cell
renders the report via _repr_html_.
Per-timestep timeseries¶
summary.timeseries contains 1-D arrays of spatial means at each timestep,
providing an overview of how conditions evolved over the simulation:
ts = summary.timeseries
print(ts.datetime) # timestamps
print(ts.ta) # air temperature per step
print(ts.tmrt_mean) # spatial mean Tmrt per step
print(ts.utci_mean) # spatial mean UTCI per step
print(ts.sun_fraction) # fraction of sunlit pixels per step
Plotting¶
plot() produces a multi-panel figure showing temperature, radiation,
sun exposure, and meteorological inputs over time:
Requires matplotlib (pip install matplotlib).
Per-Timestep UTCI and PET¶
UTCI and PET summary grids (mean, max, min, day/night averages) are included
in the returned TimeseriesSummary. To save per-timestep UTCI or PET GeoTIFFs,
include them in outputs:
summary = solweig.calculate(
surface=surface,
weather=weather_list,
output_dir="output/",
outputs=["tmrt", "utci"], # per-timestep Tmrt + UTCI saved to disk
)
The indices are computed inline during the main loop (UTCI uses a Rust polynomial implementation; PET uses an iterative solver).
Memory Management for Long Simulations¶
Processing in chunks¶
For extended simulations (weeks or months), processing in daily chunks is recommended:
for chunk_start in range(0, len(weather_list), 24):
chunk = weather_list[chunk_start:chunk_start + 24]
results = solweig.calculate(
surface=surface,
location=location,
weather=chunk,
output_dir=f"output/",
)
Performance¶
| Grid size | Surface prep (SVF) | Per timestep | 72 timesteps |
|---|---|---|---|
| 100x100 | ~5 s | ~10 ms | ~1 s |
| 200x200 | ~67 s | ~20 ms | ~2 s |
| 500x500 | ~10 min | ~100 ms | ~8 s |
SVF is computed by SurfaceData.prepare(). For file workflows, a persistent working_dir avoids recomputing SVF on each run.
Run Metadata¶
calculate() saves a run_metadata.json file recording all parameters used. This can be loaded for reproducibility: