Repository: ioos/compliance-checker

Issue:
Add check for dimension and variable names
Write a check to ensure that no variable has the same name as a dimension unless it is a coordinate variable.

> the name of a multidimensional coordinate variable should not match the name of any of its dimensions

That's self-contradictory since it's impossible to have a multi-dimensional coordinate variable. A coordinate variable can ONLY BE a variable with a single dimension sharing the same name as the variable.



Discussion:

Resolving patch:
diff --git a/compliance_checker/cf/cf.py b/compliance_checker/cf/cf.py
--- a/compliance_checker/cf/cf.py
+++ b/compliance_checker/cf/cf.py
@@ -1934,6 +1934,9 @@ def _get_coord_vars(self, ds):
 
     def check_duplicate_axis(self, ds):
         '''
+        Checks that no variable contains two coordinates defining the same
+        axis.
+
         Chapter 5 paragraph 6
 
         If an axis attribute is attached to an auxiliary coordinate variable,
@@ -1974,6 +1977,34 @@ def check_duplicate_axis(self, ds):
 
         return ret_val
 
+    def check_multi_dimensional_coords(self, ds):
+        '''
+        Checks that no multidimensional coordinate shares a name with its
+        dimensions.
+
+        Chapter 5 paragraph 4
+
+        We recommend that the name of a [multidimensional coordinate] should
+        not match the name of any of its dimensions.
+        '''
+        ret_val = []
+
+        # This can only apply to auxiliary coordinate variables
+        for coord in self._find_aux_coord_vars(ds):
+            variable = ds.variables[coord]
+            if variable.ndim < 2:
+                continue
+            not_matching = TestCtx(BaseCheck.MEDIUM,
+                                   '§5.0 multidimensional coordinate {} should not have the same '
+                                   'name as dimension'.format(coord))
+
+            not_matching.assert_true(coord not in variable.dimensions,
+                                     '{} shares the same name as one of its dimensions'
+                                     ''.format(coord))
+            ret_val.append(not_matching.to_result())
+
+        return ret_val
+
     def check_two_dimensional(self, ds):
         """
         5.2 The latitude and longitude coordinates of a horizontal grid that was


Test patch:
diff --git a/compliance_checker/tests/data/multi-dim-coordinates.cdl b/compliance_checker/tests/data/multi-dim-coordinates.cdl
new file mode 100644
--- /dev/null
+++ b/compliance_checker/tests/data/multi-dim-coordinates.cdl
@@ -0,0 +1,21 @@
+netcdf multi-dim-coordinates {
+dimensions:
+    xlon = 2;
+    xlat = 2;
+variables:
+    double xlon(xlon, xlat);
+        xlon:axis = "X";
+    double xlat(xlon, xlat);
+        xlat:axis = "Y";
+    double lat(xlon, xlat);
+        lat:standard_name = "latitude";
+        lat:units = "degrees_north";
+    double lon(xlon, xlat);
+        lon:standard_name = "longitude";
+        lon:units = "degrees_east";
+    double temperature(xlon, xlat);
+        temperature:standard_name = "sea_water_temperature";
+        temperature:units = "deg_C";
+        temperature:coordinates = "lat lon";
+    
+}
diff --git a/compliance_checker/tests/resources.py b/compliance_checker/tests/resources.py
--- a/compliance_checker/tests/resources.py
+++ b/compliance_checker/tests/resources.py
@@ -75,4 +75,5 @@ def generate_dataset(cdl_path, nc_path):
     'vertical_coords'                      : get_filename('tests/data/vertical_coords.cdl'),
     'reduced_horizontal_grid'              : get_filename('tests/data/reduced_horizontal_grid.cdl'),
     'duplicate_axis'                       : get_filename('tests/data/duplicate_axis.cdl'),
+    'multi-dim-coordinates'                : get_filename('tests/data/multi-dim-coordinates.cdl'),
 }
diff --git a/compliance_checker/tests/test_cf.py b/compliance_checker/tests/test_cf.py
--- a/compliance_checker/tests/test_cf.py
+++ b/compliance_checker/tests/test_cf.py
@@ -948,6 +948,22 @@ def test_check_duplicates(self):
         result = result_dict[u'§5.0 Variable temp does not contain duplicate coordinates']
         assert result.msgs[0] == 'duplicate axis X defined by lon_rho'
 
+    def test_check_multi_dimensional_coords(self):
+        '''
+        Test to verify that multi dimensional coordinates are checked for
+        sharing names with dimensions
+        '''
+        dataset = self.load_dataset(STATIC_FILES['multi-dim-coordinates'])
+        results = self.cf.check_multi_dimensional_coords(dataset)
+        scored, out_of, messages = self.get_results(results)
+        result_dict = {result.name: result for result in results}
+        result = result_dict[u'§5.0 multidimensional coordinate xlon should not have the same name as dimension']
+        assert result.msgs[0] == 'xlon shares the same name as one of its dimensions'
+        result = result_dict[u'§5.0 multidimensional coordinate xlat should not have the same name as dimension']
+        assert result.msgs[0] == 'xlat shares the same name as one of its dimensions'
+
+        assert (scored, out_of) == (2, 4)
+
     def test_64bit(self):
         dataset = self.load_dataset(STATIC_FILES['ints64'])
         suite = CheckSuite()