climval 0.1.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.
climval-0.1.0/LICENSE ADDED
@@ -0,0 +1,114 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship made available under
36
+ the License, as indicated by a copyright notice that is included in
37
+ or attached to the work (an example is provided in the Appendix below).
38
+
39
+ "Derivative Works" shall mean any work, whether in Source or Object
40
+ form, that is based on (or derived from) the Work and for which the
41
+ editorial revisions, annotations, elaborations, or other modifications
42
+ represent, as a whole, an original work of authorship.
43
+
44
+ "Contribution" shall mean, as submitted to the Licensor for inclusion
45
+ in the Work by the copyright owner or by an individual or Legal Entity
46
+ authorized to submit on behalf of the copyright owner.
47
+
48
+ "Contributor" shall mean Licensor and any Legal Entity on behalf of
49
+ whom a Contribution has been received by the Licensor and included
50
+ within the Work.
51
+
52
+ 2. Grant of Copyright License. Subject to the terms and conditions of
53
+ this License, each Contributor hereby grants to You a perpetual,
54
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
55
+ copyright license to reproduce, prepare Derivative Works of,
56
+ publicly display, publicly perform, sublicense, and distribute the
57
+ Work and such Derivative Works in Source or Object form.
58
+
59
+ 3. Grant of Patent License. Subject to the terms and conditions of
60
+ this License, each Contributor hereby grants to You a perpetual,
61
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
62
+ patent license to make, use, sell, offer for sale, import, and
63
+ otherwise transfer the Work.
64
+
65
+ 4. Redistribution. You may reproduce and distribute copies of the
66
+ Work or Derivative Works thereof in any medium, with or without
67
+ modifications, and in Source or Object form, provided that You
68
+ meet the following conditions:
69
+
70
+ (a) You must give any other recipients of the Work or Derivative
71
+ Works a copy of this License; and
72
+
73
+ (b) You must cause any modified files to carry prominent notices
74
+ stating that You changed the files; and
75
+
76
+ (c) You must retain, in the Source form of any Derivative Works
77
+ that You distribute, all copyright, patent, trademark, and
78
+ attribution notices from the Source form of the Work; and
79
+
80
+ (d) If the Work includes a "NOTICE" text file, you must include a
81
+ readable copy of the attribution notices contained within such
82
+ NOTICE file.
83
+
84
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
85
+ any Contribution submitted for inclusion in the Work shall be under
86
+ the terms and conditions of this License.
87
+
88
+ 6. Trademarks. This License does not grant permission to use the trade
89
+ names, trademarks, service marks, or product names of the Licensor.
90
+
91
+ 7. Disclaimer of Warranty. Unless required by applicable law or
92
+ agreed to in writing, Licensor provides the Work on an "AS IS"
93
+ BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND.
94
+
95
+ 8. Limitation of Liability. In no event and under no legal theory,
96
+ whether in tort (including negligence), contract, or otherwise,
97
+ unless required by applicable law (such as deliberate and grossly
98
+ negligent acts) or agreed to in writing, shall any Contributor be
99
+ liable to You for damages.
100
+
101
+ 9. Accepting Warranty or Additional Liability. While redistributing
102
+ the Work or Derivative Works thereof, You may offer, and charge a
103
+ fee for, acceptance of support, warranty, indemnity, or other
104
+ liability obligations and/or rights consistent with this License.
105
+
106
+ END OF TERMS AND CONDITIONS
107
+
108
+ Copyright 2026 Northflow Technologies
109
+
110
+ Licensed under the Apache License, Version 2.0 (the "License");
111
+ you may not use this file except in compliance with the License.
112
+ You may obtain a copy of the License at
113
+
114
+ http://www.apache.org/licenses/LICENSE-2.0
climval-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,377 @@
1
+ Metadata-Version: 2.4
2
+ Name: climval
3
+ Version: 0.1.0
4
+ Summary: Climate model validation and benchmarking framework
5
+ Author-email: Northflow Technologies <open@northflow.tech>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/northflow-technologies/climval
8
+ Project-URL: Issues, https://github.com/northflow-technologies/climval/issues
9
+ Project-URL: Changelog, https://github.com/northflow-technologies/climval/blob/main/CHANGELOG.md
10
+ Project-URL: Organisation, https://northflow.tech
11
+ Keywords: climate,validation,benchmarking,CMIP6,ERA5,reanalysis,atmospheric science,earth system model
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
20
+ Classifier: Topic :: Scientific/Engineering :: GIS
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: numpy>=1.24
26
+ Requires-Dist: scipy>=1.10
27
+ Provides-Extra: netcdf
28
+ Requires-Dist: xarray>=2023.1; extra == "netcdf"
29
+ Requires-Dist: netCDF4>=1.6; extra == "netcdf"
30
+ Provides-Extra: viz
31
+ Requires-Dist: matplotlib>=3.7; extra == "viz"
32
+ Requires-Dist: cartopy>=0.21; extra == "viz"
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=7.4; extra == "dev"
35
+ Requires-Dist: pytest-cov>=4.1; extra == "dev"
36
+ Requires-Dist: ruff>=0.1; extra == "dev"
37
+ Requires-Dist: mypy>=1.5; extra == "dev"
38
+ Provides-Extra: all
39
+ Requires-Dist: climval[dev,netcdf,viz]; extra == "all"
40
+ Dynamic: license-file
41
+
42
+ # climval
43
+
44
+ **Climate model validation and benchmarking, done right.**
45
+
46
+ An open, composable framework for comparing climate model outputs against
47
+ reference datasets. Built for researchers, universities, and infrastructure
48
+ teams working with CMIP6, ERA5, CORDEX, and custom simulation data.
49
+
50
+ [![CI](https://github.com/northflow-technologies/climval/actions/workflows/ci.yml/badge.svg)](https://github.com/northflow-technologies/climval/actions)
51
+ [![PyPI](https://img.shields.io/pypi/v/climval)](https://pypi.org/project/climval/)
52
+ [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/)
53
+ [![License](https://img.shields.io/badge/license-Apache%202.0-green)](LICENSE)
54
+ [![Code style: ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
55
+
56
+ ---
57
+
58
+ ## Why climval
59
+
60
+ Climate model comparison is routine science but operationally fragmented.
61
+ Every lab has a slightly different set of scripts for RMSE, bias, Taylor diagrams.
62
+ Results are rarely reproducible across groups.
63
+
64
+ `climval` provides a **typed, composable, reproducible** interface for
65
+ multi-model validation — designed from the ground up to support institutional
66
+ use, CI/CD pipelines, and long-running research workflows.
67
+
68
+ ---
69
+
70
+ ## Features
71
+
72
+ - **Composable metric library** — RMSE, MAE, Mean Bias, Normalized RMSE, Pearson r,
73
+ Spearman r, Taylor Skill Score, percentile bias (P5/P95), and more
74
+ - **Typed data models** — CF-convention variable definitions, spatial/temporal
75
+ domain objects, and structured `ValidationResult` schemas
76
+ - **Known presets** — ERA5, ERA5-Land, CMIP6-MPI, CMIP6-HadGEM, CORDEX-EUR
77
+ out of the box
78
+ - **NetCDF / CSV / Zarr support** — via `xarray` when real files are provided
79
+ - **Synthetic fallback** — full structural validation and CI without data files
80
+ - **Multi-format export** — HTML report, JSON, Markdown
81
+ - **CLI** — run comparisons directly from the terminal
82
+ - **Extensible** — plug in custom metrics, variables, and loaders
83
+
84
+ ---
85
+
86
+ ## Quickstart
87
+
88
+ ```python
89
+ from datetime import datetime
90
+ from climval import BenchmarkSuite, load_model
91
+
92
+ era5 = load_model(
93
+ "era5",
94
+ name="ERA5",
95
+ lat_range=(35.0, 72.0), # Europe
96
+ lon_range=(-10.0, 40.0),
97
+ time_start=datetime(2000, 1, 1),
98
+ time_end=datetime(2020, 12, 31),
99
+ )
100
+
101
+ mpi = load_model("cmip6-mpi", name="MPI-ESM1-2-HR")
102
+
103
+ suite = BenchmarkSuite(name="Europe-2000-2020")
104
+ suite.register(era5, role="reference")
105
+ suite.register(mpi)
106
+
107
+ report = suite.run(variables=["tas", "pr"])
108
+ report.summary()
109
+ report.export("results/report.html")
110
+ ```
111
+
112
+ Output:
113
+
114
+ ```
115
+ ════════════════════════════════════════════════════════════════════════
116
+ CLIMVAL — EUROPE-2000-2020
117
+ Reference : ERA5
118
+ Generated : 2025-01-15 14:32 UTC
119
+ ════════════════════════════════════════════════════════════════════════
120
+
121
+ ▸ Candidate: MPI-ESM1-2-HR
122
+ ──────────────────────────────────────────────────────────────────────
123
+ Variable Metric Value Units
124
+ ──────────────────────────────────────────────────────────────────────
125
+ tas rmse 1.2930 K
126
+ tas mae 1.0744 K
127
+ tas mean_bias -0.9721 K
128
+ tas nrmse 0.0845 dimensionless
129
+ tas pearson_r 0.9985 dimensionless
130
+ tas taylor_skill_score 0.9969 dimensionless
131
+ tas percentile_bias_p95 -0.0473 %
132
+ tas percentile_bias_p5 -0.6058 %
133
+ ...
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Installation
139
+
140
+ **Core (no NetCDF dependencies):**
141
+ ```bash
142
+ pip install climval
143
+ ```
144
+
145
+ **With NetCDF/xarray support:**
146
+ ```bash
147
+ pip install "climval[netcdf]"
148
+ ```
149
+
150
+ **With visualization:**
151
+ ```bash
152
+ pip install "climval[viz]"
153
+ ```
154
+
155
+ **Development:**
156
+ ```bash
157
+ git clone https://github.com/northflow-technologies/climval
158
+ cd climval
159
+ pip install -e ".[dev]"
160
+ pytest
161
+ ```
162
+
163
+ ---
164
+
165
+ ## CLI
166
+
167
+ ```bash
168
+ # Run a validation
169
+ climval run \
170
+ --reference era5 \
171
+ --candidates cmip6-mpi cordex-eur \
172
+ --variables tas pr \
173
+ --output results/report.html \
174
+ --name "Europe-2000-2020"
175
+
176
+ # List available metrics
177
+ climval list-metrics
178
+
179
+ # List model presets
180
+ climval list-presets
181
+
182
+ # Inspect a preset
183
+ climval info --model era5
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Metrics
189
+
190
+ | Metric | Name | Direction | Reference |
191
+ |--------|------|-----------|-----------|
192
+ | Root Mean Square Error | `rmse` | ↓ lower better | — |
193
+ | Mean Absolute Error | `mae` | ↓ lower better | — |
194
+ | Mean Bias | `mean_bias` | ↓ lower better | — |
195
+ | Normalized RMSE | `nrmse` | ↓ lower better | — |
196
+ | Pearson Correlation | `pearson_r` | ↑ higher better | — |
197
+ | Spearman Correlation | `spearman_r` | ↑ higher better | — |
198
+ | Taylor Skill Score | `taylor_skill_score` | ↑ higher better | Taylor (2001) |
199
+ | Percentile Bias (P95) | `percentile_bias_p95` | ↓ lower better | Gleckler et al. (2008) |
200
+ | Percentile Bias (P5) | `percentile_bias_p5` | ↓ lower better | Gleckler et al. (2008) |
201
+
202
+ ### Custom metrics
203
+
204
+ ```python
205
+ from climval.metrics import BaseMetric
206
+ import numpy as np
207
+
208
+ class KGE(BaseMetric):
209
+ """Kling-Gupta Efficiency (Gupta et al., 2009)."""
210
+ name = "kge"
211
+ higher_is_better = True
212
+
213
+ def compute(self, reference, candidate, weights=None):
214
+ r = np.corrcoef(reference, candidate)[0, 1]
215
+ alpha = np.std(candidate) / np.std(reference)
216
+ beta = np.mean(candidate) / np.mean(reference)
217
+ return float(1 - np.sqrt((r - 1)**2 + (alpha - 1)**2 + (beta - 1)**2))
218
+
219
+ suite.add_metric(KGE())
220
+ ```
221
+
222
+ ---
223
+
224
+ ## Model Presets
225
+
226
+ | Preset | Type | Spatial res. | Temporal res. | Description |
227
+ |--------|------|-------------|--------------|-------------|
228
+ | `era5` | Reanalysis | ~31 km | Hourly | ECMWF ERA5 Global Reanalysis |
229
+ | `era5-land` | Reanalysis | ~9 km | Hourly | ERA5-Land High-Resolution |
230
+ | `cmip6-mpi` | GCM | ~100 km | Monthly | MPI-ESM1-2-HR (Max Planck) |
231
+ | `cmip6-hadgem` | GCM | ~100 km | Monthly | HadGEM3-GC31-LL (Met Office) |
232
+ | `cordex-eur` | RCM | ~12 km | Daily | EURO-CORDEX 0.11° |
233
+
234
+ Custom models load from any NetCDF4, CSV, or Zarr source:
235
+
236
+ ```python
237
+ from climval import load_model
238
+ from climval.models import ModelType
239
+
240
+ model = load_model(
241
+ name="MyModel-v2",
242
+ path="data/simulation.nc",
243
+ variables=["tas", "pr", "psl"],
244
+ lat_range=(50.0, 60.0),
245
+ lon_range=(10.0, 25.0),
246
+ model_type=ModelType.CUSTOM,
247
+ )
248
+ ```
249
+
250
+ ---
251
+
252
+ ## Standard Variables
253
+
254
+ Follows [CF Conventions v1.10](https://cfconventions.org/). Built-in definitions:
255
+
256
+ | CF Name | Long Name | Units |
257
+ |---------|-----------|-------|
258
+ | `tas` | Near-Surface Air Temperature | K |
259
+ | `pr` | Precipitation | kg m⁻² s⁻¹ |
260
+ | `psl` | Sea Level Pressure | Pa |
261
+ | `ua` | Eastward Wind | m s⁻¹ |
262
+ | `va` | Northward Wind | m s⁻¹ |
263
+ | `hurs` | Near-Surface Relative Humidity | % |
264
+
265
+ ---
266
+
267
+ ## Export Formats
268
+
269
+ | Format | Extension | Use case |
270
+ |--------|-----------|----------|
271
+ | JSON | `.json` | Machine-readable, pipeline integration |
272
+ | HTML | `.html` | Self-contained report, sharing |
273
+ | Markdown | `.md` | GitHub/GitLab, documentation |
274
+
275
+ ---
276
+
277
+ ## Architecture
278
+
279
+ ```
280
+ climval/
281
+ ├── core/
282
+ │ ├── loader.py # Model loader with preset registry
283
+ │ ├── suite.py # BenchmarkSuite orchestrator
284
+ │ └── report.py # BenchmarkReport + multi-format export
285
+ ├── metrics/
286
+ │ └── stats.py # All metric implementations + registry
287
+ ├── models/
288
+ │ └── schema.py # Typed data models (CF-convention)
289
+ └── cli.py # climval CLI
290
+ ```
291
+
292
+ ---
293
+
294
+ ## Ecosystem & Prior Art
295
+
296
+ The climate model evaluation ecosystem has mature, powerful tools. `climval` is designed to complement them, not compete.
297
+
298
+ ### ESMValTool
299
+
300
+ [ESMValTool](https://www.esmvaltool.org/) is the community standard for comprehensive Earth System Model evaluation. Backed by ESA, CMIP, and a large consortium of European research institutions. If you are running **full diagnostic campaigns** against CMIP5/6 with pre-defined recipes, regridding pipelines, and multi-decadal observational datasets, ESMValTool is the right tool.
301
+
302
+ It is also a 100,000+ line codebase with a multi-day installation process, YAML-recipe configuration, and a steep learning curve for anyone outside a dedicated climate modelling team.
303
+
304
+ ### PCMDI Metrics Package (PMP)
305
+
306
+ [PMP](https://github.com/PCMDI/pcmdi_metrics), developed at Lawrence Livermore National Laboratory, provides a systematic framework for computing standardized performance metrics against observational references. Authoritative, widely cited in the literature, and complex to deploy outside a national lab environment.
307
+
308
+ ### ClimateLearn
309
+
310
+ [ClimateLearn](https://github.com/aditya-grover/climate-learn) is a Python library oriented toward machine learning pipelines for climate, providing standardized data loading and evaluation for ERA5 and CMIP6. Relevant if your workflow is ML-first.
311
+
312
+ ### Where `climval` fits
313
+
314
+ `climval` occupies a different position in the stack:
315
+
316
+ | | ESMValTool | PMP | **climval** |
317
+ |---|---|---|---|
318
+ | Installation | Complex, conda-heavy | Moderate | `pip install climval` |
319
+ | Configuration | YAML recipes | Config files | Pure Python API |
320
+ | Learning curve | Days–weeks | Days | Minutes |
321
+ | CI/CD integration | Difficult | Difficult | Native |
322
+ | Custom metrics | Recipe-based | Limited | `class MyMetric(BaseMetric)` |
323
+ | Programmatic use | Partial | Partial | First-class |
324
+ | Scope | Full diagnostic suite | Performance metrics | Composable validation |
325
+
326
+ **`climval` is the right choice when you need:**
327
+ - A reproducible validation step inside a Python pipeline or CI workflow
328
+ - A composable API to integrate climate metrics into larger systems
329
+ - Rapid prototyping, teaching, or lightweight institutional reporting
330
+ - Full programmatic control without YAML configuration or recipe management
331
+
332
+ **Use ESMValTool when you need:**
333
+ - Pre-built diagnostic recipes from the CMIP community
334
+ - Automated regridding and unit harmonization across large multi-model ensembles
335
+ - Figures and diagnostics that conform to IPCC or CMIP reporting standards
336
+
337
+ These tools solve different problems at different layers of the stack. `climval` is intentionally scoped to be the layer you can `import` in three lines.
338
+
339
+ ---
340
+
341
+ ## References
342
+
343
+ - Gleckler, P. J., Taylor, K. E., & Doutriaux, C. (2008). Performance metrics for
344
+ climate models. *Journal of Geophysical Research*, 113, D06104.
345
+ https://doi.org/10.1029/2007JD008972
346
+
347
+ - Taylor, K. E. (2001). Summarizing multiple aspects of model performance in a single
348
+ diagram. *Journal of Geophysical Research*, 106(D7), 7183–7192.
349
+ https://doi.org/10.1029/2000JD900719
350
+
351
+ - Gupta, H. V., Kling, H., Yilmaz, K. K., & Martinez, G. F. (2009). Decomposition
352
+ of the mean squared error and NSE: Implications for improving hydrological modelling.
353
+ *Journal of Hydrology*, 377(1–2), 80–91.
354
+ https://doi.org/10.1016/j.jhydrol.2009.08.003
355
+
356
+ ---
357
+
358
+ ## Contributing
359
+
360
+ Issues and pull requests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).
361
+
362
+ ```bash
363
+ git clone https://github.com/northflow-technologies/climval
364
+ cd climval
365
+ pip install -e ".[dev]"
366
+ pytest && ruff check . && mypy climval/
367
+ ```
368
+
369
+ ---
370
+
371
+ ## License
372
+
373
+ Apache License 2.0 — see [LICENSE](LICENSE) for details.
374
+
375
+ ---
376
+
377
+ *Built by [Northflow Technologies](https://northflow.tech)*