From 43604d410c9bdd9051f4e2787f2da086ce5f51ac Mon Sep 17 00:00:00 2001 From: Benjamin Adams Date: Tue, 4 Jun 2024 17:00:58 -0400 Subject: [PATCH 1/2] Implement checking of domain variables against cell_measures --- compliance_checker/cf/cf_1_9.py | 23 ++++++++++++++++++++--- compliance_checker/tests/test_cf.py | 24 +++++++++++++++++++++++- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/compliance_checker/cf/cf_1_9.py b/compliance_checker/cf/cf_1_9.py index 5e085bd7..73211e44 100644 --- a/compliance_checker/cf/cf_1_9.py +++ b/compliance_checker/cf/cf_1_9.py @@ -113,8 +113,9 @@ def check_domain_variables(self, ds: Dataset): for var in ds.get_variables_by_attributes( coordinates=lambda c: c is not None, ) - # IMPLICIT - if not var.dimensions + # IMPLICIT CONFORMANCE REQUIRED 1/4 + # all variables have dimensions attribute, but should be scalar + if var.dimensions == () ): domain_valid = TestCtx(BaseCheck.MEDIUM, self.section_titles["5.8"]) domain_valid.out_of += 1 @@ -149,7 +150,7 @@ def check_domain_variables(self, ds: Dataset): continue appendix_a_not_recommended_attrs = [] for attr_name in domain_var.ncattrs(): - if "D" not in self.appendix_a[attr_name]["attr_loc"]: + if attr_name in self.appendix_a and "D" not in self.appendix_a[attr_name]["attr_loc"]: appendix_a_not_recommended_attrs.append(attr_name) if appendix_a_not_recommended_attrs: @@ -162,6 +163,22 @@ def check_domain_variables(self, ds: Dataset): # no errors occurred domain_valid.score += 1 + + # IMPLEMENTATION CONFORMANCE 5.8 REQUIRED 4/4 + if hasattr(domain_var, "cell_measures"): + cell_measures_var_names = regex.findall(r"\b(?:area|volume):\s+(\w+)", domain_var.cell_measures) + # check exist + for var_name in cell_measures_var_names: + try: + cell_measures_variable = ds.variables[var_name] + except ValueError: + # TODO: what to do here? + continue + domain_coord_var_names = {var_like.name for var_like in domain_coord_vars} + domain_valid.assert_true(set(cell_measures_variable.dimensions).issubset(domain_coord_var_names), + "Variables named in the cell_measures attributes must have a dimensions attribute with " + "values that are a subset of the referring domain variable's dimension attribute") + results.append(domain_valid.to_result()) return results diff --git a/compliance_checker/tests/test_cf.py b/compliance_checker/tests/test_cf.py index 5e13bb7b..b9822623 100644 --- a/compliance_checker/tests/test_cf.py +++ b/compliance_checker/tests/test_cf.py @@ -3241,7 +3241,29 @@ def test_domain(self): "coordinates attribute from domain variable domain: " "xyxz, abc", ) - + # TEST CONFORMANCE 5.8 REQUIRED 4/4 + # check reference cell measures + domain_var.cell_measures = "volume: cube" + domain_var.coordinates = "lon lat depth" + # reset to good domain var coordinates + dataset.createDimension("lon", 20) + dataset.createDimension("lat", 20) + dataset.createDimension("depth", 20) + domain_var.setncattr("dimensions", "lon lat depth") + cube = dataset.createVariable("cube", "f8", ("lon", "lat", "depth")) + # OK, coordinates in cell_measures are subset of coordinates of + # referring domain variable's coordinates attribute + results = self.cf.check_domain_variables(dataset) + assert not results[0].msgs + # failing example, coordinates for cell_measures variable are no longer subset + #cube.dimensions = "virtlon virtlat height time" + domain_var.cell_measures = "volume: cube_bad" + dataset.createVariable("cube_bad", "f8", ("lon", "lat", "depth", "time")) + results = self.cf.check_domain_variables(dataset) + self.assertTrue("Variables named in the cell_measures attributes must " + "have a dimensions attribute with values that are a " + "subset of the referring domain variable's dimension " + "attribute" in results[0].msgs) del dataset dataset = MockTimeSeries() # domain should be dimensionless -- currently not an error in From e3486ad64316626550f683ed0293034c3c95f4cb Mon Sep 17 00:00:00 2001 From: Benjamin Adams Date: Tue, 4 Jun 2024 17:05:52 -0400 Subject: [PATCH 2/2] To fixup/squash: Remove unused commented code --- compliance_checker/tests/test_cf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/compliance_checker/tests/test_cf.py b/compliance_checker/tests/test_cf.py index b9822623..dce2bfa4 100644 --- a/compliance_checker/tests/test_cf.py +++ b/compliance_checker/tests/test_cf.py @@ -3256,7 +3256,6 @@ def test_domain(self): results = self.cf.check_domain_variables(dataset) assert not results[0].msgs # failing example, coordinates for cell_measures variable are no longer subset - #cube.dimensions = "virtlon virtlat height time" domain_var.cell_measures = "volume: cube_bad" dataset.createVariable("cube_bad", "f8", ("lon", "lat", "depth", "time")) results = self.cf.check_domain_variables(dataset)