Add always_xy for pyproj>=2.2.0; skip transformations when CRS exact same (#1122)

This commit is contained in:
Alan D. Snow
2019-09-12 14:23:56 +02:00
committed by Joris Van den Bossche
parent 0f0556a457
commit d2020b299b
2 changed files with 48 additions and 7 deletions
+24 -7
View File
@@ -18,7 +18,8 @@ from geopandas.plotting import plot_series
from .array import GeometryDtype, from_shapely
from .base import is_geometry_type
_PYPROJ2 = LooseVersion(pyproj.__version__) >= LooseVersion("2.1.0")
_PYPROJ_VERSION = LooseVersion(pyproj.__version__)
_SERIES_WARNING_MSG = """\
@@ -389,22 +390,38 @@ class GeoSeries(GeoPandasBase, Series):
"""
from fiona.crs import from_epsg
if crs is None and epsg is None:
raise TypeError("Must set either crs or epsg for output.")
if self.crs is None:
raise ValueError(
"Cannot transform naive geometries. "
"Please set a crs on the object first."
)
if crs is None:
try:
crs = from_epsg(epsg)
except TypeError:
raise TypeError("Must set either crs or epsg for output.")
proj_in = pyproj.Proj(self.crs, preserve_units=True)
proj_out = pyproj.Proj(crs, preserve_units=True)
if _PYPROJ2:
transformer = pyproj.Transformer.from_proj(proj_in, proj_out)
except (TypeError, ValueError):
raise ValueError("Invalid epsg: {}".format(epsg))
# skip transformation if the input CRS and output CRS are the exact same
if _PYPROJ_VERSION >= LooseVersion("2.1.2") and pyproj.CRS.from_user_input(
self.crs
).is_exact_same(pyproj.CRS.from_user_input(crs)):
return self
if _PYPROJ_VERSION >= LooseVersion("2.2.0"):
# if availale, use always_xy=True to preserve GIS axis order
transformer = pyproj.Transformer.from_crs(self.crs, crs, always_xy=True)
project = transformer.transform
elif _PYPROJ_VERSION >= LooseVersion("2.1.0"):
# use transformer for repeated transformations
transformer = pyproj.Transformer.from_crs(self.crs, crs)
project = transformer.transform
else:
proj_in = pyproj.Proj(self.crs, preserve_units=True)
proj_out = pyproj.Proj(crs, preserve_units=True)
project = partial(pyproj.transform, proj_in, proj_out)
result = self.apply(lambda geom: transform(project, geom))
result.__class__ = GeoSeries
+24
View File
@@ -1,6 +1,11 @@
from distutils.version import LooseVersion
import numpy as np
from shapely.geometry import Point
from geopandas import GeoDataFrame, points_from_xy
from geopandas.geoseries import _PYPROJ_VERSION
from geopandas.testing import assert_geodataframe_equal
import pytest
@@ -94,3 +99,22 @@ def test_transform2(epsg4326, epsg26918):
# can't check for CRS equality, as the formats differ although representing
# the same CRS
assert_geodataframe_equal(df, utm, check_less_precise=True, check_crs=False)
@pytest.mark.skipif(
_PYPROJ_VERSION < LooseVersion("2.2.0"),
reason="EPSG strings without +init= won't work on previous versions of pyproj.",
)
def test_crs_axis_order__always_xy():
df = GeoDataFrame(geometry=[Point(-1683723, 6689139)], crs="epsg:26918")
lonlat = df.to_crs("epsg:4326")
test_lonlat = GeoDataFrame(
geometry=[Point(-110.1399901, 55.1350011)], crs="epsg:4326"
)
assert_geodataframe_equal(lonlat, test_lonlat, check_less_precise=True)
def test_skip_exact_same():
df = df_epsg26918()
utm = df.to_crs(df.crs)
assert_geodataframe_equal(df, utm, check_less_precise=True)