Skip to content

Commit

Permalink
Merge pull request #1322 from corteva/crs_wkt_cache
Browse files Browse the repository at this point in the history
PERF: CRS - use WKT for cache and lazy load EPSG code
  • Loading branch information
SpacemanPaul committed Oct 13, 2022
2 parents e0dfd94 + d2d7d0d commit 0535335
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 19 deletions.
2 changes: 1 addition & 1 deletion datacube/drivers/postgis/_spatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def spindex_for_epsg(epsg: int) -> Type[SpatialIndex]:

def spindex_for_crs(crs: CRS) -> Type[SpatialIndex]:
"""Return ORM class of a SpatialIndex for CRS - dynamically creating if necessary"""
if not (str(crs).startswith('EPSG') and crs.epsg):
if not str(crs).startswith("EPSG:") and crs.epsg is None:
# Postgis identifies CRSs by a numeric "SRID" which is equivalent to EPSG number.
_LOG.error("Cannot create a postgis spatial index for a non-EPSG-style CRS.")
return None
Expand Down
39 changes: 21 additions & 18 deletions datacube/utils/geometry/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,25 +116,25 @@ def from_points(p1: Tuple[float, float],
(p1[1], p2[1]))


def _make_crs_key(crs_spec: Union[str, _CRS]) -> str:
def _make_crs_key(crs_spec: Union[str, int, _CRS]) -> str:
if isinstance(crs_spec, str):
normed_epsg = crs_spec.upper()
if normed_epsg.startswith("EPSG:"):
return normed_epsg
return crs_spec
if isinstance(crs_spec, int):
return f"EPSG:{crs_spec}"
return crs_spec.to_wkt()


@cachetools.cached({}, key=_make_crs_key) # type: ignore[misc]
def _make_crs(crs: Union[str, _CRS]) -> Tuple[_CRS, str, Optional[int]]:
if isinstance(crs, str):
crs = _CRS.from_user_input(crs)
epsg = crs.to_epsg()
if epsg is not None:
crs_str = f"EPSG:{epsg}"
else:
crs_str = crs.to_wkt()
return (crs, crs_str, crs.to_epsg())
def _make_crs(crs: Union[str, int, _CRS]) -> Tuple[_CRS, str, Optional[int]]:
epsg = False
crs = _CRS.from_user_input(crs)
crs_str = crs.srs
if crs_str.upper().startswith("EPSG:"):
epsg = int(crs_str.split(":", maxsplit=1)[-1])
return (crs, crs_str, epsg)


def _make_crs_transform_key(from_crs, to_crs, always_xy):
Expand Down Expand Up @@ -171,20 +171,20 @@ def __init__(self, crs_spec: Any):
elif isinstance(crs_spec, dict):
self._crs, self._str, self._epsg = _make_crs(_CRS.from_dict(crs_spec))
else:
try:
epsg = crs_spec.to_epsg()
except AttributeError:
epsg = None
if epsg is not None:
self._crs, self._str, self._epsg = _make_crs(f"EPSG:{epsg}")
return
try:
wkt = crs_spec.to_wkt()
except AttributeError:
wkt = None
if wkt is not None:
self._crs, self._str, self._epsg = _make_crs(wkt)
return
try:
epsg = crs_spec.to_epsg()
except AttributeError:
epsg = None
if epsg is not None:
self._crs, self._str, self._epsg = _make_crs(epsg)
return

raise CRSError(
"Expect string or any object with `.to_epsg()` or `.to_wkt()` methods"
Expand Down Expand Up @@ -213,11 +213,14 @@ def to_epsg(self) -> Optional[int]:
"""
EPSG Code of the CRS or None
"""
if self._epsg is not False:
return self._epsg
self._epsg = self._crs.to_epsg()
return self._epsg

@property
def epsg(self) -> Optional[int]:
return self._epsg
return self.to_epsg()

@property
def semi_major_axis(self):
Expand Down

0 comments on commit 0535335

Please sign in to comment.