From daa2b27382b916d21b88e83867bb17918db5acec Mon Sep 17 00:00:00 2001 From: James Warner Date: Thu, 30 Jan 2025 17:37:46 +0000 Subject: [PATCH 1/3] fix coord and units --- src/CSET/operators/read.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/CSET/operators/read.py b/src/CSET/operators/read.py index 19aedbe80..e522f81d4 100644 --- a/src/CSET/operators/read.py +++ b/src/CSET/operators/read.py @@ -228,7 +228,7 @@ def callback(cube: iris.cube.Cube, field, filename: str): _lfric_time_coord_fix_callback(cube, field, filename) _longitude_fix_callback(cube, field, filename) _fix_spatial_coord_name_callback(cube) - _fix_pressure_coord_name_callback(cube) + _fix_pressure_coord_callback(cube) return callback @@ -408,20 +408,26 @@ def _fix_spatial_coord_name_callback(cube: iris.cube.Cube): cube.coord(x_name).rename("grid_longitude") -def _fix_pressure_coord_name_callback(cube: iris.cube.Cube): - """Rename pressure_level coordinate to pressure if it exists. +def _fix_pressure_coord_callback(cube: iris.cube.Cube): + """Rename pressure coordinate to 'pressure' if it exists and ensure hPa units. This problem was raised because the AIFS model data from ECMWF defines the pressure coordinate with the name 'pressure_level' rather - than compliant CF coordinate names + than compliant CF coordinate names. + + Additionally, set the units of pressure to be hPa. """ # We only want to modify instances where the coordinate system is actually # latitude/longitude, and not touch the cube if the coordinate system is say # meters. for coord in cube.dim_coords: - if coord.name() == "pressure_level": + if coord.name() in ["pressure_level", "pressure_levels"]: coord.rename("pressure") + for coord in cube.dim_coords: + if coord.name() == "pressure": + cube.coord("pressure").convert_units("hPa") + def _check_input_files(input_paths: list[str], filename_pattern: str) -> list[Path]: """Get an iterable of files to load, and check that they all exist. From 3399a628b899e36f6b0a548a608910d5def20226 Mon Sep 17 00:00:00 2001 From: James Warner Date: Thu, 30 Jan 2025 17:51:52 +0000 Subject: [PATCH 2/3] add tests --- tests/operators/test_read.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/operators/test_read.py b/tests/operators/test_read.py index 03b2b6080..a5c15b61a 100644 --- a/tests/operators/test_read.py +++ b/tests/operators/test_read.py @@ -245,17 +245,25 @@ def test_lfric_time_coord_fix_callback_no_time(): assert len(cube.coords("time")) == 0 -def test_pressure_coord_fix_callback(): +def test_pressure_coord_name_fix_callback(): """Check that pressure_level is renamed to pressure if it exists.""" cube = iris.load_cube("tests/test_data/transect_test_umpl.nc") cube.coord("pressure").rename("pressure_level") - read._fix_pressure_coord_name_callback(cube) + read._fix_pressure_coord_callback(cube) assert ( repr(cube.coords()) == "[, , , , , ]" ) +def test_pressure_coord_unit_fix_callback(): + """Check that pressure level units are hPa.""" + cube = iris.load_cube("tests/test_data/transect_test_umpl.nc") + cube.coord("pressure").convert_units("Pa") + read._fix_pressure_coord_callback(cube) + assert repr(str(cube.coord("pressure").units)) == "'hPa'" + + def test_spatial_coord_rename_callback(): """Check that spatial coord gets renamed if it is not grid_latitude.""" # This cube contains 'latitude' and 'longitude' From 9f5cb13c071e84b2cc96cb6467b25d449b8e4979 Mon Sep 17 00:00:00 2001 From: James Warner Date: Tue, 4 Feb 2025 12:50:51 +0000 Subject: [PATCH 3/3] apply suggestions from code review --- src/CSET/operators/read.py | 20 ++++++++++---------- tests/operators/test_read.py | 15 ++++++--------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/CSET/operators/read.py b/src/CSET/operators/read.py index e522f81d4..87ae598f0 100644 --- a/src/CSET/operators/read.py +++ b/src/CSET/operators/read.py @@ -409,24 +409,24 @@ def _fix_spatial_coord_name_callback(cube: iris.cube.Cube): def _fix_pressure_coord_callback(cube: iris.cube.Cube): - """Rename pressure coordinate to 'pressure' if it exists and ensure hPa units. + """Rename pressure coordinate to "pressure" if it exists and ensure hPa units. This problem was raised because the AIFS model data from ECMWF - defines the pressure coordinate with the name 'pressure_level' rather + defines the pressure coordinate with the name "pressure_level" rather than compliant CF coordinate names. - Additionally, set the units of pressure to be hPa. + Additionally, set the units of pressure to be hPa to be consistent with the UM, + and approach the coordinates in a unified way. """ - # We only want to modify instances where the coordinate system is actually - # latitude/longitude, and not touch the cube if the coordinate system is say - # meters. for coord in cube.dim_coords: - if coord.name() in ["pressure_level", "pressure_levels"]: + coord_name = coord.name() + + if coord_name in ["pressure_level", "pressure_levels"]: coord.rename("pressure") - for coord in cube.dim_coords: - if coord.name() == "pressure": - cube.coord("pressure").convert_units("hPa") + if coord_name == "pressure": + if cube.coord("pressure").units != "hPa": + cube.coord("pressure").convert_units("hPa") def _check_input_files(input_paths: list[str], filename_pattern: str) -> list[Path]: diff --git a/tests/operators/test_read.py b/tests/operators/test_read.py index a5c15b61a..2c5a72b23 100644 --- a/tests/operators/test_read.py +++ b/tests/operators/test_read.py @@ -245,23 +245,20 @@ def test_lfric_time_coord_fix_callback_no_time(): assert len(cube.coords("time")) == 0 -def test_pressure_coord_name_fix_callback(): +def test_pressure_coord_name_fix_callback(transect_source_cube): """Check that pressure_level is renamed to pressure if it exists.""" - cube = iris.load_cube("tests/test_data/transect_test_umpl.nc") + cube = transect_source_cube.copy() cube.coord("pressure").rename("pressure_level") read._fix_pressure_coord_callback(cube) - assert ( - repr(cube.coords()) - == "[, , , , , ]" - ) + assert "pressure" in [coord.name() for coord in cube.coords()] -def test_pressure_coord_unit_fix_callback(): +def test_pressure_coord_unit_fix_callback(transect_source_cube): """Check that pressure level units are hPa.""" - cube = iris.load_cube("tests/test_data/transect_test_umpl.nc") + cube = transect_source_cube.copy() cube.coord("pressure").convert_units("Pa") read._fix_pressure_coord_callback(cube) - assert repr(str(cube.coord("pressure").units)) == "'hPa'" + assert cube.coord("pressure").units == "hPa" def test_spatial_coord_rename_callback():