55`~cartopy.crs.Projection` classes.
66"""
77from .utils import _warn_proplot
8- import numpy as np
8+ try :
9+ from mpl_toolkits .basemap import Basemap
10+ except ImportError :
11+ Basemap = object
912try :
1013 from cartopy .crs import (
11- _WarpedRectangularProjection ,
12- LambertAzimuthalEqualArea , AzimuthalEquidistant , Gnomonic )
13- _cartopy_installed = True
14+ CRS , _WarpedRectangularProjection ,
15+ LambertAzimuthalEqualArea , AzimuthalEquidistant , Gnomonic
16+ )
1417except ModuleNotFoundError :
18+ CRS = object
1519 _WarpedRectangularProjection = object
1620 LambertAzimuthalEqualArea = object
1721 AzimuthalEquidistant = object
1822 Gnomonic = object
19- _cartopy_installed = False
2023
2124__all__ = [
2225 'Proj' ,
@@ -54,16 +57,18 @@ def Proj(name, basemap=False, **kwargs):
5457
5558 Parameters
5659 ----------
57- name : str
58- The projection name. Like basemap, we use the
59- `PROJ <https://proj.org>`__ shorthands.
60-
61- The following table lists the valid projection names, their full names
62- (with links to the relevant `PROJ documentation \
60+ name : str, `~mpl_toolkits.basemap.Basemap`, or `cartopy.crs.Projection`
61+ The projection name or projection class instance. If the latter, it
62+ is simply returned. If the former, it must correspond to one of the
63+ `PROJ <https://proj.org>`__ projection name shorthands, like in
64+ basemap.
65+
66+ The following table lists the valid projection name shorthands, their
67+ full names (with links to the relevant `PROJ documentation \
6368 <https://proj4.org/operations/projections/index.html>`__),
6469 and whether they are available in the cartopy and basemap packages.
6570
66- `` (added)`` indicates a projection class that ProPlot has "added"
71+ (added) indicates a projection class that ProPlot has "added"
6772 to cartopy using the cartopy API.
6873
6974 ============= ============================================================================================ ========= =======
@@ -123,8 +128,8 @@ def Proj(name, basemap=False, **kwargs):
123128 ============= ============================================================================================ ========= =======
124129
125130 basemap : bool, optional
126- Whether to use the basemap or cartopy package. Default is
127- ``False``.
131+ Whether to use the basemap package as opposed to the cartopy package.
132+ Default is ``False``.
128133 **kwargs
129134 Passed to the `~mpl_toolkits.basemap.Basemap` or
130135 cartopy `~cartopy.crs.Projection` class.
@@ -133,17 +138,23 @@ def Proj(name, basemap=False, **kwargs):
133138 -------
134139 proj : `~mpl_toolkits.basemap.Basemap` or `~cartopy.crs.Projection`
135140 The projection instance.
136- aspect : float
137- The map projection aspect ratio. This may change if user zooms
138- into a projection, but returning an initial guess helps avoid
139- unnecessarily calculations down the line.
140141
141142 See also
142143 --------
143144 `~proplot.axes.GeoAxes`, `~proplot.axes.BasemapAxes`
144145 """ # noqa
146+ # Class instances
147+ if ((CRS is not object and isinstance (name , CRS ))
148+ or (Basemap is not object and isinstance (name , Basemap ))):
149+ proj = name
150+ elif not isinstance (proj , str ):
151+ raise ValueError (
152+ f'Unexpected Proj() argument { proj !r} . '
153+ 'Must be name, mpl_toolkits.basemap.Basemap instance, '
154+ 'or cartopy.crs.CRS instance.'
155+ )
145156 # Basemap
146- if basemap :
157+ elif basemap :
147158 import mpl_toolkits .basemap as mbasemap
148159 name = BASEMAP_TRANSLATE .get (name , name )
149160 kwproj = basemap_kwargs .get (name , {})
@@ -158,8 +169,6 @@ def Proj(name, basemap=False, **kwargs):
158169 reso = kwproj .pop ('resolution' , None ) or kwproj .pop (
159170 'reso' , None ) or 'c'
160171 proj = mbasemap .Basemap (projection = name , resolution = reso , ** kwproj )
161- aspect = (proj .urcrnrx - proj .llcrnrx ) / \
162- (proj .urcrnry - proj .llcrnry )
163172 # Cartopy
164173 else :
165174 import cartopy .crs as _ # noqa
@@ -176,18 +185,17 @@ def Proj(name, basemap=False, **kwargs):
176185 if crs is None :
177186 raise ValueError (
178187 f'Unknown projection { name !r} . Options are: '
179- + ', ' .join (map (repr , cartopy_names .keys ()))
188+ + ', ' .join (map (repr , cartopy_names .keys ())) + '.'
180189 )
181190 proj = crs (** kwargs )
182- aspect = (np .diff (proj .x_limits ) / np .diff (proj .y_limits ))[0 ]
183- return proj , aspect
191+ return proj
184192
185193
186- class Hammer (_WarpedRectangularProjection ):
187- """The `Hammer <https://en.wikipedia.org/wiki/Hammer_projection >`__
194+ class Aitoff (_WarpedRectangularProjection ):
195+ """The `Aitoff <https://en.wikipedia.org/wiki/Aitoff_projection >`__
188196 projection."""
189197 #: Registered projection name.
190- name = 'hammer '
198+ name = 'aitoff '
191199
192200 def __init__ (self , central_longitude = 0 , globe = None ,
193201 false_easting = None , false_northing = None ):
@@ -204,11 +212,13 @@ def __init__(self, central_longitude=0, globe=None,
204212 'elliptical globes.'
205213 )
206214
207- proj4_params = {'proj' : 'hammer' , 'lon_0' : central_longitude }
208- super ().__init__ (proj4_params , central_longitude ,
209- false_easting = false_easting ,
210- false_northing = false_northing ,
211- globe = globe )
215+ proj4_params = {'proj' : 'aitoff' , 'lon_0' : central_longitude }
216+ super ().__init__ (
217+ proj4_params , central_longitude ,
218+ false_easting = false_easting ,
219+ false_northing = false_northing ,
220+ globe = globe
221+ )
212222
213223 @property
214224 def threshold (self ): # how finely to interpolate line data, etc.
@@ -218,11 +228,11 @@ def threshold(self): # how finely to interpolate line data, etc.
218228 threshold .__doc__ = _reso_doc
219229
220230
221- class Aitoff (_WarpedRectangularProjection ):
222- """The `Aitoff <https://en.wikipedia.org/wiki/Aitoff_projection >`__
231+ class Hammer (_WarpedRectangularProjection ):
232+ """The `Hammer <https://en.wikipedia.org/wiki/Hammer_projection >`__
223233 projection."""
224234 #: Registered projection name.
225- name = 'aitoff '
235+ name = 'hammer '
226236
227237 def __init__ (self , central_longitude = 0 , globe = None ,
228238 false_easting = None , false_northing = None ):
@@ -239,11 +249,13 @@ def __init__(self, central_longitude=0, globe=None,
239249 'elliptical globes.'
240250 )
241251
242- proj4_params = {'proj' : 'aitoff' , 'lon_0' : central_longitude }
243- super ().__init__ (proj4_params , central_longitude ,
244- false_easting = false_easting ,
245- false_northing = false_northing ,
246- globe = globe )
252+ proj4_params = {'proj' : 'hammer' , 'lon_0' : central_longitude }
253+ super ().__init__ (
254+ proj4_params , central_longitude ,
255+ false_easting = false_easting ,
256+ false_northing = false_northing ,
257+ globe = globe
258+ )
247259
248260 @property
249261 def threshold (self ): # how finely to interpolate line data, etc.
@@ -326,49 +338,60 @@ def threshold(self):
326338class NorthPolarAzimuthalEquidistant (AzimuthalEquidistant ):
327339 """Analogous to `~cartopy.crs.NorthPolarStereo`."""
328340 def __init__ (self , central_longitude = 0.0 , globe = None ):
329- super ().__init__ (central_latitude = 90 ,
330- central_longitude = central_longitude , globe = globe )
341+ super ().__init__ (
342+ central_latitude = 90 ,
343+ central_longitude = central_longitude , globe = globe
344+ )
331345 __init__ .__doc__ = _proj_doc
332346
333347
334348class SouthPolarAzimuthalEquidistant (AzimuthalEquidistant ):
335349 """Analogous to `~cartopy.crs.SouthPolarStereo`."""
336350 def __init__ (self , central_longitude = 0.0 , globe = None ):
337- super ().__init__ (central_latitude = - 90 ,
338- central_longitude = central_longitude , globe = globe )
351+ super ().__init__ (
352+ central_latitude = - 90 ,
353+ central_longitude = central_longitude , globe = globe
354+ )
339355 __init__ .__doc__ = _proj_doc
340356
341357
342358class NorthPolarLambertAzimuthalEqualArea (LambertAzimuthalEqualArea ):
343359 """Analogous to `~cartopy.crs.NorthPolarStereo`."""
344360 def __init__ (self , central_longitude = 0.0 , globe = None ):
345- super ().__init__ (central_latitude = 90 ,
346- central_longitude = central_longitude , globe = globe )
347-
361+ super ().__init__ (
362+ central_latitude = 90 ,
363+ central_longitude = central_longitude , globe = globe
364+ )
348365 __init__ .__doc__ = _proj_doc
349366
350367
351368class SouthPolarLambertAzimuthalEqualArea (LambertAzimuthalEqualArea ):
352369 """Analogous to `~cartopy.crs.SouthPolarStereo`."""
353370 def __init__ (self , central_longitude = 0.0 , globe = None ):
354- super ().__init__ (central_latitude = - 90 ,
355- central_longitude = central_longitude , globe = globe )
371+ super ().__init__ (
372+ central_latitude = - 90 ,
373+ central_longitude = central_longitude , globe = globe
374+ )
356375 __init__ .__doc__ = _proj_doc
357376
358377
359378class NorthPolarGnomonic (Gnomonic ):
360379 """Analogous to `~cartopy.crs.SouthPolarStereo`."""
361380 def __init__ (self , central_longitude = 0.0 , globe = None ):
362- super ().__init__ (central_latitude = 90 ,
363- central_longitude = central_longitude , globe = globe )
381+ super ().__init__ (
382+ central_latitude = 90 ,
383+ central_longitude = central_longitude , globe = globe
384+ )
364385 __init__ .__doc__ = _proj_doc
365386
366387
367388class SouthPolarGnomonic (Gnomonic ):
368389 """Analogous to `~cartopy.crs.SouthPolarStereo`."""
369390 def __init__ (self , central_longitude = 0.0 , globe = None ):
370- super ().__init__ (central_latitude = - 90 ,
371- central_longitude = central_longitude , globe = globe )
391+ super ().__init__ (
392+ central_latitude = - 90 ,
393+ central_longitude = central_longitude , globe = globe
394+ )
372395 __init__ .__doc__ = _proj_doc
373396
374397
@@ -420,7 +443,7 @@ def __init__(self, central_longitude=0.0, globe=None):
420443
421444#: Mapping of "projection names" to cartopy `~cartopy.crs.Projection` classes.
422445cartopy_names = {}
423- if _cartopy_installed :
446+ if CRS is not object :
424447 # Custom ones, these are always present
425448 import cartopy .crs as ccrs # verify package is available
426449 cartopy_names = { # interpret string, create cartopy projection
0 commit comments