Skip to content

Commit 613ab0e

Browse files
committed
Rename basemap keyword/setting to [geo.]backend
1 parent f95b828 commit 613ab0e

7 files changed

Lines changed: 198 additions & 176 deletions

File tree

docs/projections.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@
8989
# to work with the projection classes directly, they are available in the
9090
# top-level namespace (e.g., ``proj=pplt.PlateCarre()`` is allowed).
9191
#
92-
# * Basemap is an alternative backend. To use basemap, set :rcraw:`basemap` to
93-
# ``True`` or pass ``basemap=True`` to the axes-creation command. When you
94-
# request a projection name with basemap as the backend (or pass a
92+
# * Basemap is an alternative backend. To use basemap, set :rcraw:`geo.backend` to
93+
# ``'basemap'`` or pass ``backend='basemap'`` to the axes-creation command. When
94+
# you request a projection name with basemap as the backend (or pass a
9595
# `~mpl_toolkits.basemap.Basemap` to the `proj` keyword), the returned axes
9696
# redirects the plotting methods plot, scatter, contour, contourf, pcolor,
9797
# pcolormesh, quiver, streamplot, and barb to the identically named methods on
@@ -148,14 +148,14 @@
148148
# Add projections
149149
gs = pplt.GridSpec(ncols=2, nrows=3, hratios=(1, 1, 1.4))
150150
for i, proj in enumerate(('cyl', 'hammer', 'npstere')):
151-
ax1 = fig.subplot(gs[i, 0], proj=proj, basemap=True) # basemap
152-
ax2 = fig.subplot(gs[i, 1], proj=proj) # cartopy
151+
ax1 = fig.subplot(gs[i, 0], proj=proj) # default cartopy backend
152+
ax2 = fig.subplot(gs[i, 1], proj=proj, backend='basemap') # basemap backend
153153

