-
Notifications
You must be signed in to change notification settings - Fork 94
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 support for pyproj-2 EPSG syntax #186
Conversation
Usage: AreaDefinition(projection='EPSG:XXXX', ...)
Codecov Report
@@ Coverage Diff @@
## master #186 +/- ##
==========================================
- Coverage 86.65% 86.61% -0.04%
==========================================
Files 36 37 +1
Lines 6653 6776 +123
==========================================
+ Hits 5765 5869 +104
- Misses 888 907 +19
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not happy how much work has had to go in to supporting EPSG codes, but I suppose we don't have much of a choice. Another option that I'm now realizing, could/should we just pass whatever the user provided to Proj
and let their deprecation warnings be the "source of truth"? I suppose with our use of the proj dicts that isn't possible.
As for your performance issues, could you maybe get this down to a simple Proj(...)(x, y)
use case? Maybe file a bug with pyproj if one does not exist already?
I had an example that failed reading from a yaml file. I would like this to be tested if possible ? |
@djhoese Yeah, I'm not happy either. Your suggestion to pass whatever the user provided to Proj is the cleanest solution. However that would be lots of internal changes. IIRC you mentioned moving to CRSes at some point. I think this could solve most of the problems. Maybe by replacing proj_dicts with CRSes. Many properties are accessible from the CRS object ( |
area_def.proj_dict['a'] = area_def.proj_dict.pop('R') | ||
for key in ['x_0', 'y_0', 'no_defs', 'b', 'init']: | ||
area_def.proj_dict.pop(key, None) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the above actually testing? Is this showing that area definitions with EPSG codes aren't comparable out of the box?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The generated area defs are compared to base_def
whos proj_dict
looks like {'proj': 'laea', 'lat_0': -90, ...}
. However, the EPSG area defs have proj_dict={'EPSG': 1234}
so that they are not directly comparable to base_def
. The workaround is to use their definition_string
. But that contains some additional (redundant) parameters like x_0=0, y_0=0
. The ellipsoid parameters in the definition string are also different depending on the proj version (a
and b
in pyproj >= 2 vs R
in pyproj < 2)
try: | ||
code = int(proj4_str.split(':', 1)[1]) | ||
except ValueError as err: | ||
six.raise_from(ValueError("Invalid EPSG code '{}': {}".format(proj4_str, err)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Am I correct in thinking that this won't be needed when python 2.7 is dropped?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, correct! Then we could use raise ... from None
If EPSG code is present, ignore other parameters
@djhoese Regarding the performance issue in In [3]: pyproj.Proj('EPSG:4326').definition_string()
Out[3]: 'proj=longlat datum=WGS84 no_defs ellps=WGS84 towgs84=0,0,0'
In [4]: pyproj.Proj('proj=longlat datum=WGS84 no_defs ellps=WGS84 towgs84=0,0,0').crs.is_geographic
Out[4]: False See pyproj4/pyproj#274. As a consequence, the shortcut if self.is_latlong():
return data1, data2 in |
Conversion proj4 string <-> dict can be tested for all pyproj versions
This PR fixes the creation of area defs using pyproj-2 EPSG syntax:
AreaDefinition(projection='EPSG:XXXX', ...)
. Additionally it adds (limited) support for EPSG codes inAreaDefinition.to_cartopy_crs()
.Syntax
Valid EPSG definitions are now:
The former two cases in conjunction with pyproj 2+ will trigger a warning. For the implementation I came up with two options:
proj_dict
.EPSG:XXXX
syntaxOption 1. would have been the cleaner solution, because we could have used a uniform
proj_dict
everywhere. However, I found out that the conversion from EPSG code to proj4 string is a potentially lossy transformation (see pyproj4/pyproj#207 (comment)). Furthermore I had a performance issue with pyproj-2 and definition strings. The following snippet took > 10 minutes (I cancelled after 10 minutes):Without the extra
towgs84
parameter in theproj_dict
it finishes within a few seconds.Cartopy CRS
Additionally, this PR adds limited support for EPSG codes in
AreaDefinition.to_cartopy_crs()
. Again, there were two options:cartopy.crs.epsg()
(https://github.com/SciTools/cartopy/blob/v0.16.0/lib/cartopy/crs.py#L1993)Unfortunately
cartopy.crs.epsg()
requires an active internet connection and doesn't work for geodetic coordinate systems such asEPSG:4326
. That is why I chose option 2.git diff origin/master **/*py | flake8 --diff