A python package to enable simple and easy gathering of climate model data and morphing of EPW files
Project description
pyepwmorph
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
With uv (recommended)
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.
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 via specific humidity (stretch)
- 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 are automatically added when needed:
- Humidity requires Temperature and Pressure
- Dew Point requires Temperature, Humidity, and Pressure
Caching
Climate model data is cached locally after the first download to speed up repeated analyses.
import pyepwmorph.models.access as access
stats = access.get_cmip6_cache_stats()
access.clear_cmip6_cache()
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
pytest
# Run with coverage
pytest --cov=pyepwmorph
Breaking changes in v2.0.0
- License changed from GPL-3.0 to MIT.
future_yearsparameter renamed totarget_yearsacross the API. The old name is still accepted with a deprecation warning.MorphConfigaccepts new parameters:data_source,custom_data,reference_scenario, andtarget_years.- EPW I/O (
pyepwmorph.tools.io) rewritten with stricter validation. Files that are not exactly 8760 data rows will now raiseValueError. The lat/lon parsing bug in the standaloneepw_location()function has been fixed. coordinate_cmip6_datanow accepts an optionaltime_slicesdict for custom temporal bounds instead of hardcoded 1960-2014 / 2015-2100.- Removed
requirements.txt,environment.yml,.bumpversion.cfg. Useuv syncorpip install .instead. - Per-module
__version__strings removed. Usepyepwmorph.__version__orimportlib.metadata.version("pyepwmorph").
Requirements
- Python >= 3.9
- Internet connection (for CMIP6 data download)
License
MIT License. See LICENSE.
Citation
McCarty, J. (2026). pyepwmorph: A Python package for climate-informed
EPW file morphing. Version 2.0.0.
https://github.com/justinfmccarty/pyepwmorph
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyepwmorph-2.0.2.tar.gz.
File metadata
- Download URL: pyepwmorph-2.0.2.tar.gz
- Upload date:
- Size: 35.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40cbcd655de7a33c0b84602ceedfb07bd16b94156a78ca8ab6763d841f7860c2
|
|
| MD5 |
d40800dde1c7d4adebf93901363215c9
|
|
| BLAKE2b-256 |
fcd524e50a7fad2e417d003c7f1ea7b7195231ee29e3c2e8724a024e9d8c5f07
|
Provenance
The following attestation bundles were made for pyepwmorph-2.0.2.tar.gz:
Publisher:
publish.yml on justinfmccarty/pyepwmorph
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyepwmorph-2.0.2.tar.gz -
Subject digest:
40cbcd655de7a33c0b84602ceedfb07bd16b94156a78ca8ab6763d841f7860c2 - Sigstore transparency entry: 1056936744
- Sigstore integration time:
-
Permalink:
justinfmccarty/pyepwmorph@4eb72d299341fc5ff94aca67b8987a5d7984b4e9 -
Branch / Tag:
refs/tags/v2.0.2 - Owner: https://github.com/justinfmccarty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4eb72d299341fc5ff94aca67b8987a5d7984b4e9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyepwmorph-2.0.2-py3-none-any.whl.
File metadata
- Download URL: pyepwmorph-2.0.2-py3-none-any.whl
- Upload date:
- Size: 40.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3feb1d62dbcd0c986688465e312eb6f931013568e637c7c4033009852256123
|
|
| MD5 |
3519ac845000b45f17823f9d4f12543c
|
|
| BLAKE2b-256 |
2d0733dec0d8a9e5de994e6f0dc2d38268ab8811b36facbb0afa9107e710f549
|
Provenance
The following attestation bundles were made for pyepwmorph-2.0.2-py3-none-any.whl:
Publisher:
publish.yml on justinfmccarty/pyepwmorph
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyepwmorph-2.0.2-py3-none-any.whl -
Subject digest:
b3feb1d62dbcd0c986688465e312eb6f931013568e637c7c4033009852256123 - Sigstore transparency entry: 1056936749
- Sigstore integration time:
-
Permalink:
justinfmccarty/pyepwmorph@4eb72d299341fc5ff94aca67b8987a5d7984b4e9 -
Branch / Tag:
refs/tags/v2.0.2 - Owner: https://github.com/justinfmccarty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4eb72d299341fc5ff94aca67b8987a5d7984b4e9 -
Trigger Event:
release
-
Statement type: