Repository: opendatacube/datacube-core

Issue:
CRS equality is returning false for a polygon's CRS
### Expected behaviour
The polygon from a shapefile that is in EPSG:3577 is used to query data for data that is stored in the same projection.  It should be recognized as the same projection.

### Actual behaviour
Each CRS object is converted to its proj4 representation and compared.
The shapefile version is has the same properties as the EPSG derived value, with the addition of the property: `+towgs84=0,0,0,0,0,0,0`

This additional property causes the equality operator to return false, even though they represent the same CRS.

Relevant code here: https://github.com/opendatacube/datacube-core/blob/develop/datacube/utils/geometry.py#L222

### Steps to reproduce the behaviour
```import fiona
from datacube.utils.geometry import CRS

filepath = '/g/data/u46/users/bxb547/GA_tidal_model.shp'
with fiona.open(filepath) as shapefile_input:
    crs = CRS(str(shapefile_input.crs_wkt))

epsg3577 = CRS('EPSG:3577')

assert crs == CRS('EPSG:3577')
```

### Environment information
agdc-py3-prod/1.4.1



Discussion:

Resolving patch:
diff --git a/datacube/utils/geometry.py b/datacube/utils/geometry.py
--- a/datacube/utils/geometry.py
+++ b/datacube/utils/geometry.py
@@ -219,8 +219,14 @@ def __repr__(self):
     def __eq__(self, other):
         if isinstance(other, compat.string_types):
             other = CRS(other)
-        canonical = lambda crs: set(crs.ExportToProj4().split() + ['+wktext'])
-        return canonical(self._crs) == canonical(other._crs)  # pylint: disable=protected-access
+        gdal_thinks_issame = self._crs.IsSame(other._crs) == 1  # pylint: disable=protected-access
+        if gdal_thinks_issame:
+            return True
+
+        def to_canonincal_proj4(crs):
+            return set(crs.ExportToProj4().split() + ['+wktext'])
+        proj4_repr_is_same = to_canonincal_proj4(self._crs) == to_canonincal_proj4(other._crs)  # pylint: disable=protected-access
+        return proj4_repr_is_same
 
     def __ne__(self, other):
         if isinstance(other, compat.string_types):


Test patch:
diff --git a/tests/test_geometry.py b/tests/test_geometry.py
--- a/tests/test_geometry.py
+++ b/tests/test_geometry.py
@@ -159,31 +159,54 @@ def test_unary_intersection():
     assert inter6.is_empty
 
 
-def test_crs_equality():
-    a = geometry.CRS("""PROJCS["unnamed",GEOGCS["Unknown datum based upon the custom spheroid",
-                       DATUM["Not specified (based on custom spheroid)",SPHEROID["Custom spheroid",6371007.181,0]],
-                       PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Sinusoidal"],
-                       PARAMETER["longitude_of_center",0],PARAMETER["false_easting",0],
-                       PARAMETER["false_northing",0],UNIT["Meter",1]]""")
-    b = geometry.CRS("""PROJCS["unnamed",GEOGCS["unnamed ellipse",DATUM["unknown",SPHEROID["unnamed",6371007.181,0]],
-                       PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Sinusoidal"],
-                       PARAMETER["longitude_of_center",0],PARAMETER["false_easting",0],
-                       PARAMETER["false_northing",0],UNIT["Meter",1]]""")
-    c = geometry.CRS('+a=6371007.181 +b=6371007.181 +units=m +y_0=0 +proj=sinu +lon_0=0 +no_defs +x_0=0')
-    assert a == b
-    assert a == c
-    assert b == c
-
-    assert a != geometry.CRS('EPSG:4326')
-
-    a = geometry.CRS("""GEOGCS["GEOCENTRIC DATUM of AUSTRALIA",DATUM["GDA94",SPHEROID["GRS80",6378137,298.257222101]],
-                        PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]]""")
-    b = geometry.CRS("""GEOGCS["GRS 1980(IUGG, 1980)",DATUM["unknown",SPHEROID["GRS80",6378137,298.257222101]],
-                        PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]]""")
-    c = geometry.CRS('+proj=longlat +no_defs +ellps=GRS80')
-    assert a == b
-    assert a == c
-    assert b == c
+class TestCRSEqualityComparisons(object):
+    def test_sinusoidal_comparison(self):
+        a = geometry.CRS("""PROJCS["unnamed",GEOGCS["Unknown datum based upon the custom spheroid",
+                           DATUM["Not specified (based on custom spheroid)",SPHEROID["Custom spheroid",6371007.181,0]],
+                           PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Sinusoidal"],
+                           PARAMETER["longitude_of_center",0],PARAMETER["false_easting",0],
+                           PARAMETER["false_northing",0],UNIT["Meter",1]]""")
+        b = geometry.CRS("""PROJCS["unnamed",GEOGCS["unnamed ellipse",
+                           DATUM["unknown",SPHEROID["unnamed",6371007.181,0]],
+                           PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Sinusoidal"],
+                           PARAMETER["longitude_of_center",0],PARAMETER["false_easting",0],
+                           PARAMETER["false_northing",0],UNIT["Meter",1]]""")
+        c = geometry.CRS('+a=6371007.181 +b=6371007.181 +units=m +y_0=0 +proj=sinu +lon_0=0 +no_defs +x_0=0')
+        assert a == b
+        assert a == c
+        assert b == c
+
+        assert a != geometry.CRS('EPSG:4326')
+
+    def test_grs80_comparison(self):
+        a = geometry.CRS("""GEOGCS["GEOCENTRIC DATUM of AUSTRALIA",DATUM["GDA94",SPHEROID["GRS80",6378137,298.257222101]],
+                            PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]]""")
+        b = geometry.CRS("""GEOGCS["GRS 1980(IUGG, 1980)",DATUM["unknown",SPHEROID["GRS80",6378137,298.257222101]],
+                            PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]]""")
+        c = geometry.CRS('+proj=longlat +no_defs +ellps=GRS80')
+        assert a == b
+        assert a == c
+        assert b == c
+
+        assert a != geometry.CRS('EPSG:4326')
+
+    def test_australian_albers_comparison(self):
+        a = geometry.CRS("""PROJCS["GDA94_Australian_Albers",GEOGCS["GCS_GDA_1994",
+                            DATUM["Geocentric_Datum_of_Australia_1994",SPHEROID["GRS_1980",6378137,298.257222101]],
+                            PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],
+                            PROJECTION["Albers_Conic_Equal_Area"],
+                            PARAMETER["standard_parallel_1",-18],
+                            PARAMETER["standard_parallel_2",-36],
+                            PARAMETER["latitude_of_center",0],
+                            PARAMETER["longitude_of_center",132],
+                            PARAMETER["false_easting",0],
+                            PARAMETER["false_northing",0],
+                            UNIT["Meter",1]]""")
+        b = geometry.CRS('EPSG:3577')
+
+        assert a == b
+
+        assert a != geometry.CRS('EPSG:4326')
 
 
 def test_geobox():
@@ -209,14 +232,14 @@ def test_geobox():
                    reason='Fails under GDAL 2.1')
 def test_wrap_dateline():
     sinus_crs = geometry.CRS("""PROJCS["unnamed",
-GEOGCS["Unknown datum based upon the custom spheroid",
-DATUM["Not specified (based on custom spheroid)", SPHEROID["Custom spheroid",6371007.181,0]],
-PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],
-PROJECTION["Sinusoidal"],
-PARAMETER["longitude_of_center",0],
-PARAMETER["false_easting",0],
-PARAMETER["false_northing",0],
-UNIT["Meter",1]]""")
+                           GEOGCS["Unknown datum based upon the custom spheroid",
+                           DATUM["Not specified (based on custom spheroid)", SPHEROID["Custom spheroid",6371007.181,0]],
+                           PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],
+                           PROJECTION["Sinusoidal"],
+                           PARAMETER["longitude_of_center",0],
+                           PARAMETER["false_easting",0],
+                           PARAMETER["false_northing",0],
+                           UNIT["Meter",1]]""")
     albers_crs = geometry.CRS('EPSG:3577')
     geog_crs = geometry.CRS('EPSG:4326')