cavapy 2.1.3__tar.gz → 2.1.4__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.
- {cavapy-2.1.3 → cavapy-2.1.4}/PKG-INFO +7 -1
- {cavapy-2.1.3 → cavapy-2.1.4}/README.md +6 -0
- {cavapy-2.1.3 → cavapy-2.1.4}/cavapy/cava_download.py +38 -31
- {cavapy-2.1.3 → cavapy-2.1.4}/cavapy/cavapy.py +19 -0
- {cavapy-2.1.3 → cavapy-2.1.4}/pyproject.toml +1 -1
- {cavapy-2.1.3 → cavapy-2.1.4}/LICENSE +0 -0
- {cavapy-2.1.3 → cavapy-2.1.4}/cavapy/__init__.py +0 -0
- {cavapy-2.1.3 → cavapy-2.1.4}/cavapy/cava_bias.py +0 -0
- {cavapy-2.1.3 → cavapy-2.1.4}/cavapy/cava_config.py +0 -0
- {cavapy-2.1.3 → cavapy-2.1.4}/cavapy/cava_plot.py +0 -0
- {cavapy-2.1.3 → cavapy-2.1.4}/cavapy/cava_validation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cavapy
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.4
|
|
4
4
|
Summary: CAVA Python package. Retrive climate data.
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -77,6 +77,12 @@ A single `get_climate_data()` call orchestrates a full pipeline:
|
|
|
77
77
|
| **Bias correction** | ERA5 is automatically fetched as the reference; EQM is trained and applied — no external tools needed |
|
|
78
78
|
| **Domain validation** | If your bounding box falls outside the chosen CORDEX domain, a corrected domain is suggested |
|
|
79
79
|
|
|
80
|
+
Unit conversion is enabled by default for backward compatibility. Pass
|
|
81
|
+
`convert_units=False` to keep the values and `units` metadata provided by the
|
|
82
|
+
source (for example, temperature in kelvin). This option cannot be combined
|
|
83
|
+
with `bias_correction=True`, because raw ERA5 and CORDEX units are not directly
|
|
84
|
+
compatible for every variable.
|
|
85
|
+
|
|
80
86
|
---
|
|
81
87
|
|
|
82
88
|
## Data Coverage
|
|
@@ -47,6 +47,12 @@ A single `get_climate_data()` call orchestrates a full pipeline:
|
|
|
47
47
|
| **Bias correction** | ERA5 is automatically fetched as the reference; EQM is trained and applied — no external tools needed |
|
|
48
48
|
| **Domain validation** | If your bounding box falls outside the chosen CORDEX domain, a corrected domain is suggested |
|
|
49
49
|
|
|
50
|
+
Unit conversion is enabled by default for backward compatibility. Pass
|
|
51
|
+
`convert_units=False` to keep the values and `units` metadata provided by the
|
|
52
|
+
source (for example, temperature in kelvin). This option cannot be combined
|
|
53
|
+
with `bias_correction=True`, because raw ERA5 and CORDEX units are not directly
|
|
54
|
+
compatible for every variable.
|
|
55
|
+
|
|
50
56
|
---
|
|
51
57
|
|
|
52
58
|
## Data Coverage
|
|
@@ -242,6 +242,7 @@ def _climate_data_for_variable(
|
|
|
242
242
|
bias_correction: bool,
|
|
243
243
|
historical: bool,
|
|
244
244
|
remote: bool,
|
|
245
|
+
convert_units: bool = True,
|
|
245
246
|
dataset: str = "CORDEX-CORE",
|
|
246
247
|
retry_log_level: int = logging.WARNING,
|
|
247
248
|
) -> xr.DataArray:
|
|
@@ -262,6 +263,7 @@ def _climate_data_for_variable(
|
|
|
262
263
|
gcm=gcm,
|
|
263
264
|
rcm=rcm,
|
|
264
265
|
rcp=rcp,
|
|
266
|
+
convert_units=convert_units,
|
|
265
267
|
retry_log_level=retry_log_level,
|
|
266
268
|
)
|
|
267
269
|
|
|
@@ -292,6 +294,7 @@ def _climate_data_for_variable(
|
|
|
292
294
|
gcm=gcm,
|
|
293
295
|
rcm=rcm,
|
|
294
296
|
rcp=rcp,
|
|
297
|
+
convert_units=convert_units,
|
|
295
298
|
retry_log_level=retry_log_level,
|
|
296
299
|
)
|
|
297
300
|
downloaded_models = list(
|
|
@@ -412,6 +415,7 @@ def _download_data(
|
|
|
412
415
|
gcm: str,
|
|
413
416
|
rcm: str,
|
|
414
417
|
rcp: str,
|
|
418
|
+
convert_units: bool = True,
|
|
415
419
|
retry_log_level: int = logging.WARNING,
|
|
416
420
|
) -> xr.DataArray:
|
|
417
421
|
"""Download a dataset, subset it to the bbox, and perform unit/calendar handling."""
|
|
@@ -556,35 +560,36 @@ def _download_data(
|
|
|
556
560
|
else:
|
|
557
561
|
raise
|
|
558
562
|
|
|
559
|
-
if
|
|
560
|
-
if
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
563
|
+
if convert_units:
|
|
564
|
+
if obs:
|
|
565
|
+
if var in ["t2mx", "t2mn", "t2m"]:
|
|
566
|
+
ds_cropped -= 273.15 # Convert from Kelvin to Celsius
|
|
567
|
+
ds_cropped.attrs["units"] = "°C"
|
|
568
|
+
elif var == "tp":
|
|
569
|
+
ds_cropped *= 1000 # Convert precipitation
|
|
570
|
+
ds_cropped.attrs["units"] = "mm"
|
|
571
|
+
elif var == "ssrd":
|
|
572
|
+
ds_cropped /= 86400 # Convert from J/m^2 to W/m^2
|
|
573
|
+
ds_cropped.attrs["units"] = "W m-2"
|
|
574
|
+
elif var == "sfcwind":
|
|
575
|
+
ds_cropped = ds_cropped * (
|
|
576
|
+
4.87 / np.log((67.8 * 10) - 5.42)
|
|
577
|
+
) # Convert wind speed from 10 m to 2 m
|
|
578
|
+
ds_cropped.attrs["units"] = "m s-1"
|
|
579
|
+
else:
|
|
580
|
+
if variable in ["tas", "tasmax", "tasmin"]:
|
|
581
|
+
ds_cropped -= 273.15 # Convert from Kelvin to Celsius
|
|
582
|
+
ds_cropped.attrs["units"] = "°C"
|
|
583
|
+
elif variable == "pr":
|
|
584
|
+
ds_cropped *= 86400 # Convert from kg m^-2 s^-1 to mm/day
|
|
585
|
+
ds_cropped.attrs["units"] = "mm"
|
|
586
|
+
elif variable == "rsds":
|
|
587
|
+
ds_cropped.attrs["units"] = "W m-2"
|
|
588
|
+
elif variable == "sfcWind":
|
|
589
|
+
ds_cropped = ds_cropped * (
|
|
590
|
+
4.87 / np.log((67.8 * 10) - 5.42)
|
|
591
|
+
) # Convert wind speed from 10 m to 2 m
|
|
592
|
+
ds_cropped.attrs["units"] = "m s-1"
|
|
588
593
|
|
|
589
594
|
# Fetch only the requested years, inside the retry loop; downstream
|
|
590
595
|
# time-core operations (interpolate_na, bias correction) need it in memory.
|
|
@@ -615,12 +620,14 @@ def _download_data(
|
|
|
615
620
|
raise last_exc
|
|
616
621
|
|
|
617
622
|
if obs:
|
|
623
|
+
unit_handling = "unit conversion" if convert_units else "source units retained"
|
|
618
624
|
log.info(
|
|
619
|
-
f"ERA5 data for {variable} has been processed:
|
|
625
|
+
f"ERA5 data for {variable} has been processed: {unit_handling} ({ds_cropped.attrs.get('units', 'unknown units')}), time selection ({min(years)}-{max(years)})"
|
|
620
626
|
)
|
|
621
627
|
else:
|
|
628
|
+
unit_handling = "unit conversion" if convert_units else "source units retained"
|
|
622
629
|
log.info(
|
|
623
|
-
f"CORDEX data for {variable} has been processed:
|
|
630
|
+
f"CORDEX data for {variable} has been processed: {unit_handling} ({ds_cropped.attrs.get('units', 'unknown units')}), calendar transformation (360-day to Gregorian), time selection ({years[0]}-{years[-1]})"
|
|
624
631
|
)
|
|
625
632
|
|
|
626
633
|
return ds_cropped
|
|
@@ -116,6 +116,7 @@ def _get_climate_data_single(
|
|
|
116
116
|
xlim: tuple[float, float] | None = None,
|
|
117
117
|
ylim: tuple[float, float] | None = None,
|
|
118
118
|
remote: bool = True,
|
|
119
|
+
convert_units: bool = True,
|
|
119
120
|
variables: list[str] | None = None,
|
|
120
121
|
num_processes: int = len(VALID_VARIABLES),
|
|
121
122
|
max_threads_per_process: int = 3,
|
|
@@ -186,6 +187,11 @@ def _get_climate_data_single(
|
|
|
186
187
|
"Cannot apply bias_correction=True when using dataset='CORDEX-CORE-BC'. "
|
|
187
188
|
"The CORDEX-CORE-BC dataset is already bias-corrected using ISIMIP methodology."
|
|
188
189
|
)
|
|
190
|
+
if bias_correction and not convert_units:
|
|
191
|
+
raise ValueError(
|
|
192
|
+
"convert_units=False cannot be used with bias_correction=True because "
|
|
193
|
+
"ERA5 and CORDEX source units are not directly compatible."
|
|
194
|
+
)
|
|
189
195
|
|
|
190
196
|
# Validate variables if provided
|
|
191
197
|
if variables is not None:
|
|
@@ -234,6 +240,7 @@ def _get_climate_data_single(
|
|
|
234
240
|
bias_correction=bias_correction,
|
|
235
241
|
historical=historical,
|
|
236
242
|
remote=remote,
|
|
243
|
+
convert_units=convert_units,
|
|
237
244
|
dataset=dataset,
|
|
238
245
|
)
|
|
239
246
|
except Exception as exc:
|
|
@@ -262,6 +269,7 @@ def _get_climate_data_single(
|
|
|
262
269
|
"bias_correction": bias_correction,
|
|
263
270
|
"historical": historical,
|
|
264
271
|
"remote": remote,
|
|
272
|
+
"convert_units": convert_units,
|
|
265
273
|
"dataset": dataset,
|
|
266
274
|
},
|
|
267
275
|
)
|
|
@@ -350,6 +358,7 @@ def get_climate_data(
|
|
|
350
358
|
xlim: tuple[float, float] | None = None,
|
|
351
359
|
ylim: tuple[float, float] | None = None,
|
|
352
360
|
remote: bool = True,
|
|
361
|
+
convert_units: bool = True,
|
|
353
362
|
variables: list[str] | None = None,
|
|
354
363
|
num_processes: int = len(VALID_VARIABLES),
|
|
355
364
|
max_threads_per_process: int = 3,
|
|
@@ -391,6 +400,8 @@ def get_climate_data(
|
|
|
391
400
|
xlim (tuple or None): Longitudinal bounds of the region of interest. Use only when country is None (default: None).
|
|
392
401
|
ylim (tuple or None): Latitudinal bounds of the region of interest. Use only when country is None (default: None).
|
|
393
402
|
remote (bool): Flag to work with remote data or not (default: True).
|
|
403
|
+
convert_units (bool): Whether to convert source data to cavapy's standard units.
|
|
404
|
+
Set to False to preserve the values and units stored by the source (default: True).
|
|
394
405
|
variables (list[str] or None): List of variables to process. Must be a subset of {VALID_VARIABLES}. If None, all variables are processed. (default: None).
|
|
395
406
|
num_processes (int): Number of processes to use, one per variable for a single combo.
|
|
396
407
|
If num_processes <= 1 or only one variable is requested, variables run sequentially.
|
|
@@ -425,6 +436,7 @@ def get_climate_data(
|
|
|
425
436
|
xlim=xlim,
|
|
426
437
|
ylim=ylim,
|
|
427
438
|
remote=remote,
|
|
439
|
+
convert_units=convert_units,
|
|
428
440
|
variables=variables,
|
|
429
441
|
num_processes=num_processes,
|
|
430
442
|
max_threads_per_process=max_threads_per_process,
|
|
@@ -452,6 +464,11 @@ def get_climate_data(
|
|
|
452
464
|
"Cannot apply bias_correction=True when using dataset='CORDEX-CORE-BC'. "
|
|
453
465
|
"The CORDEX-CORE-BC dataset is already bias-corrected using ISIMIP methodology."
|
|
454
466
|
)
|
|
467
|
+
if bias_correction and not convert_units:
|
|
468
|
+
raise ValueError(
|
|
469
|
+
"convert_units=False cannot be used with bias_correction=True because "
|
|
470
|
+
"ERA5 and CORDEX source units are not directly compatible."
|
|
471
|
+
)
|
|
455
472
|
|
|
456
473
|
if years_up_to is None:
|
|
457
474
|
raise ValueError("years_up_to is required when obs is False")
|
|
@@ -483,6 +500,7 @@ def get_climate_data(
|
|
|
483
500
|
xlim=xlim,
|
|
484
501
|
ylim=ylim,
|
|
485
502
|
remote=remote,
|
|
503
|
+
convert_units=convert_units,
|
|
486
504
|
variables=variables,
|
|
487
505
|
num_processes=num_processes,
|
|
488
506
|
max_threads_per_process=max_threads_per_process,
|
|
@@ -535,6 +553,7 @@ def get_climate_data(
|
|
|
535
553
|
"bias_correction": bias_correction,
|
|
536
554
|
"historical": historical,
|
|
537
555
|
"remote": remote,
|
|
556
|
+
"convert_units": convert_units,
|
|
538
557
|
"dataset": dataset,
|
|
539
558
|
"retry_log_level": retry_log_level,
|
|
540
559
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|