Skip to content

Commit bc12d8e

Browse files
Merge pull request #673 from cal-adapt/tests/new-core-convert-units
Tests/new core convert units
2 parents fbf4763 + 5e99b59 commit bc12d8e

8 files changed

Lines changed: 894 additions & 1 deletion

File tree

climakitae/core/constants.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,24 @@
6969

7070
CALISO_AREA_THRESHOLD = 100
7171

72+
# Valid unit conversion options
73+
UNIT_OPTIONS = {
74+
"K": ["K", "degC", "degF"],
75+
"degF": ["K", "degC", "degF"],
76+
"degC": ["K", "degC", "degF"],
77+
"hPa": ["Pa", "hPa", "mb", "inHg"],
78+
"Pa": ["Pa", "hPa", "mb", "inHg"],
79+
"m/s": ["m/s", "mph", "knots"],
80+
"m s-1": ["m s-1", "mph", "knots"],
81+
"[0 to 100]": ["[0 to 100]", "fraction"],
82+
"mm": ["mm", "inches"],
83+
"mm/d": ["mm/d", "inches/d"],
84+
"mm/h": ["mm/h", "inches/h"],
85+
"kg/kg": ["kg/kg", "g/kg"],
86+
"kg kg-1": ["kg kg-1", "g kg-1"],
87+
"kg m-2 s-1": ["kg m-2 s-1", "mm", "inches"],
88+
"g/kg": ["g/kg", "kg/kg"],
89+
}
7290
# Start and end years for LOCA and WRF data
7391
LOCA_START_YEAR = 1950
7492
LOCA_END_YEAR = 2100

climakitae/new_core/param_validation/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Import param validation classes ensuring they are registered."""
22

33
from .concat_param_validator import validate_concat_param
4+
from .convert_units_param_validator import validate_convert_units_param
45
from .clip_param_validator import validate_clip_param
56
from .data_param_validator import DataValidator
67
from .filter_unadjusted_models_param_validator import (
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
"""
2+
Validator for parameters provided to Convert Units Processor.
3+
"""
4+
5+
from __future__ import annotations
6+
7+
import warnings
8+
from typing import Any, Iterable
9+
10+
from climakitae.core.constants import UNIT_OPTIONS, UNSET
11+
from climakitae.new_core.param_validation.abc_param_validation import (
12+
register_processor_validator,
13+
)
14+
15+
# All supported units (flattened from UNIT_OPTIONS)
16+
ALL_SUPPORTED_UNITS = set()
17+
for unit_list in UNIT_OPTIONS.values():
18+
ALL_SUPPORTED_UNITS.update(unit_list)
19+
20+
21+
@register_processor_validator("convert_units")
22+
def validate_convert_units_param(
23+
value: str | Iterable[str],
24+
**kwargs: Any,
25+
) -> bool:
26+
"""
27+
Validate the parameters provided to the Convert Units Processor.
28+
29+
This function checks the value provided to the Convert Units Processor and ensures that it
30+
meets the expected criteria. Will raise a user warning and return false if the value
31+
is not valid.
32+
33+
Parameters
34+
----------
35+
value : str | Iterable[str]
36+
The unit(s) to convert to. Can be a single unit string or an iterable of unit strings.
37+
Valid units include temperature units (K, degC, degF), pressure units (Pa, hPa, mb, inHg),
38+
wind units (m/s, m s-1, mph, knots), precipitation units (mm, mm/d, mm/h, inches, inches/d, inches/h),
39+
moisture units (kg/kg, kg kg-1, g/kg, g kg-1), flux units (kg m-2 s-1), and relative humidity
40+
units ([0 to 100], fraction).
41+
42+
Returns
43+
-------
44+
bool
45+
True if all parameters are valid, False otherwise
46+
"""
47+
# kwargs unused but required for signature compatibility
48+
del kwargs
49+
50+
if value is UNSET:
51+
# UNSET is valid - processor will not perform any conversion
52+
return True
53+
54+
if not _check_input_types(value):
55+
return False
56+
57+
if not _check_unit_validity(value):
58+
return False
59+
60+
return True
61+
62+
63+
def _check_input_types(value: str | Iterable[str]) -> bool:
64+
"""
65+
Check if the input value has the correct type.
66+
67+
Parameters
68+
----------
69+
value : str | Iterable[str]
70+
The value to check.
71+
72+
Returns
73+
-------
74+
bool
75+
True if the input type is valid, False otherwise.
76+
"""
77+
if isinstance(value, str):
78+
return True
79+
80+
warnings.warn(
81+
"\n\nConvert Units Processor expects a string. "
82+
f"\nReceived type: {type(value)}"
83+
)
84+
return False
85+
86+
87+
def _check_unit_validity(value: str | Iterable[str]) -> bool:
88+
"""
89+
Check if the provided unit(s) are supported.
90+
91+
Parameters
92+
----------
93+
value : str | Iterable[str]
94+
The unit(s) to validate.
95+
96+
Returns
97+
-------
98+
bool
99+
True if all units are supported, False otherwise.
100+
"""
101+
units_to_check = [value] if isinstance(value, str) else list(value)
102+
103+
for unit in units_to_check:
104+
if unit not in ALL_SUPPORTED_UNITS:
105+
supported_units_str = ", ".join(sorted(ALL_SUPPORTED_UNITS))
106+
warnings.warn(
107+
f"\n\nUnsupported unit: '{unit}'. "
108+
f"\nSupported units are: {supported_units_str}"
109+
)
110+
return False
111+
112+
return True

climakitae/new_core/processors/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Initialize the processors, ensuring they get registered."""
22

33
from .concatenate import Concat
4+
from .convert_units import ConvertUnits
45
from .clip import Clip
56
from .filter_unadjusted_models import FilterUnAdjustedModels
67
from .time_slice import TimeSlice
@@ -9,6 +10,7 @@
910

1011
__all__ = [
1112
"Concat",
13+
"ConvertUnits",
1214
"Clip",
1315
"FilterUnAdjustedModels",
1416
"TimeSlice",

0 commit comments

Comments
 (0)