Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/src/whatsnew/latest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ This document explains the changes made to Iris for this release
#. `@melissaKG`_ upgraded Iris' tests to no longer use the deprecated
``git whatchanged`` command. (:pull:`6672`)

#. `@ukmo-ccbunney` merged functionality of ``assert_CML_approx_data`` into
``assert_CML`` via the use of a new ``approx_data`` keyword. (:pull:`6713`)


.. comment
Whatsnew author names (@github name) in alphabetical order. Note that,
Expand Down
62 changes: 34 additions & 28 deletions lib/iris/tests/_shared_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,28 +291,6 @@ def remove_test(string: str):
return str(output_path)


def assert_CML_approx_data(
request: pytest.FixtureRequest, cubes, reference_filename=None, **kwargs
):
# passes args and kwargs on to approx equal
# See result_path() Examples for how to access the ``request`` fixture.

_check_for_request_fixture(request, "assert_CML_approx_data")

if isinstance(cubes, iris.cube.Cube):
cubes = [cubes]
if reference_filename is None:
reference_filename = result_path(request, None, "cml")
reference_filename = [get_result_path(reference_filename)]
for i, cube in enumerate(cubes):
fname = list(reference_filename)
# don't want the ".cml" for the json stats file
fname[-1] = fname[-1].removesuffix(".cml")
fname[-1] += ".data.%d.json" % i
assert_data_almost_equal(cube.data, fname, **kwargs)
assert_CML(request, cubes, reference_filename, checksum=False)


def assert_CDL(
request: pytest.FixtureRequest, netcdf_filename, reference_filename=None, flags="-h"
):
Expand Down Expand Up @@ -385,14 +363,30 @@ def sort_key(line):


