From 17f22c069199dfdeca9f921cab990eb3557363fa Mon Sep 17 00:00:00 2001 From: Samuel Letellier-Duchesne Date: Mon, 7 Sep 2026 20:41:04 -0400 Subject: [PATCH] Document the climate zone keys, in both idioms The page told a reader to filter by zone "using a plain list comprehension" over `ashrae_climate_zone.startswith("4A")`. On the bundled index that is the bug the libraries just fixed: `startswith("7A")` returns 1,262 records whose zone upstream could not determine, and `startswith("8A")` returns 900. Both idioms, per Principle IV. The TypeScript snippet is not authored here: it is vendored from idfkit-js at the pinned docs level, so this includes it and idfkit-js#54 publishes it. THIS CANNOT MERGE UNTIL THE PIN MOVES, and that is the design working. pyright over docs/snippets reports four errors, all "No parameter named climate_zone", because the site pins idfkit==1.0.0-rc.3 and the keys ship in the next release. Per bump-idfkit.yml's own rule the fix is never to relax the check; here it is also not the page, because the page is right about the version it will describe. The fix is the pin, and it arrives with the release. --- .../station-search/filter_by_climate_zone.py | 23 ++++++++---- docs/weather/station-search.md | 36 ++++++++++++++++--- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/docs/snippets/weather/station-search/filter_by_climate_zone.py b/docs/snippets/weather/station-search/filter_by_climate_zone.py index 62075af..7f5ad96 100644 --- a/docs/snippets/weather/station-search/filter_by_climate_zone.py +++ b/docs/snippets/weather/station-search/filter_by_climate_zone.py @@ -4,14 +4,25 @@ index: StationIndex = ... # type: ignore[assignment] # --8<-- [start:example] -# Each WeatherStation carries its ASHRAE HOF climate zone. -zone_4a = [s for s in index.stations if s.ashrae_climate_zone.startswith("4A")] +# Ask for a zone by its code. The code is parsed out of the label rather than +# read off the front of it, which matters: 2,162 of the 69,638 bundled records +# are labelled "7A - ASHRAE Climate Zone could not be determined" or "8A - ...", +# and neither 7A nor 8A is an ASHRAE zone, since zones 7 and 8 carry no suffix. +zone_4a = index.filter(climate_zone="4A") print(f"Zone 4A stations: {len(zone_4a)}") -# Combine with country/state via the existing filter() to narrow further: -us_zone_5 = [s for s in index.filter(country="USA") if s.ashrae_climate_zone.startswith("5")] +# Combine with the other keys, which all narrow together. +seattle_area = index.filter(climate_zone="4C", country="USA", state="WA") +print(f"Zone 4C in Washington: {len(seattle_area)}") -# Pick the warmest design dry-bulb in a given zone: -hottest = max(us_zone_5, key=lambda s: s.cooling_design_db_c) +# The stations whose zone upstream could not determine are reachable, and only +# this way: no climate_zone value returns them. Asking for them is a separate +# question because the zone key's domain is already every real code, so a +# reserved string could not be told apart from one. +undetermined = index.filter(climate_zone_determined=False) +print(f"Zone not determined upstream: {len(undetermined)}") + +# Pick the warmest design dry-bulb in a zone. +hottest = max(index.filter(climate_zone="5A", country="USA"), key=lambda s: s.cooling_design_db_c) print(f"{hottest.display_name}: {hottest.cooling_design_db_c} °C / {hottest.cooling_design_db_f:.1f} °F") # --8<-- [end:example] diff --git a/docs/weather/station-search.md b/docs/weather/station-search.md index 0f6d8fc..9ec8ce8 100644 --- a/docs/weather/station-search.md +++ b/docs/weather/station-search.md @@ -112,7 +112,8 @@ Combine `geocode()` with `nearest()` for address-based search: !!! tip "Climate-zone-aware search" Each `WeatherStation` carries its ASHRAE HOF climate zone, design - dry-bulb temperatures, HDD18, and CDD10. See + dry-bulb temperatures, HDD18, and CDD10. Filter on the zone with the + index's own key rather than on the label text: see [Filter by Climate Zone](#filter-by-climate-zone) below. ## Filter by Country @@ -151,11 +152,36 @@ design conditions from a neighbouring WMO station; otherwise it is ## Filter by Climate Zone -Filter stations by ASHRAE climate zone using a plain list comprehension: +Ask the index for a zone by its code. -```python ---8<-- "docs/snippets/weather/station-search/filter_by_climate_zone.py:example" -``` +=== "Python" + + ```python + --8<-- "docs/snippets/weather/station-search/filter_by_climate_zone.py:example" + ``` + +=== "TypeScript" + + ```ts + --8<-- "docs/snippets/js/weather/station-search/filter_by_climate_zone.ts:example" + ``` + +!!! warning "The label is not a code, and matching its first token invents two zones" + + 2,162 of the 69,638 bundled records are labelled + `7A - ASHRAE Climate Zone could not be determined` or `8A - ...`. Neither 7A + nor 8A is an ASHRAE zone: zones 7 and 8 carry no moisture suffix. Reading the + code off the front of the label therefore produces twenty-one zones where + there are nineteen, and files 3.1% of the index under two that do not exist. + + The zone key matches a parsed code with those records excluded, so it returns + nothing for `7A`. They stay reachable through the separate key for records + whose zone was not determined, and every station is returned by exactly one of + the two. + + A related trap, for anyone writing the parse by hand: the suffix is `[ABC]`, + not `[AB]`. Dropping C loses 3C, 4C and 5C, which is 1,653 marine-zone + stations, leaves sixteen zones where there are nineteen, and raises nothing. ## Listing Countries