AT6012 · learning module · infrared.city SDK 0.4.9

Regenerative Thermal Analysis with infrared.city

Read a city street as the grids that actually govern comfort, UTCI, wind and solar, then test one design question with real data.

The question this module answers: does adding canopy cool a street? Not always. Placement, density and street geometry decide the outcome. You will measure a case where more trees made a canyon hotter, and a case where they helped.
~3 hours across nine units 🐍 Python + infrared-sdk 🗺 QGIS export 🎓 5 ECTS micro-credential, next cohort 23 Sep 2026
How the module is built

A synergetic nine-square

Position carries meaning. The top row holds the principles, the centre cell is the live probe you run, and the foot of the grid is praxis: real cities, the honest counter-case, and where to go next. Read it top to bottom and you walk from idea to practice.

North · principle (abstract) West · setup & definitions Centre · the live probe East · tools & metrics South · praxis (concrete)

▲ general / principle  ·  the vertical axis is an abstraction gradient  ·  special / praxis ▼

NWPrinciple

The finding

Whether added canopy cools a street or traps its heat depends on the street's form, its density and its geometry.

In plain terms: where and how you plant matters more than how much.
NPrinciple

UTCI, the comfort scale

The Universal Thermal Climate Index folds air temperature, radiation, wind and humidity into one felt temperature.

In plain terms: one number for what a body actually feels outdoors.
NEPrinciple

Assembly complexity

A regenerative microclimate is a diverse mosaic of thermal zones. Alberti's lens reads that mosaic, made grid-native.

In plain terms: variety of conditions is itself a quality.
WSetup

Connect to the SDK

Install infrared-sdk 0.4.9, hold your key in .env, and preview a site for free before you spend anything.

In plain terms: get connected, look before you run.
The probe

Run the analysis

Submit a polygon, get back an AreaResult grid for UTCI, wind or solar. Baseline first, then the same site with trees.

In plain terms: this is the hands-on core. You run a real street.
ETools

Compute the metrics

Heat-stress %, severe-heat %, the Thermal Assembly Complexity Index and thermal-zone diversity, straight off the grid.

In plain terms: turn the grid into numbers you can compare.
SWCounter-case

When trees backfire

A dense canyon plus canopy can trap radiant heat and cut ventilation. The honest failure mode, measured.

In plain terms: the lesson that proves the finding is real.
SPraxis

Four cities, real results

Marseille, Cork, Rome and London run through the same probe. The deltas disagree, and that is the point.

In plain terms: see how the same method lands differently per city.
SEExemplar

Carry it further

The scorecard, the QGIS export, and the simSPACE serious game where the finding becomes playable.

In plain terms: where to take the skill once you have it.
North · principle

The finding

The thesis the whole module tests.

Frames: Alberti (2016); Oke (1988), street-canyon energetics.

Urban greening is sold as cooling. Often it is. But canopy changes a microclimate for better or for worse, and which one depends on the street's form. A broad crown over an open plaza shades a hot surface and cools it. The same crown packed into a narrow, deep canyon can trap the longwave heat the buildings radiate and choke the wind that would carry it away.

So the regenerative question is not "how many trees" but "what does this canopy do to this street's heat and air". That is a measurement question, and this module is how you measure it.

What you will be able to do: take any site polygon, model its thermal comfort with and without vegetation, and state plainly whether the intervention helped, with the numbers to back it.
North · principle

UTCI, the comfort scale

The single number this module reads off every grid.

Source: Bröde et al. (2012); Błażejczyk et al. (2013), the UTCI assessment scale.

The Universal Thermal Climate Index answers "what does a body feel here", folding air temperature, mean radiant temperature, wind speed and humidity into one equivalent temperature in °C. It is the index the infrared.city thermal-comfort model returns.

The assessment scale sorts that number into stress bands. The module uses these exact thresholds (Błażejczyk et al. 2013):

below 9°
cold stress
9–26°
comfortable
26–32°
moderate heat
32–38°
strong heat
38–46°
very strong
46°+
extreme

Two figures drive the whole assessment:

  • Heat-stress % = the share of the grid above 26°C (moderate heat and worse).
  • Severe-heat % = the share above 38°C (strong heat and worse).
Why count cells: a comfortable average can hide a corner in extreme stress. A street is judged by its worst cells, so the module counts them.
North · principle

Assembly complexity

Why a varied microclimate is itself a quality.

Frames: Alberti (2016), Cities That Think Like Planets; Shannon (1948), diversity.

A single mean flattens a street into one verdict. Alberti's planetary-urbanism lens asks a richer question: how many distinct thermal conditions does a place offer, and how evenly are they mixed. A street with shade pockets, sunny edges and ventilated gaps gives a body somewhere to move to. The module operationalises this as the Thermal Assembly Complexity Index (TACI), grid-native.

It is built from the UTCI band map of the grid:

  • Zone diversity, a Shannon index over the occupied stress bands.
  • Spatial complexity, how interleaved those zones are across the grid.
Reading it: a rise in thermal-zone diversity after planting can be a real gain even when the mean barely moves. Cork shows exactly that below.
West · setup

Connect to the SDK

Install, authenticate, and preview for free.

Package: infrared-sdk 0.4.9 (supersedes the old hand-rolled REST client).

