Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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: 2 additions & 1 deletion docs/src/whatsnew/latest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ This document explains the changes made to Iris for this release
✨ Features
===========

#. N/A
#. `@ESadek-MO`_ updated the error messages in :func:`~iris.cube.Cube.concatenate`
to better explain the error. (:pull:`6005`)


🐛 Bugs Fixed
Expand Down
44 changes: 40 additions & 4 deletions lib/iris/_concatenate.py
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,7 @@ def register(
# Check for compatible cube signatures.
cube_signature = _CubeSignature(cube)
match = self._cube_signature.match(cube_signature, error_on_mismatch)
mismatch_error_msg = None

# Check for compatible coordinate signatures.
if match:
Expand All @@ -901,17 +902,20 @@ def register(
match = candidate_axis is not None and (
candidate_axis == axis or axis is None
)
if not match:
mismatch_error_msg = (
f"Cannot find an axis to concatenate over for phenomenon "
f"{self._cube_signature.defn.name()}"
)

# Check for compatible coordinate extents.
if match:
dim_ind = self._coord_signature.dim_mapping.index(candidate_axis)
match = self._sequence(coord_signature.dim_extents[dim_ind], candidate_axis)
if error_on_mismatch and not match:
msg = f"Found cubes with overlap on concatenate axis {candidate_axis}, cannot concatenate overlapping cubes"
raise iris.exceptions.ConcatenateError([msg])
mismatch_error_msg = f"Found cubes with overlap on concatenate axis {candidate_axis}, cannot concatenate overlapping cubes"
elif not match:
msg = f"Found cubes with overlap on concatenate axis {candidate_axis}, skipping concatenation for these cubes"
warnings.warn(msg, category=iris.warnings.IrisUserWarning)
mismatch_error_msg = f"Found cubes with overlap on concatenate axis {candidate_axis}, skipping concatenation for these cubes"

# Check for compatible AuxCoords.
if match:
Expand All @@ -926,6 +930,12 @@ def register(
or candidate_axis not in coord_b.dims
):
if not coord_a == coord_b:
mismatch_error_msg = (
"Auxiliary coordinates differ for phenomenon"
f" {self._cube_signature.defn.name()}:\n"
f"a: {coord_a}\n"
f"b: {coord_b}"
)
match = False

# Check for compatible CellMeasures.
Expand All @@ -941,6 +951,12 @@ def register(
or candidate_axis not in coord_b.dims
):
if not coord_a == coord_b:
mismatch_error_msg = (
"Cell measures differ for phenomenon"
f" {self._cube_signature.defn.name()}:\n"
f"a: {coord_a}\n"
f"b: {coord_b}"
)
match = False

# Check for compatible AncillaryVariables.
Expand All @@ -956,6 +972,12 @@ def register(
or candidate_axis not in coord_b.dims
):
if not coord_a == coord_b:
mismatch_error_msg = (
"Ancillary variables differ for phenomenon"
f" {self._cube_signature.defn.name()}:\n"
f"a: {coord_a}\n"
f"b: {coord_b}"
)
match = False

# Check for compatible derived coordinates.
Expand All @@ -971,6 +993,12 @@ def register(
or candidate_axis not in coord_b.dims
):
if not coord_a == coord_b:
mismatch_error_msg = (
"Derived coordinates differ for phenomenon"
f" {self._cube_signature.defn.name()}:\n"
f"a: {coord_a}\n"
f"b: {coord_b}"
)
match = False

if match:
Expand All @@ -991,6 +1019,14 @@ def register(
if existing_order == _CONSTANT and this_order != _CONSTANT:
self._coord_signature.dim_order[dim_ind] = this_order

if mismatch_error_msg:
if not match and error_on_mismatch:
raise iris.exceptions.ConcatenateError([mismatch_error_msg])
elif not match:
warnings.warn(
mismatch_error_msg, category=iris.warnings.IrisUserWarning
)

return match

def _add_skeleton(self, coord_signature, data):
Expand Down
39 changes: 39 additions & 0 deletions lib/iris/tests/unit/concatenate/test_concatenate.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,45 @@ def test_dim_coords_overlap_message(self):
_ = concatenate([cube_1, cube_2], True)


class TestNonMetadataMessages(TestMessages):
def setUp(self):
super().setUp()
cube_2 = self.cube.copy()
cube_2.coord("time").points = cube_2.coord("time").points + 2
self.cube_2 = cube_2

def test_dim_coords_same_message(self):
pass

def test_aux_coords_diff_message(self):
self.cube_2.coord("foo").points = [3, 4, 5]

exc_regexp = "Auxiliary coordinates differ for phenomenon * "
with self.assertRaisesRegex(ConcatenateError, exc_regexp):
_ = concatenate([self.cube, self.cube_2], True)

def test_cell_measures_diff_message(self):
self.cube_2.cell_measure("bar").data = [3, 4, 5]

exc_regexp = "Cell measures differ for phenomenon * "
with self.assertRaisesRegex(ConcatenateError, exc_regexp):
_ = concatenate([self.cube, self.cube_2], True)

def test_ancillary_variable_diff_message(self):
self.cube_2.ancillary_variable("baz").data = [3, 4, 5]

exc_regexp = "Ancillary variables differ for phenomenon * "
with self.assertRaisesRegex(ConcatenateError, exc_regexp):
_ = concatenate([self.cube, self.cube_2], True)

def test_derived_coords_diff_message(self):
self.cube_2.aux_factories[0].update(self.cube_2.coord("sigma"), None)

exc_regexp = "Derived coordinates differ for phenomenon * "
with self.assertRaisesRegex(ConcatenateError, exc_regexp):
_ = concatenate([self.cube, self.cube_2], True)


class TestOrder(tests.IrisTest):
def _make_cube(self, points, bounds=None):
nx = 4
Expand Down