154154
# Format projections
155155
fig.format(
156156
land=True,
157157
suptitle='Figure with several projections',
158-
toplabels=('Basemap projections', 'Cartopy projections'),
158+
toplabels=('Cartopy examples', 'Basemap examples'),
159159
toplabelweight='normal',
160160
latlines=30, lonlines=60,
161161
lonlabels='b', latlabels='r', # or lonlabels=True, labels=True, etc.
@@ -206,8 +206,9 @@
206206
gs = pplt.GridSpec(nrows=2, ncols=2)
207207
fig = pplt.figure(refwidth=2.5)
208208
for i, ss in enumerate(gs):
209-
ax = fig.subplot(ss, proj='kav7', basemap=(i % 2))
210209
cmap = ('sunset', 'sunrise')[i % 2]
210+
backend = ('cartopy', 'basemap')[i % 2]
211+
ax = fig.subplot(ss, proj='kav7', backend=backend)
211212
if i > 1:
212213
ax.pcolor(lon, lat, data, cmap=cmap, globe=globe, extend='both')
213214
else:
@@ -319,7 +320,7 @@
319320

320321
# Plate Carrée map projection
321322
pplt.rc.reso = 'med' # use higher res for zoomed in geographic features
322-
basemap = pplt.Proj('cyl', lonlim=(-20, 180), latlim=(-10, 50), basemap=True)
323+
basemap = pplt.Proj('cyl', lonlim=(-20, 180), latlim=(-10, 50), backend='basemap')
323324
fig, axs = pplt.subplots(nrows=2, refwidth=5, proj=('cyl', basemap))
324325
axs.format(
325326
land=True, labels=True, lonlines=20, latlines=20,
@@ -333,7 +334,7 @@
333334
import proplot as pplt
334335

335336
# Pole-centered map projections
336-
basemap = pplt.Proj('npaeqd', boundinglat=60, basemap=True)
337+
basemap = pplt.Proj('npaeqd', boundinglat=60, backend='basemap')
337338
fig, axs = pplt.subplots(ncols=2, refwidth=2.7, proj=('splaea', basemap))
338339
fig.format(suptitle='Zooming into polar projections')
339340
axs.format(land=True, latmax=80) # no gridlines poleward of 80 degrees
@@ -347,7 +348,7 @@
347348
fig = pplt.figure(refwidth=3)
348349
ax = fig.subplot(121, proj='lcc', proj_kw={'lon_0': 0})
349350
ax.format(lonlim=(-20, 50), latlim=(30, 70), title='Cartopy example')
350-
proj = pplt.Proj('lcc', lon_0=-100, lat_0=45, width=8e6, height=8e6, basemap=True)
351+
proj = pplt.Proj('lcc', lon_0=-100, lat_0=45, width=8e6, height=8e6, backend='basemap')
351352
ax = fig.subplot(122, proj=proj)
352353
ax.format(lonlines=20, title='Basemap example')
353354
fig.format(suptitle='Zooming into specific regions', land=True)
@@ -419,7 +420,7 @@
419420
'vandg', 'aea', 'eqdc', 'gnom', 'cass', 'lcc',
420421
'npstere', 'npaeqd', 'nplaea'
421422
]
422-
fig, axs = pplt.subplots(ncols=3, nrows=8, basemap=True, figwidth=7, proj=projs)
423+
fig, axs = pplt.subplots(ncols=3, nrows=8, figwidth=7, proj=projs, backend='basemap')
423424
axs.format(
424425
land=True, labels=False,
425426
suptitle='Table of basemap projections'

proplot/axes/base.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,14 @@
107107
Keyword arguments passed to `~mpl_toolkits.basemap.Basemap` or
108108
cartopy `~cartopy.crs.Projection` classes on instantiation.
109109
"""
110-
_basemap_docstring = """
111-
basemap : bool or dict-like, default: :rc:`basemap`
110+
_backend_docstring = """
111+
backend : {'cartopy', 'basemap'}, default: :rc:`geo.backend`
112112
Whether to use `~mpl_toolkits.basemap.Basemap` or
113113
`~cartopy.crs.Projection` for map projections.
114114
"""
115115
docstring._snippet_manager['axes.proj'] = _proj_docstring
116116
docstring._snippet_manager['axes.proj_kw'] = _proj_kw_docstring
117-
docstring._snippet_manager['axes.basemap'] = _basemap_docstring
117+
docstring._snippet_manager['axes.backend'] = _backend_docstring
118118

119119

120120
# Colorbar and legend space
@@ -180,7 +180,7 @@
180180
Default is to use the same projection as the current axes.
181181
%(axes.proj)s
182182
%(axes.proj_kw)s
183-
%(axes.basemap)s
183+
%(axes.backend)s
184184
zorder : float, default: 4
185185
The `zorder <https://matplotlib.org/stable/gallery/misc/zorder_demo.html>`__
186186
of the axes. Should be greater than the zorder of elements in the parent axes.

proplot/config.py

Lines changed: 60 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ def __getitem__(self, key):
736736
Return an `rc_matplotlib` or `rc_proplot` setting using dictionary notation
737737
(e.g., ``value = pplt.rc[name]``).
738738
"""
739-
key = self._validate_key(key) # might issue proplot removed/renamed error
739+
key, _ = self._validate_key(key) # might issue proplot removed/renamed error
740740
try:
741741
return rc_proplot[key]
742742
except KeyError:
@@ -748,7 +748,7 @@ def __setitem__(self, key, value):
748748
Modify an `rc_matplotlib` or `rc_proplot` setting using dictionary notation
749749
(e.g., ``pplt.rc[name] = value``).
750750
"""
751-
kw_proplot, kw_matplotlib = self._item_dicts(key, value)
751+
kw_proplot, kw_matplotlib = self._get_item_dicts(key, value)
752752
rc_proplot.update(kw_proplot)
753753
rc_matplotlib.update(kw_matplotlib)
754754

@@ -782,10 +782,10 @@ def __enter__(self):
782782
)
783783
context = self._context[-1]
784784
kwargs = context.kwargs
785-
rc_new = context.rc_new # used for context-based _item_context
785+
rc_new = context.rc_new # used for context-based _get_item_context
786786
rc_old = context.rc_old # used to re-apply settings without copying whole dict
787787
for key, value in kwargs.items():
788-
kw_proplot, kw_matplotlib = self._item_dicts(key, value)
788+
kw_proplot, kw_matplotlib = self._get_item_dicts(key, value)
789789
for rc_dict, kw_new in zip(
790790
(rc_proplot, rc_matplotlib),
791791
(kw_proplot, kw_matplotlib),
@@ -804,42 +804,11 @@ def __exit__(self, *args): # noqa: U100
804804
)
805805
context = self._context[-1]
806806
for key, value in context.rc_old.items():
807-
kw_proplot, kw_matplotlib = self._item_dicts(key, value)
807+
kw_proplot, kw_matplotlib = self._get_item_dicts(key, value)
808808
rc_proplot.update(kw_proplot)
809809
rc_matplotlib.update(kw_matplotlib)
810810
del self._context[-1]
811811

812-
@staticmethod
813-
def _validate_key(key):
814-
"""
815-
Ensure string and convert keys with omitted dots.
816-
"""
817-
if not isinstance(key, str):
818-
raise KeyError(f'Invalid key {key!r}. Must be string.')
819-
if '.' not in key:
820-
key = rcsetup._rc_nodots.get(key, key)
821-
key = rc_proplot._check_key(key) # may issue deprecation warning
822-
return key.lower()
823-
824-
@staticmethod
825-
def _validate_value(key, value):
826-
"""
827-
Convert numpy ndarray to list and validate if possible.
828-
"""
829-
# NOTE: Ideally would implicitly validate on subsequent assignment to rc
830-
# dictionaries, but must explicitly do it here, so _item_dicts can 'sync'
831-
# settings with children (e.g. multiplying tick widths by width ratios)
832-
# and so _load_file() can catch errors and emit warnings before assignment.
833-
if isinstance(value, np.ndarray):
834-
value = value.item() if value.size == 1 else value.tolist()
835-
validate = getattr(rc_matplotlib, 'validate', None)
836-
validate_proplot = rc_proplot._validate
837-
if validate is not None and key in validate: # guard against API change
838-
value = validate[key](value)
839-
elif key in validate_proplot:
840-
value = validate_proplot[key](value)
841-
return value
842-
843812
def _init(self, *, local, user, default, skip_cycle=False):
844813
"""
845814
Initialize the configurator.
@@ -854,7 +823,7 @@ def _init(self, *, local, user, default, skip_cycle=False):
854823
rc_matplotlib.update(rcsetup._rc_matplotlib_default)
855824
rc_proplot.update(rcsetup._rc_proplot_default)
856825
for key, value in rc_proplot.items():
857-
kw_proplot, kw_matplotlib = self._item_dicts(
826+
kw_proplot, kw_matplotlib = self._get_item_dicts(
858827
key, value, skip_cycle=skip_cycle
859828
)
860829
rc_matplotlib.update(kw_matplotlib)
@@ -875,12 +844,49 @@ def _init(self, *, local, user, default, skip_cycle=False):
875844
continue
876845
self.load(path)
877846

878-
def _item_context(self, key, mode=None):
847+
@staticmethod
848+
def _validate_key(key, value=None):
849+
"""
850+
Validate setting names and handle `rc_proplot` deprecations.
851+
"""
852+
# NOTE: Not necessary to check matplotlib key here because... not sure why.
853+
# Think deprecated matplotlib keys are not involved in any synced settings.
854+
# Also note _check_key includes special handling for some renamed keys.
855+
if not isinstance(key, str):
856+
raise KeyError(f'Invalid key {key!r}. Must be string.')
857+
key = key.lower()
858+
if '.' not in key:
859+
key = rcsetup._rc_nodots.get(key, key)
860+
key, value = rc_proplot._check_key(key, value) # may issue deprecation warning
861+
return key, value
862+
863+
@staticmethod
864+
def _validate_value(key, value):
865+
"""
866+
Validate setting values and convert numpy ndarray to list if possible.
867+
"""
868+
# NOTE: Ideally would implicitly validate on subsequent assignment to rc
869+
# dictionaries, but must explicitly do it here, so _get_item_dicts can
870+
# work with e.g. 'tick.lenratio', so _get_item_dicts does not have to include
871+
# deprecated name handling in its if statements, and so _load_file can
872+
# catch errors and emit warnings with line number indications as files
873+
# are being read rather than after the end of the file reading.
874+
if isinstance(value, np.ndarray):
875+
value = value.item() if value.size == 1 else value.tolist()
876+
validate_matplotlib = getattr(rc_matplotlib, 'validate', None)
877+
validate_proplot = rc_proplot._validate
878+
if validate_matplotlib is not None and key in validate_matplotlib:
879+
value = validate_matplotlib[key](value)
880+
elif key in validate_proplot:
881+
value = validate_proplot[key](value)
882+
return value
883+
884+
def _get_item_context(self, key, mode=None):
879885
"""
880886
As with `~Configurator.__getitem__` but the search is limited based
881887
on the context mode and ``None`` is returned if the key is not found.
882888
"""
883-
key = self._validate_key(key)
889+
key, _ = self._validate_key(key)
884890
if mode is None:
885891
mode = self._context_mode
886892
cache = tuple(context.rc_new for context in self._context)
@@ -902,14 +908,14 @@ def _item_context(self, key, mode=None):
902908
if mode == 0: # otherwise return None
903909
raise KeyError(f'Invalid rc setting {key!r}.')
904910

905-
def _item_dicts(self, key, value, skip_cycle=False):
911+
def _get_item_dicts(self, key, value, skip_cycle=False):
906912
"""
907913
Return dictionaries for updating the `rc_proplot` and `rc_matplotlib`
908914
properties associated with this key. Used when setting items, entering
909915
context blocks, or loading files.
910916
"""
911917
# Get validated key, value, and child keys
912-
key = self._validate_key(key)
918+
key, value = self._validate_key(key, value)
913919
value = self._validate_value(key, value)
914920
keys = (key,) + rcsetup._rc_children.get(key, ()) # settings to change
915921
contains = lambda *args: any(arg in keys for arg in args) # noqa: E731
@@ -1016,7 +1022,7 @@ def _item_dicts(self, key, value, skip_cycle=False):
10161022
return kw_proplot, kw_matplotlib
10171023

10181024
@staticmethod
1019-
def _axisbelow_to_zorder(axisbelow):
1025+
def _get_axisbelow_zorder(axisbelow):
10201026
"""
10211027
Convert the `axisbelow` string to its corresponding `zorder`.
10221028
"""
@@ -1112,7 +1118,7 @@ def _get_gridline_props(self, which='major', native=True, rebuild=False):
11121118
if native: # this is a native plot so use set_axisbelow() down the line
11131119
kwlines['axisbelow'] = axisbelow
11141120
else: # this is a geographic plot so apply with zorder
1115-
kwlines['zorder'] = self._axisbelow_to_zorder(axisbelow)
1121+
kwlines['zorder'] = self._get_axisbelow_zorder(axisbelow)
11161122
return kwlines
11171123

11181124
def _get_label_props(self, native=True, **kwargs):
@@ -1349,8 +1355,8 @@ def context(self, *args, mode=0, file=None, **kwargs):
13491355
file : path-like, optional
13501356
Filename from which settings should be loaded.
13511357
**kwargs
1352-
`rc` names and values passed as keyword arguments. If the
1353-
name has dots, simply omit them.
1358+
`rc` names and values passed as keyword arguments.
1359+
If the name has dots, simply omit them.
13541360
13551361
Other parameters
13561362
----------------
@@ -1363,16 +1369,16 @@ def context(self, *args, mode=0, file=None, **kwargs):
13631369
13641370
* ``mode=0``: Matplotlib's `rc_matplotlib` settings
13651371
and proplot's `rc_proplot` settings are all returned,
1366-
whether they are local to the "with as" block.
1372+
whether or not they are local to the "with as" block.
13671373
* ``mode=1``: Matplotlib's `rc_matplotlib` settings are only
13681374
returned if they are local to the "with as" block. For example,
13691375
if :rcraw:`axes.titlesize` was passed to `~Configurator.context`,
13701376
then ``pplt.rc.find('axes.titlesize', context=True)`` will return
1371-
this value, but ``pplt.rc.find('axes.titleweight', context=True)``
1372-
will return ``None``.
1377+
this value, but ``pplt.rc.find('axes.titleweight', context=True)`` will
1378+
return ``None``. This is used internally when instantiating axes.
13731379
* ``mode=2``: Matplotlib's `rc_matplotlib` settings and proplot's
13741380
`rc_proplot` settings are only returned if they are local to the
1375-
"with as" block.
1381+
"with as" block. This is used internally when formatting axes.
13761382
13771383
Note
13781384
----
@@ -1451,7 +1457,7 @@ def category(self, cat, *, trimcat=True, context=False):
14511457
for key in self:
14521458
if not re.match(fr'\A{cat}\.[^.]+\Z', key):
14531459
continue
1454-
value = self._item_context(key, None if context else 0)
1460+
value = self._get_item_context(key, None if context else 0)
14551461
if value is None:
14561462
continue
14571463
if trimcat:
@@ -1480,7 +1486,7 @@ def fill(self, props, *, context=False):
14801486
"""
14811487
kw = {}
14821488
for key, value in props.items():
1483-
item = self._item_context(value, None if context else 0)
1489+
item = self._get_item_context(value, None if context else 0)
14841490
if item is not None:
14851491
kw[key] = item
14861492
return kw
@@ -1502,7 +1508,7 @@ def find(self, key, *, context=False):
15021508
Configurator.category
15031509
Configurator.fill
15041510
"""
1505-
return self._item_context(key, None if context else 0)
1511+
return self._get_item_context(key, None if context else 0)
15061512

15071513
def update(self, *args, **kwargs):
15081514
"""
@@ -1586,7 +1592,7 @@ def _load_file(self, path):
15861592
with warnings.catch_warnings():
15871593
warnings.simplefilter('error', warnings.ProplotWarning)
15881594
try:
1589-
ikw_proplot, ikw_matplotlib = self._item_dicts(key, val)
1595+
ikw_proplot, ikw_matplotlib = self._get_item_dicts(key, val)
15901596
except KeyError:
15911597
warnings._warn_proplot(
15921598
f'Invalid rc key {key!r} on {message}.', 'default'
@@ -1602,7 +1608,7 @@ def _load_file(self, path):
16021608
f'Outdated rc key {key!r} on {message}: {err}', 'default'
16031609
)
16041610
warnings.simplefilter('ignore', warnings.ProplotWarning)
1605-
ikw_proplot, ikw_matplotlib = self._item_dicts(key, val)
1611+
ikw_proplot, ikw_matplotlib = self._get_item_dicts(key, val)
16061612
# Update the settings
16071613
kw_proplot.update(ikw_proplot)
16081614
kw_matplotlib.update(ikw_matplotlib)

0 commit comments

Comments
 (0)