pyepwmorph 2.2.0__tar.gz → 3.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/PKG-INFO +45 -48
  2. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/README.md +38 -39
  3. pyepwmorph-3.0.0/pyepwmorph/__init__.py +8 -0
  4. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/pyepwmorph/models/access.py +13 -19
  5. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/pyepwmorph/models/assemble.py +3 -6
  6. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/pyepwmorph/models/coordinate.py +7 -38
  7. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/pyepwmorph/models/custom.py +0 -1
  8. pyepwmorph-3.0.0/pyepwmorph/morph/procedures.py +561 -0
  9. pyepwmorph-3.0.0/pyepwmorph/tools/cache.py +324 -0
  10. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/pyepwmorph/tools/configuration.py +51 -18
  11. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/pyepwmorph/tools/io.py +47 -27
  12. pyepwmorph-3.0.0/pyepwmorph/tools/psychrometrics.py +185 -0
  13. pyepwmorph-3.0.0/pyepwmorph/tools/solar.py +268 -0
  14. pyepwmorph-3.0.0/pyepwmorph/tools/utilities.py +407 -0
  15. pyepwmorph-3.0.0/pyepwmorph/tools/workflow.py +448 -0
  16. pyepwmorph-3.0.0/pyproject.toml +93 -0
  17. pyepwmorph-2.2.0/pyepwmorph/__init__.py +0 -8
  18. pyepwmorph-2.2.0/pyepwmorph/morph/procedures.py +0 -563
  19. pyepwmorph-2.2.0/pyepwmorph/tools/cache.py +0 -271
  20. pyepwmorph-2.2.0/pyepwmorph/tools/ladybug_psychrometrics.py +0 -531
  21. pyepwmorph-2.2.0/pyepwmorph/tools/solar.py +0 -326
  22. pyepwmorph-2.2.0/pyepwmorph/tools/utilities.py +0 -455
  23. pyepwmorph-2.2.0/pyepwmorph/tools/workflow.py +0 -569
  24. pyepwmorph-2.2.0/pyproject.toml +0 -66
  25. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/.gitignore +0 -0
  26. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/LICENSE +0 -0
  27. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/pyepwmorph/models/__init__.py +0 -0
  28. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/pyepwmorph/morph/__init__.py +0 -0
  29. {pyepwmorph-2.2.0 → pyepwmorph-3.0.0}/pyepwmorph/tools/__init__.py +0 -0
@@ -1,12 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyepwmorph
3
- Version: 2.2.0
3
+ Version: 3.0.0
4
4
  Summary: A python package to enable simple and easy gathering of climate model data and morphing of EPW files
5
5
  Project-URL: Homepage, https://github.com/justinfmccarty/pyepwmorph
6
6
  Project-URL: Issues, https://github.com/justinfmccarty/pyepwmorph/issues
7
+ Project-URL: Changelog, https://github.com/justinfmccarty/pyepwmorph/blob/main/CHANGELOG.md
7
8
  Author-email: Justin McCarty <mccarty.justin.f@gmail.com>
8
9
  License: MIT
9
10
  License-File: LICENSE
11
+ Classifier: Intended Audience :: Science/Research
10
12
  Classifier: License :: OSI Approved :: MIT License
11
13
  Classifier: Operating System :: OS Independent
12
14
  Classifier: Programming Language :: Python :: 3
@@ -14,21 +16,17 @@ Classifier: Programming Language :: Python :: 3.9
14
16
  Classifier: Programming Language :: Python :: 3.10
15
17
  Classifier: Programming Language :: Python :: 3.11
16
18
  Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
17
21
  Requires-Python: >=3.9
18
22
  Requires-Dist: dask>=2023.5.0
19
- Requires-Dist: distributed>=2023.5.0
20
23
  Requires-Dist: gcsfs>=2023.5.0
21
24
  Requires-Dist: intake-esm>=2023.6.0
22
25
  Requires-Dist: intake>=0.6.0
23
- Requires-Dist: ipython>=7.0
24
- Requires-Dist: lz4>=4.0.0
25
- Requires-Dist: meteocalc>=1.1.0
26
- Requires-Dist: numpy>=1.20.0
27
- Requires-Dist: pandas>=1.3.0
26
+ Requires-Dist: numpy>=1.24
27
+ Requires-Dist: pandas>=2.2
28
28
  Requires-Dist: pvlib<1.0.0,>=0.13.0
