diff --git a/changelog/7198.internal.rst b/changelog/7198.internal.rst new file mode 100644 index 0000000000..aa0f1af23e --- /dev/null +++ b/changelog/7198.internal.rst @@ -0,0 +1,2 @@ +:user:`01luyicheng` added unit tests for :meth:`~iris.cube.Cube.coord_dims`. +(:issue:`4552`) diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index d91c7e81c0..560aa5e650 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -3989,3 +3989,81 @@ def test_with_data(self): def test_without_data(self): cube = Cube(data=None, shape=self.shape) assert cube.is_dataless() + + +class Test_coord_dims: + """Tests for :meth:`iris.cube.Cube.coord_dims`.""" + + @pytest.fixture(autouse=True) + def _setup(self): + # Build a 3D cube with dimension coordinates and auxiliary + # coordinates spanning one and multiple dimensions. + + # Set-up the cube. + data = np.arange(24).reshape(2, 3, 4) + cube = Cube(data) + + # Set-up the DimCoords and add them to the cube. + x_coord = DimCoord(points=np.array([0, 1]), long_name="x") + y_coord = DimCoord(points=np.array([0, 1, 2]), long_name="y") + z_coord = DimCoord(points=np.array([0, 1, 2, 3]), long_name="z") + cube.add_dim_coord(x_coord, 0) + cube.add_dim_coord(y_coord, 1) + cube.add_dim_coord(z_coord, 2) + + # Set-up the AuxCoords and add them to the cube. + aux_1d = AuxCoord(points=np.array([0, 1]), long_name="aux_1d") + aux_2d = AuxCoord(points=np.arange(6).reshape(2, 3), long_name="aux_2d") + cube.add_aux_coord(aux_1d, 0) + cube.add_aux_coord(aux_2d, (0, 1)) + + # Assign them all to class variables. + self.cube = cube + self.x_coord = x_coord + self.aux_1d = aux_1d + self.aux_2d = aux_2d + + def test_dim_coord(self): + # A dimension coordinate is found by object identity. + assert self.cube.coord_dims(self.x_coord) == (0,) + + def test_string_name(self): + # A coordinate may be looked up by its string name. + assert self.cube.coord_dims("y") == (1,) + + def test_aux_coord_single_dim(self): + # An auxiliary coordinate spanning a single dimension. + assert self.cube.coord_dims(self.aux_1d) == (0,) + + def test_aux_coord_multiple_dims(self): + # An auxiliary coordinate spanning multiple dimensions. + assert self.cube.coord_dims(self.aux_2d) == (0, 1) + + def test_aux_factory(self): + # A derived coordinate provided by an aux factory. + # Dependencies for a hybrid-height derived coordinate ("altitude"). + delta = AuxCoord(points=np.array([0, 1]), long_name="delta", units="m") + sigma = AuxCoord(points=np.array([0, 1]), long_name="sigma") + orography = AuxCoord( + np.arange(12).reshape(3, 4), units="m", long_name="orography" + ) + self.cube.add_aux_coord(delta, 0) + self.cube.add_aux_coord(sigma, 0) + self.cube.add_aux_coord(orography, (1, 2)) + factory = HybridHeightFactory(delta=delta, sigma=sigma, orography=orography) + self.cube.add_aux_factory(factory) + derived_coord = factory.make_coord(self.cube.coord_dims) + assert self.cube.coord_dims(derived_coord) == (0, 1, 2) + + def test_equivalent_coord_not_instance(self): + # An equivalent coordinate (same metadata, different instance) is + # resolved via the fallback coordinate lookup. + equivalent = self.x_coord.copy() + assert equivalent is not self.x_coord + assert self.cube.coord_dims(equivalent) == (0,) + + def test_no_match_raises(self): + # A coordinate that is not on the cube and matches nothing raises. + missing = DimCoord(points=np.array([0, 1]), long_name="missing") + with pytest.raises(CoordinateNotFoundError): + self.cube.coord_dims(missing)