Repository: ioos/compliance-checker

Issue:
CF duplicate axis check fails incorrectly
For a file with the following structure:
```
dimensions:
        TIME = 26577 ;
        HEIGHT_ABOVE_SENSOR = 25 ;
        DIST_ALONG_BEAMS = 25 ;

variables:
        double TIME(TIME) ;
                TIME:axis = "T" ;
        double LATITUDE ;
                LATITUDE:axis = "Y" ;
        double LONGITUDE ;
                LONGITUDE:axis = "X" ;
        float HEIGHT_ABOVE_SENSOR(HEIGHT_ABOVE_SENSOR) ;
                HEIGHT_ABOVE_SENSOR:axis = "Z" ;
        float NOMINAL_DEPTH ;
                NOMINAL_DEPTH:axis = "Z" ;
        float DIST_ALONG_BEAMS(DIST_ALONG_BEAMS) ;
                // no axis attribute (this is not strictly a depth/height coordinate)

        float ABSIC1(TIME, DIST_ALONG_BEAMS) ;
                ABSIC1:coordinates = "TIME LATITUDE LONGITUDE DIST_ALONG_BEAMS" ;
                ABSIC1:_FillValue = 999999.f ;
                ABSIC1:long_name = "backscatter_intensity_from_acoustic_beam_1" ;
                ABSIC1:units = "count" ;
```
I get a failing CF check with the message:
```
§5.0 Variable ABSIC1 does not contain d:3:     5/ 6 : duplicate axis Z defined
                                                      by NOMINAL_DEPTH
```
This is referring to the section of [CF](http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html#coordinate-system) (6th paragraph) that says:
> it is not permissible for a data variable to have both a coordinate variable and an auxiliary coordinate variable, or more than one of either type of variable, having an axis attribute with any given value

However in this case the `ABSIC1` variable has _no_ associated coordinate variables of either kind that define an axis="Z" attribute, so I think the checker is wrong.

It's true that there are two variables int he file that have axis="Z" (`HEIGHT_ABOVE_SENSOR` and `NOMINAL_DEPTH`), but I think this is allowed, as long as no other variable names _both_ of them as associated coordinate variables, which is the case in this file.

CF duplicate axis check fails incorrectly
For a file with the following structure:
```
dimensions:
        TIME = 26577 ;
        HEIGHT_ABOVE_SENSOR = 25 ;
        DIST_ALONG_BEAMS = 25 ;

variables:
        double TIME(TIME) ;
                TIME:axis = "T" ;
        double LATITUDE ;
                LATITUDE:axis = "Y" ;
        double LONGITUDE ;
                LONGITUDE:axis = "X" ;
        float HEIGHT_ABOVE_SENSOR(HEIGHT_ABOVE_SENSOR) ;
                HEIGHT_ABOVE_SENSOR:axis = "Z" ;
        float NOMINAL_DEPTH ;
                NOMINAL_DEPTH:axis = "Z" ;
        float DIST_ALONG_BEAMS(DIST_ALONG_BEAMS) ;
                // no axis attribute (this is not strictly a depth/height coordinate)

        float ABSIC1(TIME, DIST_ALONG_BEAMS) ;
                ABSIC1:coordinates = "TIME LATITUDE LONGITUDE DIST_ALONG_BEAMS" ;
                ABSIC1:_FillValue = 999999.f ;
                ABSIC1:long_name = "backscatter_intensity_from_acoustic_beam_1" ;
                ABSIC1:units = "count" ;
```
I get a failing CF check with the message:
```
§5.0 Variable ABSIC1 does not contain d:3:     5/ 6 : duplicate axis Z defined
                                                      by NOMINAL_DEPTH
```
This is referring to the section of [CF](http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html#coordinate-system) (6th paragraph) that says:
> it is not permissible for a data variable to have both a coordinate variable and an auxiliary coordinate variable, or more than one of either type of variable, having an axis attribute with any given value

However in this case the `ABSIC1` variable has _no_ associated coordinate variables of either kind that define an axis="Z" attribute, so I think the checker is wrong.

It's true that there are two variables int he file that have axis="Z" (`HEIGHT_ABOVE_SENSOR` and `NOMINAL_DEPTH`), but I think this is allowed, as long as no other variable names _both_ of them as associated coordinate variables, which is the case in this file.



Discussion:
Here is a sample of the file demonstrating this issue: [imos_duplicate_axis.zip](https://github.com/ioos/compliance-checker/files/1805568/imos_duplicate_axis.zip)

Here is a sample of the file demonstrating this issue: [imos_duplicate_axis.zip](https://github.com/ioos/compliance-checker/files/1805568/imos_duplicate_axis.zip)


Resolving patch:
diff --git a/compliance_checker/cfutil.py b/compliance_checker/cfutil.py
--- a/compliance_checker/cfutil.py
+++ b/compliance_checker/cfutil.py
@@ -677,20 +677,6 @@ def get_axis_map(ds, variable):
             if coord_name not in axis_map[axis]:
                 axis_map[axis].append(coord_name)
 
-    # Sometimes dimensionless coordinates are considered coordinate variables.
-    # I know, it's confusing.
-    if 'X' not in axis_map and longitudes:
-        axis_map['X'] = longitudes
-
-    if 'Y' not in axis_map and latitudes:
-        axis_map['Y'] = latitudes
-
-    if 'T' not in axis_map and times:
-        axis_map['T'] = times
-
-    if 'Z' not in axis_map and heights:
-        axis_map['Z'] = heights
-
     return axis_map
 
 


Test patch:
diff --git a/compliance_checker/tests/test_feature_detection.py b/compliance_checker/tests/test_feature_detection.py
--- a/compliance_checker/tests/test_feature_detection.py
+++ b/compliance_checker/tests/test_feature_detection.py
@@ -283,8 +283,9 @@ def test_global_feature_detection(self):
 
             axis_map = util.get_axis_map(nc, 'temperature')
             assert axis_map['T'] == ['time']
-            assert axis_map['Y'] == ['lat']
-            assert axis_map['X'] == ['lon']
+            assert axis_map['Z'] == []
+            assert axis_map['Y'] == []
+            assert axis_map['X'] == []
 
         with Dataset(resources.STATIC_FILES['index_ragged']) as nc:
             assert util.guess_feature_type(nc, 'temperature') == "single-trajectory"
@@ -300,7 +301,7 @@ def test_global_feature_detection(self):
 
             axis_map = util.get_axis_map(nc, 'sea_surface_height')
             assert axis_map['T'] == ['time']
-            assert axis_map['Z'] == ['z']
+            assert axis_map['Z'] == []
             assert axis_map['Y'] == ['lat']
             assert axis_map['X'] == ['lon']