Skip to main content

pyepwmorph

License: MIT Python 3.9+ PyPI

A Python package for morphing EnergyPlus Weather (EPW) files with climate model data. Supports CMIP6 projections from Google Cloud and custom CSV-based model data for both future and historical scenarios.

Overview

pyepwmorph enables building performance analysts and researchers to create morphed weather files by applying scientifically validated procedures (Belcher et al. 2005, Jentsch et al. 2013) to existing EPW files. The package can morph EPWs using:

  • CMIP6 data fetched automatically from Google Cloud (Pangeo)
  • Custom CSV data from any climate model, including historical reconstructions

Installation

uv add pyepwmorph

Development setup

git clone https://github.com/justinfmccarty/pyepwmorph.git
cd pyepwmorph
uv sync --extra dev

With pip

pip install pyepwmorph

Quick start

CMIP6 workflow (future projections)

import pyepwmorph.tools.workflow as workflow

results = workflow.morphing_workflow(
    project_name="MyBuilding_Future",
    epw_file="weather.epw",
    user_variables=["Temperature", "Humidity", "Clouds and Radiation"],
    user_pathways=["Middle of the Road"],   # ssp245
    percentiles=[50],
    target_years=[2050],
    output_directory="output/",
)

Custom CSV workflow (historical or any model)

import pyepwmorph.tools.workflow as workflow

custom_data = {
    "reference": {
        "tas": "data/reference_tas.csv",
        "tasmax": "data/reference_tasmax.csv",
        "tasmin": "data/reference_tasmin.csv",
    },
    "target_1990s": {
        "tas": "data/target_tas.csv",
        "tasmax": "data/target_tasmax.csv",
        "tasmin": "data/target_tasmin.csv",
    },
}

results = workflow.morphing_workflow(
    project_name="Historical_Morph",
    epw_file="weather.epw",
    user_variables=["Temperature"],
    user_pathways=["target_1990s"],
    percentiles=[50],
    target_years=[1990],
    output_directory="output/",
    data_source="custom",
    custom_data=custom_data,
    reference_scenario="reference",
)

Custom CSVs should have a date column (parseable by pandas) and a column named after the CMIP6 variable (e.g. tas, tasmax). Rows should be monthly.

The reference and target scenarios must cover different years, the same way the CMIP6 historical and sspXXX experiments do. The two series are concatenated before the baseline and target periods are sliced out, so overlapping years get averaged together and weaken the climate signal. Keep baseline_range inside the years the reference scenario covers.

Climate scenarios

Scenario SSP Description Expected warming
Best Case Scenario ssp126 Strong mitigation, renewable transition ~1.8 C by 2100
Middle of the Road ssp245 Moderate mitigation efforts ~2.7 C by 2100
Upper Middle Scenario ssp370 Regional rivalry, slow convergence ~3.6 C by 2100
Worst Case Scenario ssp585 Fossil-fueled development ~4.4 C by 2100

Morphing variables

  • Temperature -- dry bulb temperature (shift + stretch)
  • Humidity -- relative humidity, stretched in specific humidity space
  • Pressure -- atmospheric pressure (shift)
  • Wind -- wind speed (stretch)
  • Clouds and Radiation -- global/diffuse/direct radiation and sky cover
  • Dew Point -- recalculated from morphed temperature and humidity

Variable dependencies

Some variables cannot be morphed on their own:

  • Humidity requires Temperature and Pressure
  • Dew Point requires Temperature, Humidity, and Pressure

Dependencies are added automatically and are written to the output file. Asking for Dew Point alone therefore returns an EPW with morphed pressure, temperature, relative humidity, and dew point, which keeps the file internally consistent. MorphConfig.resolved_variables shows exactly what will be written, in the order it is computed.

Caching

Climate model data is cached locally after the first download, and the cache is consulted before the remote catalogue is opened so a hit costs no network traffic.

import pyepwmorph.models.access as access

stats = access.get_cmip6_cache_stats()
access.clear_cmip6_cache()

Cache entries live in the per-user cache directory (~/Library/Caches/pyepwmorph on macOS, ~/.cache/pyepwmorph on Linux, %LOCALAPPDATA%\pyepwmorph on Windows) and are keyed by location, pathway, variable, model sources, and time slices. Two environment variables override the defaults:

Variable Purpose Default
PYEPWMORPH_CACHE_DIR Where cache files are written per-user cache directory
PYEPWMORPH_CACHE_MAX_MB Size cap before old files go 500

Available climate models

from pyepwmorph.tools.utilities import available_models

models = available_models()

Development

git clone https://github.com/justinfmccarty/pyepwmorph.git
cd pyepwmorph
uv sync --extra dev

# Run tests (fully offline)
uv run pytest

# Run with coverage
uv run pytest --cov=pyepwmorph

# Lint
uv run ruff check pyepwmorph tests gui

Releases

./release.sh [patch|minor|major]

The script refuses to run on a dirty tree, off main, with failing lint or tests, or without a matching CHANGELOG.md section. It bumps the version, tags, and pushes; creating the GitHub Release then triggers the PyPI publish workflow.

gh release create v3.0.0 \
  --title "v3.0.0" \
  --notes "See CHANGELOG.md."

Changes

See CHANGELOG.md for the full history. The most recent release corrects several morphing calculations, so morphed humidity, dew point, wind speed, cloud cover, and direct/diffuse radiation all differ from files produced by earlier versions.

Requirements

  • Python >= 3.9
  • pandas >= 2.2
  • Internet connection (for CMIP6 data download; the custom CSV workflow runs offline)

License

MIT License. See LICENSE.

Citation

McCarty, J. (2026). pyepwmorph: A Python package for climate-informed
EPW file morphing. Version 3.0.0.
https://github.com/justinfmccarty/pyepwmorph

Metadata

Release files for pyepwmorph 3.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyepwmorph 3.0.0
File Size Uploaded
pyepwmorph-3.0.0.tar.gz 34.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyepwmorph 3.0.0
File Interpreter ABI Platform
pyepwmorph-3.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 74.1 kB

Release files / pyepwmorph-3.0.0.tar.gz

Download URL pyepwmorph-3.0.0.tar.gz
Size 34.3 kB
Tags Source
SHA-256 checksum
How to use checksums
10fc33e50fd11e4c82ce5c491f4f9a2e56fe49502cffbcfca3a4346f3f74c238
BLAKE2b-256 checksum
How to use checksums
cdba93a20b118dac145b66467e0ff22dbfadc078747aaee46a8fcdf514d36aec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release files / pyepwmorph-3.0.0-py3-none-any.whl

Download URL pyepwmorph-3.0.0-py3-none-any.whl
Size 39.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f57b657f3257527aa883c39fa2f7e25e4c2c235b87a0aa1156973fe8ed5b899b
BLAKE2b-256 checksum
How to use checksums
8eca97a8138e465d27fd0821f4bbb2c85a4e64590f11d122355d699c138b0b82
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release history Release notifications | RSS feed

3.5.0

2 release files

3.4.0

2 release files

3.3.0

2 release files

3.2.0

2 release files

3.1.0

2 release files

This release

3.0.0 This release

2 release files

2.2.0

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.2

2 release files

2.0.0

2 release files

1.1.0

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

0.4.12

2 release files

0.4.11

2 release files

0.4.10

2 release files

0.4.9

2 release files

0.4.8

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.1

2 release files

0.3.1

1 release file

0.3.0

1 release file

0.2.8

1 release file

0.2.7

1 release file

0.2.6

1 release file

0.2.5

1 release file

0.2.4

1 release file

0.2.3

1 release file

0.2.2

1 release file

0.2.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page