Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix handling wkt strings and add pyproj.CRS support #1139

Merged
merged 18 commits into from
Sep 26, 2023
Merged
8 changes: 8 additions & 0 deletions hvplot/tests/testutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,14 @@ def test_proj_to_cartopy(self):

assert isinstance(crs, self.ccrs.CRS)

def test_proj_to_cartopy_wkt_string(self):
from ..util import proj_to_cartopy
crs = proj_to_cartopy('GEOGCRS["unnamed",BASEGEOGCRS["unknown",DATUM["unknown",ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1,ID["EPSG",9001]]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8901]]],DERIVINGCONVERSION["unknown",METHOD["PROJ ob_tran o_proj=latlon"],PARAMETER["o_lon_p",0,ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9122]]],PARAMETER["o_lat_p",37.5,ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9122]]],PARAMETER["lon_0",357.5,ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9122]]]],CS[ellipsoidal,2],AXIS["longitude",east,ORDER[1],ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9122]]],AXIS["latitude",north,ORDER[2],ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9122]]]]') # noqa: E501

assert isinstance(crs, self.ccrs.RotatedPole)
assert crs.proj4_params["lon_0"] == 357.5
assert crs.proj4_params["o_lat_p"] == 37.5


class TestDynamicArgs(TestCase):

Expand Down
44 changes: 27 additions & 17 deletions hvplot/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,11 @@ class Dummy:
out = pyproj.Proj(crs.to_wkt(), preserve_units=True)
elif isinstance(crs, dict) or isinstance(crs, str):
if isinstance(crs, str):
# quick fix for https://github.com/pyproj4/pyproj/issues/345
crs = crs.replace(' ', '').replace('+', ' +')
try:
crs = pyproj.CRS.from_wkt(crs)
except RuntimeError:
# quick fix for https://github.com/pyproj4/pyproj/issues/345
crs = crs.replace(' ', '').replace('+', ' +')
try:
out = pyproj.Proj(crs, preserve_units=True)
except RuntimeError:
Expand Down Expand Up @@ -124,10 +127,10 @@ def proj_to_cartopy(proj):
except ImportError:
has_gdal = False

proj = check_crs(proj)

if proj_is_latlong(proj):
return ccrs.PlateCarree()
input_proj = proj
proj = check_crs(input_proj)
if proj is None:
raise ValueError(f"Invalid proj projection {input_proj!r}")

srs = proj.srs
if has_gdal:
Expand Down Expand Up @@ -167,19 +170,23 @@ def proj_to_cartopy(proj):
except:
pass
if k == 'proj':
if v == 'tmerc':
if v == "longlat":
cl = ccrs.PlateCarree
elif v == 'tmerc':
cl = ccrs.TransverseMercator
kw_proj['approx'] = True
if v == 'lcc':
elif v == 'lcc':
cl = ccrs.LambertConformal
if v == 'merc':
elif v == 'merc':
cl = ccrs.Mercator
if v == 'utm':
elif v == 'utm':
cl = ccrs.UTM
if v == 'stere':
elif v == 'stere':
cl = ccrs.Stereographic
if v == 'ob_tran':
elif v == 'ob_tran':
cl = ccrs.RotatedPole
else:
raise NotImplementedError('Unknown projection {}'.format(v))
ahuang11 marked this conversation as resolved.
Show resolved Hide resolved
ahuang11 marked this conversation as resolved.
Show resolved Hide resolved
if k in km_proj:
if k == 'zone':
v = int(v)
Expand Down Expand Up @@ -228,7 +235,8 @@ def process_crs(crs):
1. EPSG codes: Defined as string of the form "EPSG: {code}" or an integer
2. proj.4 string: Defined as string of the form "{proj.4 string}"
3. cartopy.crs.CRS instance
4. None defaults to crs.PlateCaree
4. WKT string: Defined as string of the form "{WKT string}"
5. None defaults to crs.PlateCaree
"""
missing = []
try:
Expand All @@ -252,13 +260,12 @@ def process_crs(crs):
errors = []
if isinstance(crs, str) and crs.lower().startswith('epsg'):
try:
crs = crs[5:].lstrip().rstrip()
return ccrs.epsg(crs)
crs = pyproj.CRS.from_epsg(crs).to_wkt()
ahuang11 marked this conversation as resolved.
Show resolved Hide resolved
except Exception as e:
errors.append(e)
if isinstance(crs, int):
try:
return ccrs.epsg(crs)
crs = pyproj.CRS.from_epsg(crs).to_wkt()
ahuang11 marked this conversation as resolved.
Show resolved Hide resolved
except Exception as e:
crs = str(crs)
errors.append(e)
Expand All @@ -270,7 +277,10 @@ def process_crs(crs):
if isinstance(crs, ccrs.CRS):
return crs

raise ValueError("Projection must be defined as a EPSG code, proj4 string, cartopy CRS or pyproj.Proj.") from Exception(*errors)
raise ValueError(
"Projection must be defined as a EPSG code, proj4 string, "
"WKT string, cartopy CRS, or pyproj.Proj."
) from Exception(*errors)


def is_list_like(obj):
Expand Down