29
29
  Requires-Dist: pyarrow>=13.0.0
30
- Requires-Dist: skyfield>=1.40
31
- Requires-Dist: timezonefinder>=6.0.0
32
30
  Requires-Dist: xarray>=2022.3.0
33
31
  Provides-Extra: dev
34
32
  Requires-Dist: build>=0.10; extra == 'dev'
@@ -43,7 +41,7 @@ Description-Content-Type: text/markdown
43
41
 
44
42
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
45
43
  [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/downloads/)
46
- [![Version](https://img.shields.io/badge/version-2.0.0-green.svg)](https://github.com/justinfmccarty/pyepwmorph)
44
+ [![PyPI](https://img.shields.io/pypi/v/pyepwmorph.svg)](https://pypi.org/project/pyepwmorph/)
47
45
 
48
46
  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.
49
47
 
@@ -128,19 +126,21 @@ results = workflow.morphing_workflow(
128
126
 
129
127
  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.
130
128
 
129
+ 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.
130
+
131
131
  ## Climate scenarios
132
132
 
133
- | Scenario | SSP | Description | Expected warming |
134
- |----------|-----|-------------|------------------|
135
- | Best Case Scenario | ssp126 | Strong mitigation, renewable transition | ~1.8 C by 2100 |
136
- | Middle of the Road | ssp245 | Moderate mitigation efforts | ~2.7 C by 2100 |
137
- | Upper Middle Scenario | ssp370 | Regional rivalry, slow convergence | ~3.6 C by 2100 |
138
- | Worst Case Scenario | ssp585 | Fossil-fueled development | ~4.4 C by 2100 |
133
+ | Scenario | SSP | Description | Expected warming |
134
+ | --------------------- | ------ | --------------------------------------- | ---------------- |
135
+ | Best Case Scenario | ssp126 | Strong mitigation, renewable transition | ~1.8 C by 2100 |
136
+ | Middle of the Road | ssp245 | Moderate mitigation efforts | ~2.7 C by 2100 |
137
+ | Upper Middle Scenario | ssp370 | Regional rivalry, slow convergence | ~3.6 C by 2100 |
138
+ | Worst Case Scenario | ssp585 | Fossil-fueled development | ~4.4 C by 2100 |
139
139
 
140
140
  ## Morphing variables
141
141
 
142
142
  - **Temperature** -- dry bulb temperature (shift + stretch)
143
- - **Humidity** -- relative humidity via specific humidity (stretch)
143
+ - **Humidity** -- relative humidity, stretched in specific humidity space
144
144
  - **Pressure** -- atmospheric pressure (shift)
145
145
  - **Wind** -- wind speed (stretch)
146
146
  - **Clouds and Radiation** -- global/diffuse/direct radiation and sky cover
@@ -148,14 +148,16 @@ Custom CSVs should have a `date` column (parseable by pandas) and a column named
148
148
 
149
149
  ### Variable dependencies
150
150
 
151
- Some variables are automatically added when needed:
151
+ Some variables cannot be morphed on their own:
152
152
 
153
153
  - **Humidity** requires Temperature and Pressure
154
154
  - **Dew Point** requires Temperature, Humidity, and Pressure
155
155
 
156
+ 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.
157
+
156
158
  ## Caching
157
159
 
158
- Climate model data is cached locally after the first download to speed up repeated analyses.
160
+ 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.
159
161
 
160
162
  ```python
161
163
  import pyepwmorph.models.access as access
@@ -164,6 +166,13 @@ stats = access.get_cmip6_cache_stats()
164
166
  access.clear_cmip6_cache()
165
167
  ```
166
168
 
169
+ 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:
170
+
171
+ | Variable | Purpose | Default |
172
+ | ------------------------- | ------------------------------ | ------- |
173
+ | `PYEPWMORPH_CACHE_DIR` | Where cache files are written | per-user cache directory |
174
+ | `PYEPWMORPH_CACHE_MAX_MB` | Size cap before old files go | 500 |
175
+
167
176
  ## Available climate models
168
177
 
169
178
  ```python
@@ -179,51 +188,39 @@ git clone https://github.com/justinfmccarty/pyepwmorph.git
179
188
  cd pyepwmorph
180
189
  uv sync --extra dev
181
190
 
182
- # Run tests
183
- pytest
191
+ # Run tests (fully offline)
192
+ uv run pytest
184
193
 
185
194
  # Run with coverage
186
- pytest --cov=pyepwmorph
195
+ uv run pytest --cov=pyepwmorph
196
+
197
+ # Lint
198
+ uv run ruff check pyepwmorph tests gui
187
199
  ```
188
200
 
189
201
  ### Releases
202
+
190
203
  ```bash
191
204
  ./release.sh [patch|minor|major]
192
205
  ```
193
206
 
194
- Copy-paste (change version number) for release statement
195
- ```bash
196
- gh release create v2.2.0 \
197
- --title "v2.2.0" \
198
- --notes "## What's new
207
+ 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.
199
208
 
200
- See README for full breaking changes list."
209
+ ```bash
210
+ gh release create v3.0.0 \
211
+ --title "v3.0.0" \
212
+ --notes "See CHANGELOG.md."
201
213
  ```
202
214
 
215
+ ## Changes
203
216
 
204
-
205
- ## Breaking changes in v2.0.0
206
-
207
- - **License changed** from GPL-3.0 to MIT.
208
- - **`future_years`** parameter renamed to **`target_years`** across the API.
209
- The old name is still accepted with a deprecation warning.
210
- - **`MorphConfig`** accepts new parameters: `data_source`, `custom_data`,
211
- `reference_scenario`, and `target_years`.
212
- - **EPW I/O** (`pyepwmorph.tools.io`) rewritten with stricter validation.
213
- Files that are not exactly 8760 data rows will now raise `ValueError`.
214
- The lat/lon parsing bug in the standalone `epw_location()` function has
215
- been fixed.
216
- - **`coordinate_cmip6_data`** now accepts an optional `time_slices` dict
217
- for custom temporal bounds instead of hardcoded 1960-2014 / 2015-2100.
218
- - **Removed** `requirements.txt`, `environment.yml`, `.bumpversion.cfg`.
219
- Use `uv sync` or `pip install .` instead.
220
- - **Per-module `__version__`** strings removed. Use
221
- `pyepwmorph.__version__` or `importlib.metadata.version("pyepwmorph")`.
217
+ See [CHANGELOG.md](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.
222
218
 
223
219
  ## Requirements
224
220
 
225
221
  - Python >= 3.9
226
- - Internet connection (for CMIP6 data download)
222
+ - pandas >= 2.2
223
+ - Internet connection (for CMIP6 data download; the custom CSV workflow runs offline)
227
224
 
228
225
  ## License
229
226
 
@@ -233,6 +230,6 @@ MIT License. See [LICENSE](LICENSE).
233
230
 
234
231
  ```text
235
232
  McCarty, J. (2026). pyepwmorph: A Python package for climate-informed
236
- EPW file morphing. Version 2.0.0.
233
+ EPW file morphing. Version 3.0.0.
237
234
  https://github.com/justinfmccarty/pyepwmorph
238
235
  ```
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
4
  [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/downloads/)
5
- [![Version](https://img.shields.io/badge/version-2.0.0-green.svg)](https://github.com/justinfmccarty/pyepwmorph)
5
+ [![PyPI](https://img.shields.io/pypi/v/pyepwmorph.svg)](https://pypi.org/project/pyepwmorph/)
6
6
 
7
7
  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.
8
8
 
@@ -87,19 +87,21 @@ results = workflow.morphing_workflow(
87
87
 
88
88
  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.
89
89
 
90
+ 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.
91
+
90
92
  ## Climate scenarios
91
93
 
92
- | Scenario | SSP | Description | Expected warming |
93
- |----------|-----|-------------|------------------|
94
- | Best Case Scenario | ssp126 | Strong mitigation, renewable transition | ~1.8 C by 2100 |
95
- | Middle of the Road | ssp245 | Moderate mitigation efforts | ~2.7 C by 2100 |
96
- | Upper Middle Scenario | ssp370 | Regional rivalry, slow convergence | ~3.6 C by 2100 |
97
- | Worst Case Scenario | ssp585 | Fossil-fueled development | ~4.4 C by 2100 |
94
+ | Scenario | SSP | Description | Expected warming |
95
+ | --------------------- | ------ | --------------------------------------- | ---------------- |
96
+ | Best Case Scenario | ssp126 | Strong mitigation, renewable transition | ~1.8 C by 2100 |
97
+ | Middle of the Road | ssp245 | Moderate mitigation efforts | ~2.7 C by 2100 |
98
+ | Upper Middle Scenario | ssp370 | Regional rivalry, slow convergence | ~3.6 C by 2100 |
99
+ | Worst Case Scenario | ssp585 | Fossil-fueled development | ~4.4 C by 2100 |
98
100
 
99
101
  ## Morphing variables
100
102
 
101
103
  - **Temperature** -- dry bulb temperature (shift + stretch)
102
- - **Humidity** -- relative humidity via specific humidity (stretch)
104
+ - **Humidity** -- relative humidity, stretched in specific humidity space
103
105
  - **Pressure** -- atmospheric pressure (shift)
104
106
  - **Wind** -- wind speed (stretch)
105
107
  - **Clouds and Radiation** -- global/diffuse/direct radiation and sky cover
@@ -107,14 +109,16 @@ Custom CSVs should have a `date` column (parseable by pandas) and a column named
107
109
 
108
110
  ### Variable dependencies
109
111
 
110
- Some variables are automatically added when needed:
112
+ Some variables cannot be morphed on their own:
111
113
 
112
114
  - **Humidity** requires Temperature and Pressure
113
115
  - **Dew Point** requires Temperature, Humidity, and Pressure
114
116
 
117
+ 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.
118
+
115
119
  ## Caching
116
120
 
117
- Climate model data is cached locally after the first download to speed up repeated analyses.
121
+ 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.
118
122
 
119
123
  ```python
120
124
  import pyepwmorph.models.access as access
@@ -123,6 +127,13 @@ stats = access.get_cmip6_cache_stats()
123
127
  access.clear_cmip6_cache()
124
128
  ```
125
129
 
130
+ 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:
131
+
132
+ | Variable | Purpose | Default |
133
+ | ------------------------- | ------------------------------ | ------- |
134
+ | `PYEPWMORPH_CACHE_DIR` | Where cache files are written | per-user cache directory |
135
+ | `PYEPWMORPH_CACHE_MAX_MB` | Size cap before old files go | 500 |
136
+
126
137
  ## Available climate models
127
138
 
128
139
  ```python
@@ -138,51 +149,39 @@ git clone https://github.com/justinfmccarty/pyepwmorph.git
138
149
  cd pyepwmorph
139
150
  uv sync --extra dev
140
151
 
141
- # Run tests
142
- pytest
152
+ # Run tests (fully offline)
153
+ uv run pytest
143
154
 
144
155
  # Run with coverage
145
- pytest --cov=pyepwmorph
156
+ uv run pytest --cov=pyepwmorph
157
+
158
+ # Lint
159
+ uv run ruff check pyepwmorph tests gui
146
160
  ```
147
161
 
148
162
  ### Releases
163
+
149
164
  ```bash
150
165
  ./release.sh [patch|minor|major]
151
166
  ```
152
167
 
153
- Copy-paste (change version number) for release statement
154
- ```bash
155
- gh release create v2.2.0 \
156
- --title "v2.2.0" \
157
- --notes "## What's new
168
+ 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.
158
169
 
159
- See README for full breaking changes list."
170
+ ```bash
171
+ gh release create v3.0.0 \
172
+ --title "v3.0.0" \
173
+ --notes "See CHANGELOG.md."
160
174
  ```
161
175
 
176
+ ## Changes
162
177
 
163
-
164
- ## Breaking changes in v2.0.0
165
-
166
- - **License changed** from GPL-3.0 to MIT.
167
- - **`future_years`** parameter renamed to **`target_years`** across the API.
168
- The old name is still accepted with a deprecation warning.
169
- - **`MorphConfig`** accepts new parameters: `data_source`, `custom_data`,
170
- `reference_scenario`, and `target_years`.
171
- - **EPW I/O** (`pyepwmorph.tools.io`) rewritten with stricter validation.
172
- Files that are not exactly 8760 data rows will now raise `ValueError`.
173
- The lat/lon parsing bug in the standalone `epw_location()` function has
174
- been fixed.
175
- - **`coordinate_cmip6_data`** now accepts an optional `time_slices` dict
176
- for custom temporal bounds instead of hardcoded 1960-2014 / 2015-2100.
177
- - **Removed** `requirements.txt`, `environment.yml`, `.bumpversion.cfg`.
178
- Use `uv sync` or `pip install .` instead.
179
- - **Per-module `__version__`** strings removed. Use
180
- `pyepwmorph.__version__` or `importlib.metadata.version("pyepwmorph")`.
178
+ See [CHANGELOG.md](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.
181
179
 
182
180
  ## Requirements
183
181
 
184
182
  - Python >= 3.9
185
- - Internet connection (for CMIP6 data download)
183
+ - pandas >= 2.2
184
+ - Internet connection (for CMIP6 data download; the custom CSV workflow runs offline)
186
185
 
187
186
  ## License
188
187
 
@@ -192,6 +191,6 @@ MIT License. See [LICENSE](LICENSE).
192
191
 
193
192
  ```text
194
193
  McCarty, J. (2026). pyepwmorph: A Python package for climate-informed
195
- EPW file morphing. Version 2.0.0.
194
+ EPW file morphing. Version 3.0.0.
196
195
  https://github.com/justinfmccarty/pyepwmorph
197
196
  ```
@@ -0,0 +1,8 @@
1
+ """pyepwmorph -- Climate model data gathering and EPW file morphing."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ try:
6
+ __version__ = version("pyepwmorph")
7
+ except PackageNotFoundError: # running from a source tree that was never installed
8
+ __version__ = "0.0.0+unknown"
@@ -1,16 +1,11 @@
1
- # coding=utf-8
2
1
  """
3
2
  various scripts for accessing different flavors of climate models
4
3
  """
5
4
 
6
- import warnings
7
-
8
5
  from pyepwmorph.tools import cache
9
6
 
10
- warnings.filterwarnings("ignore")
11
-
12
7
  __author__ = "Justin McCarty"
13
- __copyright__ = "Copyright 2023"
8
+ __copyright__ = "Copyright 2023-2026"
14
9
  __credits__ = ["Justin McCarty"]
15
10
  __license__ = "MIT"
16
11
 
@@ -46,12 +41,12 @@ def access_cmip6_data(models, pathway, variable):
46
41
  import intake
47
42
 
48
43
  # NOTE: No caching at this level because the data contains lazy dask arrays
49
- # that reference the full global grid. Caching happens in coordinate.py after
44
+ # that reference the full global grid. Caching happens in workflow.py once
50
45
  # the data has been spatially selected and computed for a specific location.
51
-
46
+
52
47
  table_id = 'Amon' # atmospheric variables (A) saved at monthly resolution (mon)
53
48
  member_id = 'r1i1p1f1'
54
-
49
+
55
50
  # Fetch from Google Cloud
56
51
  gcsfs.GCSFileSystem(token='anon')
57
52
  # datastore_json = 'pangeo-cmip6.json'
@@ -64,7 +59,7 @@ def access_cmip6_data(models, pathway, variable):
64
59
 
65
60
  # convert data catalog into a dictionary of xarray datasets
66
61
  dataset_dict = model_search.to_dataset_dict(zarr_kwargs={'consolidated': True, 'decode_times': False})
67
-
62
+
68
63
  return dataset_dict
69
64
 
70
65
 
@@ -84,19 +79,18 @@ def build_accessible_data_list():
84
79
  import gcsfs
85
80
  import intake
86
81
  gcsfs.GCSFileSystem(token='anon')
87
- # datastore_json = 'pangeo-cmip6.json'
88
82
  esm_data = intake.open_esm_datastore("https://storage.googleapis.com/cmip6/pangeo-cmip6.json")
89
- # return esm_data.df['source_id'].unique().tolist()
83
+ return sorted(esm_data.df['source_id'].unique().tolist())
90
84
 
91
85
 
92
86
  def clear_cmip6_cache():
93
87
  """
94
88
  Clear all cached CMIP6 data.
95
-
89
+
96
90
  This clears location-specific cached data that has been processed and stored
97
- for faster repeated access. This is useful for development or when you want
91
+ for faster repeated access. This is useful for development or when you want
98
92
  to free up disk space.
99
-
93
+
100
94
  Examples
101
95
  --------
102
96
  >>> clear_cmip6_cache()
@@ -107,11 +101,11 @@ def clear_cmip6_cache():
107
101
  def get_cmip6_cache_stats():
108
102
  """
109
103
  Get statistics about the CMIP6 data cache.
110
-
104
+
111
105
  Returns information about cache size, number of files, and individual
112
106
  file details for development and monitoring purposes. The cache stores
113
107
  location-specific processed data.
114
-
108
+
115
109
  Returns
116
110
  -------
117
111
  dict
@@ -122,10 +116,10 @@ def get_cmip6_cache_stats():
122
116
  - max_size_mb: Maximum allowed cache size
123
117
  - usage_percent: Percentage of max size used
124
118
  - files: List of individual file details
125
-
119
+
126
120
  Examples
127
121
  --------
128
122
  >>> stats = get_cmip6_cache_stats()
129
123
  >>> print(f"Cache using {stats['total_size_mb']} MB ({stats['usage_percent']}%)")
130
124
  """
131
- return cache.get_cache_stats()
125
+ return cache.get_cache_stats()
@@ -1,17 +1,14 @@
1
- # coding=utf-8
2
1
  """
3
2
  This module creates ensembles from multiple model inputs downloaded for a single pathway and variable.
4
3
  This is what enables the slicing of the data from a percentile point of view.
5
4
  """
6
5
  import pandas as pd
7
6
  import xarray as xr
8
- from pyepwmorph.tools import utilities
9
- import warnings
10
7
 
11
- warnings.filterwarnings("ignore")
8
+ from pyepwmorph.tools import utilities
12
9
 
13
10
  __author__ = "Justin McCarty"
14
- __copyright__ = "Copyright 2023"
11
+ __copyright__ = "Copyright 2023-2026"
15
12
  __credits__ = ["Justin McCarty"]
16
13
  __license__ = "MIT"
17
14
 
@@ -111,4 +108,4 @@ def calc_model_climatologies(baseline_range, future_range, baseline_data, future
111
108
  future_means = utilities.monthly_means(future_data).rename(variable)
112
109
 
113
110
 
114
- return baseline_means, future_means
111
+ return baseline_means, future_means
@@ -1,4 +1,3 @@
1
- # coding=utf-8
2
1
  """Coordinate CMIP6 model data into a standard grid and time system.
3
2
 
4
3
  Climate model data comes in varied grid systems and temporal indices.
@@ -7,16 +6,10 @@ it is fed to the morphing algorithm.
7
6
  """
8
7
 
9
8
  import logging
10
- import time
11
- import warnings
12
9
 
13
10
  import dask
14
- import pandas as pd
15
11
  import xarray as xr
16
12
 
17
- from pyepwmorph.tools import cache
18
-
19
- warnings.filterwarnings("ignore")
20
13
  logger = logging.getLogger(__name__)
21
14
 
22
15
  __author__ = "Justin McCarty"
@@ -64,30 +57,17 @@ def coordinate_cmip6_data(
64
57
  -------
65
58
  dict
66
59
  Dictionary of computed xarray Datasets keyed by source name.
60
+
61
+ Notes
62
+ -----
63
+ Caching lives in ``workflow.compile_climate_model_data`` so that a cache
64
+ hit avoids opening the remote catalogue at all. Calling this function
65
+ directly always recomputes.
67
66
  """
68
67
  slices = {**DEFAULT_TIME_SLICES}
69
68
  if time_slices:
70
69
  slices.update(time_slices)
71
70
 
72
- source_ids = list(dset_dict.keys())
73
- model_names = []
74
- for source_id in source_ids:
75
- parts = source_id.split('.')
76
- if len(parts) >= 3:
77
- model_names.append(parts[2])
78
- else:
79
- model_names.append(source_id)
80
-
81
- cached_data = cache.get_cached_coordinate_data(
82
- latitude=latitude,
83
- longitude=longitude,
84
- pathway=pathway,
85
- variable=variable,
86
- source_id=model_names,
87
- )
88
- if cached_data is not None:
89
- return cached_data
90
-
91
71
  time_start, time_end = slices.get(pathway, DEFAULT_SSP_SLICE)
92
72
 
93
73
  ds_dict = {}
@@ -118,15 +98,4 @@ def coordinate_cmip6_data(
118
98
 
119
99
  ds_dict[name] = ds
120
100
 
121
- datasets = dask.compute(ds_dict)[0]
122
-
123
- cache.save_coordinate_to_cache(
124
- data=datasets,
125
- latitude=latitude,
126
- longitude=longitude,
127
- pathway=pathway,
128
- variable=variable,
129
- source_id=model_names,
130
- )
131
-
132
- return datasets
101
+ return dask.compute(ds_dict)[0]
@@ -1,4 +1,3 @@
1
- # coding=utf-8
2
1
  """Load custom (non-CMIP6) climate model data from CSV files.
3
2
 
4
3
  The CSV format expected is: