Skip to content

Commit

Permalink
Use special unit conversion for derived variables (#2471)
Browse files Browse the repository at this point in the history
  • Loading branch information
bouweandela committed Jul 2, 2024
1 parent d472381 commit 60aec3e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 10 deletions.
17 changes: 9 additions & 8 deletions esmvalcore/preprocessor/_derive/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import iris

from esmvalcore.preprocessor._units import convert_units

logger = logging.getLogger(__name__)


Expand All @@ -18,7 +20,6 @@ def _get_all_derived_variables():
dict
All derived variables with `short_name` (keys) and the associated
python classes (values).
"""
derivers = {}
for path in Path(__file__).parent.glob('[a-z]*.py'):
Expand Down Expand Up @@ -50,7 +51,6 @@ def get_required(short_name, project):
-------
list
List of dictionaries (including at least the key `short_name`).
"""
if short_name.lower() not in ALL_DERIVED_VARIABLES:
raise NotImplementedError(
Expand Down Expand Up @@ -82,7 +82,6 @@ def derive(cubes, short_name, long_name, units, standard_name=None):
-------
iris.cube.Cube
The new derived variable.
"""
if short_name == cubes[0].var_name:
return cubes[0]
Expand Down Expand Up @@ -116,11 +115,13 @@ def derive(cubes, short_name, long_name, units, standard_name=None):
"'%s', automatically setting them to '%s'. This might lead to "
"incorrect data", short_name, cube.units, units)
cube.units = units
elif cube.units.is_convertible(units):
cube.convert_units(units)
else:
raise ValueError(
f"Units '{cube.units}' after executing derivation script of "
f"'{short_name}' cannot be converted to target units '{units}'")
try:
convert_units(cube, units)
except ValueError as exc:
raise ValueError(
f"Units '{cube.units}' after executing derivation script of "
f"'{short_name}' cannot be converted to target units '{units}'"
) from exc

return cube
6 changes: 4 additions & 2 deletions tests/integration/preprocessor/_derive/test_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ def patched_derive(mocker):
mocker.patch.object(_derive, 'logger', autospec=True)


def mock_all_derived_variables(returned_units):
def mock_all_derived_variables(returned_units, fail_unit_conversion=False):
"""Mock the :obj:`dict` containing all derived variables accordingly."""
cube = mock.create_autospec(Cube, instance=True)
cube.units = returned_units
if fail_unit_conversion:
cube.convert_units.side_effect = [ValueError]
calculate_function = mock.Mock(return_value=cube)
derived_var = mock.Mock(name='DerivedVariable')
derived_var.return_value.calculate = calculate_function
Expand Down Expand Up @@ -127,7 +129,7 @@ def test_check_units_convertible(mock_cubes):
@pytest.mark.usefixtures("patched_derive")
def test_check_units_fail(mock_cubes):
"""Test units after derivation if derivation scripts returns None."""
mock_all_derived_variables(Unit('kg'))
mock_all_derived_variables(Unit('kg'), fail_unit_conversion=True)
with pytest.raises(ValueError) as err:
derive(mock_cubes, SHORT_NAME, mock.sentinel.long_name, 'm',
standard_name=mock.sentinel.standard_name)
Expand Down

0 comments on commit 60aec3e

Please sign in to comment.