diff --git a/esmvalcore/cmor/check.py b/esmvalcore/cmor/check.py index 3e5a1c6f9c..6dbc0e6e4f 100644 --- a/esmvalcore/cmor/check.py +++ b/esmvalcore/cmor/check.py @@ -765,10 +765,10 @@ def _check_coord_points(self, coord_info, coord, var_name): self._cube = self._cube.intersection(lon_extent) else: new_lons = coord.core_points().copy() - self._set_range_in_0_360(new_lons) + new_lons = self._set_range_in_0_360(new_lons) if coord.bounds is not None: new_bounds = coord.bounds.copy() - self._set_range_in_0_360(new_bounds) + new_bounds = self._set_range_in_0_360(new_bounds) else: new_bounds = None new_coord = coord.copy(new_lons, new_bounds) @@ -796,10 +796,8 @@ def _check_longitude_min(self, coord, var_name): @staticmethod def _set_range_in_0_360(array): - while array.min() < 0: - array[array < 0] += 360 - while array.max() > 360: - array[array > 360] -= 360 + """Convert longitude coordinate to [0, 360].""" + return (array + 360.0) % 360.0 def _check_requested_values(self, coord, coord_info, var_name): """Check requested values.""" diff --git a/tests/unit/cmor/test_cmor_check.py b/tests/unit/cmor/test_cmor_check.py index 6935538e29..f3135558a2 100644 --- a/tests/unit/cmor/test_cmor_check.py +++ b/tests/unit/cmor/test_cmor_check.py @@ -13,8 +13,11 @@ from cf_units import Unit from esmvalcore.cmor.check import ( - CheckLevels, CMORCheck, - CMORCheckError, _get_cmor_checker) + CheckLevels, + CMORCheck, + CMORCheckError, + _get_cmor_checker, +) class VariableInfoMock: @@ -760,8 +763,7 @@ def test_non_decreasing_fix(self): cube_points = self.cube.coord('latitude').points reference = np.linspace(90, -90, 20, endpoint=True) for index in range(20): - self.assertTrue( - iris.util.approx_equal(cube_points[index], reference[index])) + np.testing.assert_allclose(cube_points[index], reference[index]) # test bounds are contiguous bounds = self.cube.coord('latitude').bounds right_bounds = bounds[:-2, 1] @@ -1113,6 +1115,21 @@ def test_hr_mip_cordex(self): assert checker(self.cube)._cmor_var.short_name == 'tas' assert checker(self.cube)._cmor_var.frequency == '3hr' + def test_set_range_in_0_360(self): + checker = _get_cmor_checker('CMIP5', 'Amon', 'tas', 'mon') + arr_in = np.array([[-120.0, 0.0, 20.0], [-1.0, 360.0, 400.0]]) + arr_exp = np.array([[240.0, 0.0, 20.0], [359.0, 0.0, 40.0]]) + arr_out = checker(self.cube)._set_range_in_0_360(arr_in) + np.testing.assert_allclose(arr_out, arr_exp) + + def test_set_range_in_0_360_lazy(self): + checker = _get_cmor_checker('CMIP5', 'Amon', 'tas', 'mon') + arr_in = da.from_array([[-120.0, 0.0, 20.0], [-1.0, 360.0, 400.0]]) + arr_exp = da.from_array([[240.0, 0.0, 20.0], [359.0, 0.0, 40.0]]) + arr_out = checker(self.cube)._set_range_in_0_360(arr_in) + self.assertTrue(isinstance(arr_out, da.core.Array)) + np.testing.assert_allclose(arr_out.compute(), arr_exp.compute()) + def _check_fails_on_data(self): checker = CMORCheck(self.cube, self.var_info) checker.check_metadata()