From b756210907adddcad9b3621690586cc4f6084b1a Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Fri, 25 Oct 2024 17:21:02 +0100 Subject: [PATCH] fix tests and example --- lib/iris/fileformats/cf.py | 74 ++++++------------- .../unit/fileformats/cf/test_CFReader.py | 28 +++++-- 2 files changed, 45 insertions(+), 57 deletions(-) diff --git a/lib/iris/fileformats/cf.py b/lib/iris/fileformats/cf.py index 0b67a58c2e..35bb64587d 100644 --- a/lib/iris/fileformats/cf.py +++ b/lib/iris/fileformats/cf.py @@ -16,6 +16,7 @@ from abc import ABCMeta, abstractmethod from collections.abc import Iterable, MutableMapping +import contextlib import os import re from typing import ClassVar @@ -1418,72 +1419,43 @@ def _translate(self): for cf_var in formula_terms.values(): for cf_root, cf_term in cf_var.cf_terms_by_root.items(): - - - # Ignore formula terms owned by a bounds variable. - # if cf_root not in self.cf_group.bounds: - # cf_name = cf_var.cf_name - # if cf_var.cf_name not in self.cf_group: - # self.cf_group[cf_name] = CFAuxiliaryCoordinateVariable( - # cf_name, cf_var.cf_data - # ) - # self.cf_group[cf_name].add_formula_term(cf_root, cf_term) - - if cf_root not in self.cf_group.bounds: - - # Check if cf_root has a bounds attribute. - if cf_root in self.cf_group.coordinates: - # Need to generalise this for if it's a dim or aux coord. - bounds_name = getattr( - self.cf_group.coordinates[cf_root], "bounds", None + bounds_name = None + cf_root_coord = self.cf_group.coordinates.get(cf_root) + with contextlib.suppress(AttributeError): + # Copes with cf_root_coord not existing, OR not having + # `bounds` attribute. + bounds_name = cf_root_coord.bounds + if bounds_name is not None: + # This will error if more or less than 1 variable is found. + (bounds_var,) = [ + f + for f in formula_terms.values() + if f.cf_terms_by_root.get(bounds_name) == cf_term + ] + if bounds_var != cf_var: + cf_var.bounds = bounds_var.cf_name + new_var = CFBoundaryVariable( + bounds_var.cf_name, bounds_var.cf_data ) - if bounds_name is not None: - form_terms = getattr( - self.cf_group.coordinates[cf_root], "formula_terms" - ) - form_terms = form_terms.replace(":", "") - form_terms = form_terms.split(" ") - example_dict = {"a": "A", "b": "B", "ps": "PS", "p0": "P0", "orog": "orography"} - for cf_vari in formula_terms.values(): - for ( - cf_roots, - cf_terms, - ) in cf_vari.cf_terms_by_root.items(): - if cf_terms == cf_term: - if ( - cf_roots in self.cf_group.bounds - and cf_roots == bounds_name - ): - if cf_terms in form_terms: - to_attach_to = example_dict[cf_terms] - attach_from = cf_vari.cf_name - if ( - to_attach_to.lower() - != attach_from.lower() - ): - self.cf_group[cf_vari.cf_name] = CFBoundaryVariable(cf_vari.cf_name, cf_vari.cf_data) - cf_var.bounds = cf_vari.cf_name - + new_var.add_formula_term(bounds_name, cf_term) + self.cf_group[bounds_var.cf_name] = new_var + if cf_root not in self.cf_group.bounds: cf_name = cf_var.cf_name if cf_var.cf_name not in self.cf_group: - new_var = CFAuxiliaryCoordinateVariable( - cf_name, cf_var.cf_data - ) + new_var = CFAuxiliaryCoordinateVariable(cf_name, cf_var.cf_data) if hasattr(cf_var, "bounds"): new_var.bounds = cf_var.bounds + new_var.add_formula_term(cf_root, cf_term) self.cf_group[cf_name] = new_var - self.cf_group[cf_name].add_formula_term(cf_root, cf_term) # Determine the CF data variables. data_variable_names = ( set(netcdf_variable_names) - self.cf_group.non_data_variable_names ) - print("name") for name in data_variable_names: self.cf_group[name] = CFDataVariable(name, self._dataset.variables[name]) - print("name") def _build_cf_groups(self): """Build the first order relationships between CF-netCDF variables.""" diff --git a/lib/iris/tests/unit/fileformats/cf/test_CFReader.py b/lib/iris/tests/unit/fileformats/cf/test_CFReader.py index 01e6f062b4..f84ed5766b 100644 --- a/lib/iris/tests/unit/fileformats/cf/test_CFReader.py +++ b/lib/iris/tests/unit/fileformats/cf/test_CFReader.py @@ -174,9 +174,6 @@ def test_create_formula_terms(self): self.assertEqual(set(group.keys()), set(aux_coordinates)) for name in aux_coordinates: self.assertIs(group[name].cf_data, getattr(self, name)) - # Check all the auxiliary coordinates are formula terms. - formula_terms = cf_group.formula_terms - self.assertEqual(set(group.items()), set(formula_terms.items())) # Check there are three bounds. group = cf_group.bounds self.assertEqual(len(group), 3) @@ -184,6 +181,17 @@ def test_create_formula_terms(self): self.assertEqual(set(group.keys()), set(bounds)) for name in bounds: self.assertEqual(group[name].cf_data, getattr(self, name)) + # Check the formula terms contains all expected terms + formula_terms = cf_group.formula_terms + expected_keys = ["delta", "sigma", "orography", "delta_bnds", "sigma_bnds"] + expected_group = { + k: v + for k, v in dict( + **cf_group.auxiliary_coordinates, **cf_group.bounds + ).items() + if k in expected_keys + } + self.assertEqual(set(expected_group.items()), set(formula_terms.items())) class Test_build_cf_groups__formula_terms(tests.IrisTest): @@ -273,11 +281,9 @@ def test_associate_formula_terms_with_data_variable(self): self.assertEqual(len(group), 5) aux_coordinates = ["delta", "sigma", "orography", "x", "y"] self.assertEqual(set(group.keys()), set(aux_coordinates)) + formula_terms = cf_group.formula_terms for name in aux_coordinates: self.assertIs(group[name].cf_data, getattr(self, name)) - # Check all the auxiliary coordinates are formula terms. - formula_terms = cf_group.formula_terms - self.assertTrue(set(formula_terms.items()).issubset(list(group.items()))) # Check the terms by root. for name, term in zip(aux_coordinates, ["a", "b", "orog"]): self.assertEqual( @@ -294,6 +300,16 @@ def test_associate_formula_terms_with_data_variable(self): aux_coord_group[name_bnds].cf_data, getattr(self, name_bnds), ) + # Check the formula terms contains all expected terms + expected_keys = ["delta", "sigma", "orography", "delta_bnds", "sigma_bnds"] + expected_group = { + k: v + for k, v in dict( + **cf_group.auxiliary_coordinates, **cf_group.bounds + ).items() + if k in expected_keys + } + self.assertEqual(set(expected_group.items()), set(formula_terms.items())) def test_promote_reference(self): with mock.patch(