def assert_CML(
request: pytest.FixtureRequest, cubes, reference_filename=None, checksum=True
request: pytest.FixtureRequest,
cubes,
reference_filename=None,
checksum=True,
approx_data=False,
**kwargs,
):
"""Test that the CML for the given cubes matches the contents of
the reference file.

If the environment variable IRIS_TEST_CREATE_MISSING is
non-empty, the reference file is created if it doesn't exist.

The data payload of individual cubes is not compared unless ``checksum``
or ``approx_data`` are True.

Notes
-----
The ``approx_data`` keyword provides functionality equivalent to the
old ``assert_CML_approx_data`` function.

``**kwargs`` are passed through to :func:`assert_data_almost_equal` if
``approx_data`` is True.

Parameters
----------
request : pytest.FixtureRequest
Expand All @@ -409,6 +403,10 @@ def assert_CML(
checksum : bool, optional
When True, causes the CML to include a checksum for each
Cube's data. Defaults to True.
approx_data : bool, optional, default=False
When True, the cube's data will be compared with the reference
data and asserted to be within a specified tolerance. Implies
``checksum=False``.

"""
_check_for_request_fixture(request, "assert_CML")
Expand All @@ -417,15 +415,23 @@ def assert_CML(
cubes = [cubes]
if reference_filename is None:
reference_filename = result_path(request, None, "cml")

# Note: reference_path could be a tuple of path parts
reference_path = get_result_path(reference_filename)
if approx_data:
# compare data payload stats against known good stats
checksum = False # ensure we are not comparing data checksums
for i, cube in enumerate(cubes):
# Build the json stats filename based on CML file path:
fname = reference_path.removesuffix(".cml")
fname += f".data.{i}.json"
assert_data_almost_equal(cube.data, fname, **kwargs)
if isinstance(cubes, (list, tuple)):
xml = iris.cube.CubeList(cubes).xml(
cml = iris.cube.CubeList(cubes).xml(
checksum=checksum, order=False, byteorder=False
)
else:
xml = cubes.xml(checksum=checksum, order=False, byteorder=False)
reference_path = get_result_path(reference_filename)
_check_same(xml, reference_path)
cml = cubes.xml(checksum=checksum, order=False, byteorder=False)
_check_same(cml, reference_path)


def assert_text_file(source_filename, reference_filename, desc="text file"):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,9 @@ def test_regrid_to_same_grid(self, request):
src = self.simple_cube
res = regrid_area_weighted(src, src)
assert res == src
_shared_utils.assert_CML_approx_data(request, res, RESULT_DIR + ("simple.cml",))
_shared_utils.assert_CML(
request, res, RESULT_DIR + ("simple.cml",), approx_data=True
)

def test_equal_area_numbers(self):
# Remove coords system and units so it is no longer spherical.
Expand Down Expand Up @@ -321,8 +323,8 @@ def test_regrid_latlon_reduced_res(self, request):
# Reduce from (3, 4) to (2, 2).
dest = _subsampled_grid(src, 2, 2)
res = regrid_area_weighted(src, dest)
_shared_utils.assert_CML_approx_data(
request, res, RESULT_DIR + ("latlonreduced.cml",)
_shared_utils.assert_CML(
request, res, RESULT_DIR + ("latlonreduced.cml",), approx_data=True
)

def test_regrid_reorder_axis(self):
Expand Down Expand Up @@ -360,8 +362,8 @@ def test_regrid_lon_to_half_res(self, request):
src = self.simple_cube
dest = _resampled_grid(src, 0.5, 1.0)
res = regrid_area_weighted(src, dest)
_shared_utils.assert_CML_approx_data(
request, res, RESULT_DIR + ("lonhalved.cml",)
_shared_utils.assert_CML(
request, res, RESULT_DIR + ("lonhalved.cml",), approx_data=True
)

def test_regrid_to_non_int_frac(self, request):
Expand All @@ -370,21 +372,25 @@ def test_regrid_to_non_int_frac(self, request):
src = self.simple_cube
dest = _resampled_grid(src, 0.75, 0.67)
res = regrid_area_weighted(src, dest)
_shared_utils.assert_CML_approx_data(request, res, RESULT_DIR + ("lower.cml",))
_shared_utils.assert_CML(
request, res, RESULT_DIR + ("lower.cml",), approx_data=True
)

def test_regrid_to_higher_res(self, request):
src = self.simple_cube
frac = 3.5
dest = _resampled_grid(src, frac, frac)
res = regrid_area_weighted(src, dest)
_shared_utils.assert_CML_approx_data(request, res, RESULT_DIR + ("higher.cml",))
_shared_utils.assert_CML(
request, res, RESULT_DIR + ("higher.cml",), approx_data=True
)

def test_hybrid_height(self, request):
src = self.realistic_cube
dest = _resampled_grid(src, 0.7, 0.8)
res = regrid_area_weighted(src, dest)
_shared_utils.assert_CML_approx_data(
request, res, RESULT_DIR + ("hybridheight.cml",)
_shared_utils.assert_CML(
request, res, RESULT_DIR + ("hybridheight.cml",), approx_data=True
)

def test_missing_data(self):
Expand Down Expand Up @@ -483,8 +489,11 @@ def test_cross_section(self, request):
dest.add_dim_coord(lon, 1)
dest.add_aux_coord(src.coord("grid_latitude").copy(), None)
res = regrid_area_weighted(src, dest)
_shared_utils.assert_CML_approx_data(
request, res, RESULT_DIR + ("const_lat_cross_section.cml",)
_shared_utils.assert_CML(
request,
res,
RESULT_DIR + ("const_lat_cross_section.cml",),
approx_data=True,
)
# Constant latitude, data order [x, z]
# Using original and transposing the result should give the
Expand All @@ -493,8 +502,11 @@ def test_cross_section(self, request):
dest.transpose()
res = regrid_area_weighted(src, dest)
res.transpose()
_shared_utils.assert_CML_approx_data(
request, res, RESULT_DIR + ("const_lat_cross_section.cml",)
_shared_utils.assert_CML(
request,
res,
RESULT_DIR + ("const_lat_cross_section.cml",),
approx_data=True,
)

# Constant longitude
Expand All @@ -507,8 +519,11 @@ def test_cross_section(self, request):
dest.add_dim_coord(lat, 1)
dest.add_aux_coord(src.coord("grid_longitude").copy(), None)
res = regrid_area_weighted(src, dest)
_shared_utils.assert_CML_approx_data(
request, res, RESULT_DIR + ("const_lon_cross_section.cml",)
_shared_utils.assert_CML(
request,
res,
RESULT_DIR + ("const_lon_cross_section.cml",),
approx_data=True,
)
# Constant longitude, data order [y, z]
# Using original and transposing the result should give the
Expand All @@ -517,8 +532,11 @@ def test_cross_section(self, request):
dest.transpose()
res = regrid_area_weighted(src, dest)
res.transpose()
_shared_utils.assert_CML_approx_data(
request, res, RESULT_DIR + ("const_lon_cross_section.cml",)
_shared_utils.assert_CML(
request,
res,
RESULT_DIR + ("const_lon_cross_section.cml",),
approx_data=True,
)

def test_scalar_source_cube(self):
Expand Down
27 changes: 17 additions & 10 deletions lib/iris/tests/test_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,17 +213,17 @@ def test_weighted_mean_little(self):
if a.dtype > np.float32:
cast_data = a.data.astype(np.float32)
a.data = cast_data
_shared_utils.assert_CML_approx_data(
self.request, a, ("analysis", "weighted_mean_lat.cml")
_shared_utils.assert_CML(
self.request, a, ("analysis", "weighted_mean_lat.cml"), approx_data=True
)

b = cube.collapsed(lon_coord, iris.analysis.MEAN, weights=weights)
if b.dtype > np.float32:
cast_data = b.data.astype(np.float32)
b.data = cast_data
b.data = np.asarray(b.data)
_shared_utils.assert_CML_approx_data(
self.request, b, ("analysis", "weighted_mean_lon.cml")
_shared_utils.assert_CML(
self.request, b, ("analysis", "weighted_mean_lon.cml"), approx_data=True
)
assert b.coord("dummy").shape == (1,)

Expand All @@ -234,8 +234,8 @@ def test_weighted_mean_little(self):
if c.dtype > np.float32:
cast_data = c.data.astype(np.float32)
c.data = cast_data
_shared_utils.assert_CML_approx_data(
self.request, c, ("analysis", "weighted_mean_latlon.cml")
_shared_utils.assert_CML(
self.request, c, ("analysis", "weighted_mean_latlon.cml"), approx_data=True
)
assert c.coord("dummy").shape == (1,)

Expand Down Expand Up @@ -331,25 +331,32 @@ def _common(
_shared_utils.assert_CML(self.request, self.cube, ("analysis", original_name))

a = self.cube.collapsed("grid_latitude", aggregate)
_shared_utils.assert_CML_approx_data(
self.request, a, ("analysis", "%s_latitude.cml" % name), *args, **kwargs
_shared_utils.assert_CML(
self.request,
a,
("analysis", "%s_latitude.cml" % name),
*args,
approx_data=True,
**kwargs,
)

b = a.collapsed("grid_longitude", aggregate)
_shared_utils.assert_CML_approx_data(
_shared_utils.assert_CML(
self.request,
b,
("analysis", "%s_latitude_longitude.cml" % name),
*args,
approx_data=True,
**kwargs,
)

c = self.cube.collapsed(["grid_latitude", "grid_longitude"], aggregate)
_shared_utils.assert_CML_approx_data(
_shared_utils.assert_CML(
self.request,
c,
("analysis", "%s_latitude_longitude_1call.cml" % name),
*args,
approx_data=True,
**kwargs,
)

Expand Down
Loading
Loading