Metadata-Version: 2.4
Name: epwforge
Version: 0.1.0
Summary: Python client for EPWForge — generate climate-stressed EPW weather files for any global location. Custom TMYx / AMY from ERA5, CMIP6 future-climate morphing across SSP scenarios, urban heat island, extreme-event injection (heat waves, cold snaps, compound humidity/wind), and wildfire smoke overlays. For EnergyPlus, OpenStudio, IES VE, eQUEST.
Project-URL: Homepage, https://epwforge.com
Project-URL: Repository, https://github.com/guzz-labs/epwforge-py
Project-URL: Issues, https://github.com/guzz-labs/epwforge-py/issues
Author-email: Guzzlabs <tuna@guzzlabs.com>
License: MIT
License-File: LICENSE
Keywords: amy,building-energy-modeling,building-energy-simulation,climate-adaptation,climate-deltas,climate-resilience,cmip6,cold-snap,compound-events,custom-weather-file,ddy,energyplus,epw,epwforge,equest,era5,extreme-events,guzzlabs,heat-wave,honeybee,ies-ve,ipcc-ar6,ladybug,openstudio,ssp,tmy,tmyx,uhi,urban-heat-island,weather-file,weather-morphing,wildfire-smoke
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
Requires-Python: >=3.9
Requires-Dist: httpx[http2]>=0.27.0
Description-Content-Type: text/markdown

# epwforge

> Python client for [EPWForge](https://epwforge.com) — 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.

## Install

```bash
pip install epwforge
```

Requires Python ≥ 3.9.

## Usage

```python
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.

## Authentication

Generate an API key at [epwforge.com/account](https://epwforge.com/account). Pass it explicitly or set `EPWFORGE_API_KEY` in the environment.

## Plan requirements

| 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.

## Error handling

```python
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:
        raise
```

## Compound events

`events="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.

## AR6 auto-fill under SSP

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.

## Context manager

```python
with Client() as c:
    c.weather_file(lat=40.71, lon=-74.01, save_to="nyc.epw")
    # connection pool closed automatically on exit
```

## Links

- **Website:** [epwforge.com](https://epwforge.com)
- **REST API docs:** [epwforge.com/docs](https://epwforge.com/docs)
- **MCP server (for AI agents):** [`pip install epwforge-mcp`](https://pypi.org/project/epwforge-mcp/)
- **Maker:** [Guzzlabs](https://guzzlabs.com)

## License

MIT
