From c1badbdf77d6e85c2fabe3dd99ea4c0dc183d027 Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Wed, 26 Jun 2024 11:29:06 +0200 Subject: [PATCH 1/2] Added fix for AIRS-2-0 --- esmvalcore/cmor/_fixes/obs4mips/airs_2_0.py | 35 +++++++++++++++++++ .../cmor/_fixes/obs4mips/test_airs_2_0.py | 30 ++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 esmvalcore/cmor/_fixes/obs4mips/airs_2_0.py create mode 100644 tests/integration/cmor/_fixes/obs4mips/test_airs_2_0.py diff --git a/esmvalcore/cmor/_fixes/obs4mips/airs_2_0.py b/esmvalcore/cmor/_fixes/obs4mips/airs_2_0.py new file mode 100644 index 0000000000..b8eab7b711 --- /dev/null +++ b/esmvalcore/cmor/_fixes/obs4mips/airs_2_0.py @@ -0,0 +1,35 @@ +"""Fixes for obs4MIPs dataset AIRS-2-0.""" +import dask.array as da + +from ..fix import Fix + + +class Hur(Fix): + """Fixes for hur.""" + + def fix_metadata(self, cubes): + """Fix metadata. + + Convert units from `1` to `%` and remove `valid_range` attribute. + + Parameters + ---------- + cubes: iris.cube.CubeList + Input cubes. + + Returns + ------- + iris.cube.CubeList + Fixed cubes. + + """ + for cube in cubes: + # Put information from valid_range into mask and remove the + # attribute (otherwise this will cause problems after reloading the + # data with different units) + valid_range = cube.attributes['valid_range'] + cube.data = da.ma.masked_outside(cube.core_data(), *valid_range) + cube.attributes.pop('valid_range', None) + + cube.convert_units('%') + return cubes diff --git a/tests/integration/cmor/_fixes/obs4mips/test_airs_2_0.py b/tests/integration/cmor/_fixes/obs4mips/test_airs_2_0.py new file mode 100644 index 0000000000..57eaf1ed9c --- /dev/null +++ b/tests/integration/cmor/_fixes/obs4mips/test_airs_2_0.py @@ -0,0 +1,30 @@ +"""Test AIRS-2-0 fixes.""" +import dask.array as da +import numpy as np +from iris.cube import Cube, CubeList + +from esmvalcore.cmor.fix import fix_metadata + + +def test_fix_metadata_hur(): + """Test ``fix_metadata`` for hur.""" + cubes = CubeList([ + Cube( + da.from_array([-0.1, 0.2, 1.2, 1.7]), + var_name='hur', + units='1', + attributes={'valid_range': [0.0, 1.5]}, + ), + ]) + + fixed_cubes = fix_metadata( + cubes, 'hur', 'obs4MIPs', 'AIRS-2-0', 'Amon', check_level=5, + ) + + assert len(fixed_cubes) == 1 + fixed_cube = fixed_cubes[0] + assert fixed_cube.units == '%' + assert fixed_cube.has_lazy_data() + expected_data = np.ma.masked_invalid([np.nan, 20.0, 120.0, np.nan]) + np.testing.assert_allclose(fixed_cube.data.mask, expected_data.mask) + np.testing.assert_allclose(fixed_cube.data, expected_data) From 5d7c05c04721821f87af8d421c9a812898debe95 Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Wed, 26 Jun 2024 11:34:55 +0200 Subject: [PATCH 2/2] Also check attribute --- tests/integration/cmor/_fixes/obs4mips/test_airs_2_0.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/cmor/_fixes/obs4mips/test_airs_2_0.py b/tests/integration/cmor/_fixes/obs4mips/test_airs_2_0.py index 57eaf1ed9c..9ba4603f8c 100644 --- a/tests/integration/cmor/_fixes/obs4mips/test_airs_2_0.py +++ b/tests/integration/cmor/_fixes/obs4mips/test_airs_2_0.py @@ -24,6 +24,7 @@ def test_fix_metadata_hur(): assert len(fixed_cubes) == 1 fixed_cube = fixed_cubes[0] assert fixed_cube.units == '%' + assert fixed_cube.attributes == {} assert fixed_cube.has_lazy_data() expected_data = np.ma.masked_invalid([np.nan, 20.0, 120.0, np.nan]) np.testing.assert_allclose(fixed_cube.data.mask, expected_data.mask)