One install, one key. The client reads INFRARED_API_KEY from your environment and auto-loads a local .env on import. Treat the key as a password; never commit it (the toolkit's .gitignore already excludes .env).

setup.py free · no billing
# pip install infrared-sdk numpy matplotlib
import infrared_sdk as ir

# reads INFRARED_API_KEY from your .env automatically
client = ir.InfraredClient()

# a square around your site, lon/lat, closed ring
polygon = [[-8.486,51.897],[-8.482,51.897],
           [-8.482,51.899],[-8.486,51.899],[-8.486,51.897]]

# PREVIEW: tiles the area, no job is submitted, nothing is billed.
# always pass analysis_type (wind grid = 256 m, solar/thermal = 512 m)
preview = client.preview_area(polygon, analysis_type="solar")
print(preview.tile_count, "tiles ready, 0 cost")
Design at zero cost. preview_area never submits a job. Use it to frame your polygon and pick a resolution before you run anything billable.
Centre · the live probe ●

Run the analysis

The hands-on core. Baseline, then the same site with trees.

Returns: an AreaResult with .merged_grid (numpy, NaN outside the polygon), .bounds and a legend.

A real run submits a model request over your polygon and waits for the grid. This is the billable step, so the module teaches it with the cost guard switched on from the start.

run_baseline.py billable · submits a job
from infrared_sdk.models import TimePeriod
import regenerative_metrics as rm

# a solar run needs no weather file; UTCI does (see the toolkit's fetch helper)
request = ir.SolarModelRequest(time_period=TimePeriod.SUMMER)

# BILLABLE. run_area_and_wait submits a real job. cap tiles while learning.
baseline = client.run_area_and_wait(
    request, polygon,
    on_progress=lambda p: print(f"  {p:.0%}"),
)
grid = baseline.merged_grid          # numpy array, NaN outside the site
print(rm.utci_stats(grid).line())

Now run the same polygon again with vegetation injected, so the only thing that changed is the trees:

run_with_trees.py billable · submits a job
# real street trees, fetched and shaped by the SDK's vegetation service
veg = client.vegetation.get_area(polygon)
print(veg.total_trees, "trees on this site")

intervention = client.run_area_and_wait(request, polygon, vegetation=veg)
print(rm.utci_stats(intervention.merged_grid).line())
Cost guard. run_area_and_wait bills. The toolkit's scorecard.py only previews unless you pass --run, and --max-tiles N caps the spend. Never launch an area run without meaning to.
East · tools

Compute the metrics

Grid in, comparable numbers out.

Module: regenerative_metrics.py (UTCI bands, heat-stress %, TACI).

The metrics module reads a numpy grid and returns the figures the scorecard compares. Nothing here is billed; it is pure post-processing of grids you already have.

score.py free · local compute
import regenerative_metrics as rm

base = rm.utci_stats(baseline.merged_grid)
trees = rm.utci_stats(intervention.merged_grid)

print(f"heat-stress  {base.heat_stress_pct:.1f}% -> {trees.heat_stress_pct:.1f}%")
print(f"mean UTCI    {base.mean:.1f} -> {trees.mean:.1f} °C")

# the assembly view: did the street gain thermal-zone diversity?
taci = rm.assembly_index(intervention.merged_grid)
print(f"zone diversity (Shannon)  {taci.spatial_diversity:.2f}")
Measurement honesty. canopy masks the grid cells beneath it, so a baseline-vs-intervention percentage is not strictly apples to apples. The scorecard reports this openly. Teaching the caveat is part of the method.
South · counter-case

When trees backfire

The failure mode that proves the finding.

Frames: Oke (1988), canyon radiation trapping & reduced sky-view factor.

Run the probe on a deep, narrow Mediterranean street and add a broad canopy, and the heat-stress fraction goes up. The crowns lower the sky-view factor, so the longwave heat the walls radiate at night is trapped under the leaves, and the same crowns slow the cross-street wind that would have flushed it.

This is not a bug in the model. It is the model telling you the truth about that street. Marseille below is the worked example: heat-stress rises from 79.1% to 83.0% after planting, because the intervention was canopy in a canyon.

The design lesson: in a tight canyon, ventilation and a higher sky-view factor cool more than shade. Reach for narrow crowns, gaps, and airflow before broad canopy. Test it, do not assume it.
South · praxis

Four cities, real results

The same probe, four very different answers.

Data: the live toolkit run; values from kpis.json.

These are the measured deltas from running the probe over each city's site. They are not tidy. That is the honest result, and the teaching point: the method is constant, the verdict is local.

CityHeat-stress (base → +trees)Mean UTCIWhat it shows
Marseille79.1% → 83.0%27.3 → 27.5 °CCanyon + canopy traps heat (1.1% tree-cover site)
Cork0% → 0%15.6 → 15.2 °CMild maritime; +7.6% thermal-zone diversity
Rome96.9% → 97.6%30.0 → 30.1 °C757 city trees / 33 species: a data-provenance proof, with a near-flat delta

Cork is the regenerative case: no heat stress to begin with, and planting widened the mix of thermal zones (the assembly gain). Marseille and Rome are the cautionary cases, where dense form and sparse ground make canopy a weaker lever than airflow. Same code, three different streets, three different truths.

No fabricated data. every number here comes from a real run. Where a figure is not yet measured, the toolkit says so and leaves a marked placeholder.
South · exemplar

Carry it further

Where the skill goes after the module.

All live on the AT6012 site and the GitHub Pages mirror.

The module is the front door. Each of these takes the same finding somewhere concrete:

What you can now do

Connect to the SDK, preview a site for free, run a real UTCI / wind / solar grid, inject real vegetation, compute heat-stress, severe-heat and thermal-assembly metrics, and judge honestly whether a planting helped, including the cases where it did not.

References

Alberti, M. (2016). Cities That Think Like Planets. · Bröde, P. et al. (2012). Deriving the operational procedure for the UTCI. Int. J. Biometeorol. · Błażejczyk, K. et al. (2013). An introduction to the UTCI. Geographia Polonica. · Oke, T. R. (1988). Street design and urban canopy layer climate. Energy and Buildings. · Shannon, C. (1948). A mathematical theory of communication.