Python client for EPWForge — generate climate-stressed EPW weather files for any global location. Custom TMYx / AMY from ERA5, CMIP6 future-climate morphing, urban heat island, extreme-event injection, and wildfire smoke overlays. For EnergyPlus, OpenStudio, IES VE, eQUEST.
pip install epwforgeRequires Python ≥ 3.9.
from epwforge import Client
c = Client(api_key="sk_live_...") # or set EPWFORGE_API_KEY env var
# Basic TMYx for any global lat/lon
c.weather_file(lat=40.71, lon=-74.01, save_to="nyc.epw")
# Actual Meteorological Year (specific year of ERA5 reanalysis)
c.weather_file(lat=40.71, lon=-74.01, basis="amy", amy_year=2023,
save_to="nyc_2023.epw")
# Future climate morphing — IPCC CMIP6 SSPs at 4 horizons × 7 percentiles
c.weather_file(lat=40.71, lon=-74.01, ssp="ssp245", year=2050,
save_to="nyc_2050.epw")
# Worst-case design scenario — UHI + heat wave + smoke + compound events
c.weather_file(
lat=33.45, lon=-112.07,
ssp="ssp585", year=2090, percentile=90,
uhi="urban",
events="heatwave,hothumid", # compound: humidity blends into heat
intensity="heatwave:9", # override AR6 auto-fill
smoke=True, smoke_intensity=5, # AOD ~3 (Bay Area 2020 levels)
save_to="phoenix_worst.epw",
)
# Per-model CMIP6 ensemble — one EPW per model for inter-model uncertainty
c.ensemble(lat=47.6, lon=-122.3, ssp="ssp245", year=2050,
save_to_dir="seattle/")
# ASHRAE design-day (DDY) file for EnergyPlus sizing
c.design_day(lat=40.71, lon=-74.01, ssp="ssp585", year=2090,
save_to="nyc_2090.ddy")
# Nearest ERA5 grid cells to a coordinate
c.stations(lat=40.71, lon=-74.01, max_results=5)save_to (or save_to_dir for ensembles) decodes the EPW directly to disk and returns the path — recommended pattern. Omit it to get the base64 payload inline.
Generate an API key at epwforge.com/account. Pass it explicitly or set EPWFORGE_API_KEY in the environment.
| Feature | Plan |
|---|---|
| TMYx / AMY basis without SSP | Starter |
| UHI / events / smoke adjustments | Starter |
ssp= future-climate morphing |
Pro |
c.ensemble(...) per-model CMIP6 |
Pro |
c.stations(...) |
Free |
The API enforces this server-side. The client surfaces 403 errors as EPWForgeError with a clear upgrade message.
from epwforge import Client, EPWForgeError
c = Client()
try:
c.weather_file(lat=40.71, lon=-74.01, ssp="ssp585", year=2090,
save_to="future.epw")
except EPWForgeError as e:
if e.status == 429:
print(f"Rate limited; retry in {e.retry_after}s")
elif e.status == 403:
print("Upgrade plan to use future-climate morphing")
else:
raiseevents="heatwave,hothumid" auto-blends humidity onto the heat event at 50%. events="coldsnap,coldwindy" does the same for wind onto cold. The secondary event is folded into the primary stitch (not added separately) so files don't get two events at different windows.
When ssp=... is set and you don't specify an event's intensity, the API fetches the IPCC AR6 ensemble factor for that (region, ssp, year, percentile, event type) and uses it as the slider value. Cold-family events are floored at 5 (no future amplification) — AR6 says cold dampens but recent observations don't yet support that, so we hold conservatively. Pass intensity_auto=False to opt out.
with Client() as c:
c.weather_file(lat=40.71, lon=-74.01, save_to="nyc.epw")
# connection pool closed automatically on exit- Website: epwforge.com
- REST API docs: epwforge.com/docs
- MCP server (for AI agents):
pip install epwforge-mcp - Maker: Guzzlabs
MIT