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 04ca15b2..f053f837 100644 --- a/compliance_checker/tests/test_cf.py +++ b/compliance_checker/tests/test_cf.py @@ -3240,7 +3240,28 @@ 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 + 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