Weather API Overview¶
The weather module provides station search, file downloads, and design day management.
Quick Reference¶
| Class/Function | Description |
|---|---|
StationIndex |
Weather station search and filtering |
WeatherStation |
Station metadata container |
WeatherDownloader |
EPW/DDY file downloads |
WeatherFiles |
Downloaded file paths |
DesignDayManager |
Design day parsing and injection |
DesignDayType |
Design day type enumeration |
apply_ashrae_sizing() |
Quick design day application |
geocode() |
Address to coordinates |
Module Contents¶
Weather station search, download, and design day injection.
This sub-package provides tools for:
- Searching the climate.onebuilding.org TMYx station index by name, coordinates, or metadata filters.
- Downloading EPW and DDY weather files with local caching.
- Parsing DDY files and injecting ASHRAE design day conditions into EnergyPlus models.
- Geocoding addresses to coordinates via the free Nominatim API.
Station Index¶
The bundled index contains ~55,000 dataset entries representing
~17,300 unique physical weather stations worldwide. The difference
is because each station may have multiple TMYx year-range variants
(e.g., TMYx.2007-2021, TMYx.2009-2023), each stored as a
separate entry with its own download URL.
Quick Start¶
Search by name:
```python
from idfkit.weather import StationIndex, WeatherDownloader
index = StationIndex.load() # Instant, no network needed
results = index.search("chicago ohare")
station = results[0].station
downloader = WeatherDownloader()
files = downloader.download(station)
print(files.epw, files.ddy)
```
Search by Address (Splat Pattern)¶
Combine geocode with nearest using the splat operator to find weather stations near any address:
```python
from idfkit.weather import StationIndex, geocode
index = StationIndex.load()
# Find stations near an address (one line!)
results = index.nearest(*geocode("350 Fifth Avenue, New York, NY"))
for r in results[:3]:
print(f"{r.station.display_name}: {r.distance_km:.0f} km")
# Output:
# New York La Guardia AP, NY, USA: 10 km
# New York J F Kennedy Intl AP, NY, USA: 18 km
# Newark Liberty Intl AP, NJ, USA: 22 km
```
The geocode function uses the free Nominatim (OpenStreetMap) service, which requires no API key. Requests are rate-limited to 1 per second.
Apply Design Days¶
Inject ASHRAE sizing design days into your model:
```python
from idfkit import load_idf
from idfkit.weather import StationIndex, apply_ashrae_sizing
model = load_idf("building.idf")
station = StationIndex.load().search("chicago ohare")[0].station
# Apply ASHRAE 90.1 design conditions
added = apply_ashrae_sizing(model, station, standard="90.1")
print(f"Added {len(added)} design days")
```
Index Freshness¶
StationIndex.load() is purely local and requires no extra dependencies.
Use StationIndex.refresh() (requires openpyxl) to re-download the
upstream Excel indexes and rebuild the local cache:
```python
if index.check_for_updates():
index = StationIndex.refresh() # requires openpyxl
```
NoDesignDaysError
¶
Bases: IdfKitError
Raised when a DDY file contains no SizingPeriod:DesignDay objects.
This typically occurs for weather stations that lack ASHRAE design conditions data in the climate.onebuilding.org database.
Attributes:
| Name | Type | Description |
|---|---|---|
station_name |
Display name of the station (if available). |
|
ddy_path |
Path to the DDY file that was parsed. |
|
nearby_suggestions |
List of nearby stations that may have design days. |
DesignDayManager
¶
Parse DDY files and inject design day conditions into IDF models.
A DDY file is a valid IDF-syntax file containing Site:Location and
SizingPeriod:DesignDay objects. This class uses [idfkit.load_idf][idfkit.load_idf]
to parse the file and classifies each design day by its ASHRAE condition
type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ddy_path
|
Path | str
|
Path to a |
required |
version
|
tuple[int, int, int] | None
|
EnergyPlus version to use for schema resolution. Defaults to the latest supported version (design day fields are stable across versions). |
None
|
all_design_days
property
¶
All SizingPeriod:DesignDay objects from the DDY file.
annual
property
¶
All classified annual design day objects.
monthly
property
¶
All monthly design day objects.
Monthly design days follow the naming pattern
{Location} {Month} {pct}% Condns {type} and are not classified
into the DesignDayType enum.
heating
property
¶
All heating design days.
cooling
property
¶
All cooling dry-bulb, wet-bulb, enthalpy, and dehumidification design days.
location
property
¶
The Site:Location object from the DDY file, if present.
from_station(station, *, dataset=None, version=None)
classmethod
¶
Download the DDY file for a station and parse it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station
|
WeatherStation
|
The weather station. |
required |
dataset
|
str | None
|
TMYx variant to download. Defaults to the most recent. |
None
|
version
|
tuple[int, int, int] | None
|
EnergyPlus version for schema resolution. |
None
|
get(dd_type)
¶
Get a specific design day by type.
raise_if_empty()
¶
Raise :exc:NoDesignDaysError if this DDY has no design days.
When constructed via from_station, the error message includes suggestions for nearby stations that may have design day data.
Raises:
| Type | Description |
|---|---|
NoDesignDaysError
|
If |
apply_to_model(model, *, heating='99.6%', cooling='1%', include_wet_bulb=False, include_enthalpy=False, include_dehumidification=False, include_wind=False, update_location=True, replace_existing=True)
¶
Inject design day objects into an IDF model.
Selects the appropriate design days based on common ASHRAE sizing
practices and adds them as SizingPeriod:DesignDay objects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
IDFDocument
|
The target IDFDocument. |
required |
heating
|
Literal['99.6%', '99%', 'both']
|
Which heating percentile to include. |
'99.6%'
|
cooling
|
Literal['0.4%', '1%', '2%', 'all']
|
Which cooling dry-bulb percentile to include. |
'1%'
|
include_wet_bulb
|
bool
|
Also include cooling wet-bulb design days. |
False
|
include_enthalpy
|
bool
|
Also include cooling enthalpy design days. |
False
|
include_dehumidification
|
bool
|
Also include dehumidification design days. |
False
|
include_wind
|
bool
|
Also include heating wind-speed design days. |
False
|
update_location
|
bool
|
Update the |
True
|
replace_existing
|
bool
|
Remove existing |
True
|
Returns:
| Type | Description |
|---|---|
list[str]
|
List of design day names that were added. |
summary()
¶
Human-readable summary of all design days in the DDY file.
DesignDayType
¶
Bases: Enum
Classification of ASHRAE annual design day conditions.
Values encode the condition type and annual percentile.
WeatherDownloader
¶
Download and cache weather files from climate.onebuilding.org.
Downloaded ZIP archives are extracted and cached locally so that subsequent requests for the same station and dataset are served from disk without a network call.
Examples:
from idfkit.weather import StationIndex, WeatherDownloader
station = StationIndex.load().search("chicago ohare")[0].station
downloader = WeatherDownloader()
files = downloader.download(station)
print(files.epw)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache_dir
|
Path | None
|
Override the default cache directory. |
None
|
max_age
|
timedelta | float | None
|
Maximum age of cached files before re-downloading.
Can be a timedelta or a number of seconds.
If |
None
|
Note
The cache has no size limit. For CI/CD environments with limited disk
space, consider using clear_cache periodically or setting
a max_age to force re-downloads of stale files.
download(station)
¶
Download and extract weather files for station.
If the files are already cached and not stale, no network request is made.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station
|
WeatherStation
|
The weather station to download files for. |
required |
Returns:
| Type | Description |
|---|---|
WeatherFiles
|
A WeatherFiles with paths to the extracted files. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the download or extraction fails. |
get_epw(station)
¶
Download and return the path to the EPW file.
get_ddy(station)
¶
Download and return the path to the DDY file.
clear_cache()
¶
Remove all cached weather files.
This removes the entire files/ subdirectory within the cache,
which contains all downloaded ZIP archives and extracted files.
WeatherFiles
dataclass
¶
Paths to downloaded and extracted weather files.
Attributes:
| Name | Type | Description |
|---|---|---|
epw |
Path
|
Path to the |
ddy |
Path
|
Path to the |
stat |
Path | None
|
Path to the |
zip_path |
Path
|
Path to the original downloaded ZIP archive. |
station |
WeatherStation
|
The station this download corresponds to. |
StationIndex
¶
Searchable index of weather stations from climate.onebuilding.org.
Use load to load the bundled (or user-refreshed) station index.
No network access or openpyxl is required for load.
Use check_for_updates to see if upstream data has changed, and refresh to re-download and rebuild the index.
Examples:
index = StationIndex.load()
results = index.search("chicago ohare", limit=3)
for r in results:
print(r.station.display_name, r.score)
stations
property
¶
All stations in the index.
countries
property
¶
Sorted list of unique country codes in the index.
load(*, cache_dir=None)
classmethod
¶
Load the station index from a local compressed file.
Checks for a user-refreshed cache first, then falls back to the bundled index shipped with the package. No network access is required.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache_dir
|
Path | None
|
Override the default cache directory. |
None
|
from_stations(stations)
classmethod
¶
Create an index from an explicit list of stations (useful for tests).
refresh(*, cache_dir=None)
classmethod
¶
Re-download Excel indexes from climate.onebuilding.org and rebuild the cache.
Requires openpyxl. Install with pip install idfkit[weather].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache_dir
|
Path | None
|
Override the default cache directory. |
None
|
check_for_updates()
¶
Check if upstream Excel files have changed since this index was built.
Sends lightweight HEAD requests to climate.onebuilding.org.
Returns True if any file has a newer Last-Modified date.
Returns False if all files match or if the check fails (offline,
timeout, etc.).
get_by_wmo(wmo)
¶
Look up stations by WMO number.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wmo
|
str
|
WMO station number as a string (e.g. |
required |
Returns a list because a single WMO number can correspond to multiple stations or dataset variants.
search(query, *, limit=10, country=None)
¶
Fuzzy-search stations by name, city, state, or WMO number.
Matching is case-insensitive and uses substring / token-prefix heuristics (no external NLP dependencies).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
str
|
Free-text search query. |
required |
limit
|
int
|
Maximum number of results to return. |
10
|
country
|
str | None
|
If given, restrict to stations in this country code. |
None
|
nearest(latitude, longitude, *, limit=5, max_distance_km=None, country=None)
¶
Find stations nearest to a geographic coordinate.
Uses the Haversine formula for great-circle distance. A bounding-box pre-filter is applied when max_distance_km is specified to avoid computing distances for stations that are obviously too far.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
latitude
|
float
|
Decimal degrees, north positive. |
required |
longitude
|
float
|
Decimal degrees, east positive. |
required |
limit
|
int
|
Maximum results to return. |
5
|
max_distance_km
|
float | None
|
Exclude stations farther than this. |
None
|
country
|
str | None
|
If given, restrict to this country code. |
None
|
filter(*, country=None, state=None, wmo_region=None)
¶
Filter stations by metadata criteria.
All specified criteria must match (logical AND).
SearchResult
dataclass
¶
SpatialResult
dataclass
¶
A spatial proximity result with great-circle distance.
distance_km
instance-attribute
¶
Great-circle distance in kilometres.
WeatherStation
dataclass
¶
Metadata for a single weather file entry from climate.onebuilding.org.
Each instance represents one downloadable weather dataset. The same physical
station may appear multiple times with different source or year-range
variants (e.g. TMYx.2007-2021 vs TMYx.2009-2023).
Attributes:
| Name | Type | Description |
|---|---|---|
country |
str
|
ISO 3166 country code (e.g. |
state |
str
|
State or province abbreviation (e.g. |
city |
str
|
City or station name as it appears in the index
(e.g. |
wmo |
str
|
WMO station number as a string to preserve leading zeros
(e.g. |
source |
str
|
Dataset source identifier (e.g. |
latitude |
float
|
Decimal degrees, north positive. |
longitude |
float
|
Decimal degrees, east positive. |
timezone |
float
|
Hours offset from GMT (e.g. |
elevation |
float
|
Meters above sea level. |
url |
str
|
Full download URL for the ZIP archive. |
display_name
property
¶
Human-readable station name with location context.
Dots in the city name are replaced with spaces for readability.
dataset_variant
property
¶
Extract the TMYx dataset variant from the download URL.
Returns a string like "TMYx", "TMYx.2007-2021", or
"TMYx.2009-2023".
to_dict()
¶
Serialize to a plain dictionary for JSON storage.
from_dict(data)
classmethod
¶
Deserialize from a plain dictionary.
apply_ashrae_sizing(model, station, *, standard='general', version=None)
¶
Apply standard ASHRAE sizing design days to a model.
This is the one-line convenience function for the most common use case.
Presets
"90.1": Heating 99.6% + Cooling 1% DB + Cooling 1% WB (per ASHRAE Standard 90.1 requirements)."general": Heating 99.6% + Cooling 0.4% DB (conservative general practice).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
IDFDocument
|
The IDFDocument to modify. |
required |
station
|
WeatherStation
|
Weather station whose DDY file to use. |
required |
standard
|
Literal['90.1', 'general']
|
ASHRAE preset to apply. |
'general'
|
version
|
tuple[int, int, int] | None
|
EnergyPlus version for schema resolution. |
None
|
Returns:
| Type | Description |
|---|---|
list[str]
|
List of design day names that were added. |
Raises:
| Type | Description |
|---|---|
NoDesignDaysError
|
If the station's DDY file contains no design days. The exception includes suggestions for nearby stations that may have design day data. |