我试图创建气象数据的垂直截面。我希望主图是一个普通的 matplotlib 图,显示垂直横截面数据,右上角的插图显示地图上横截面的位置。我之前已经能够使用Figure.add_axes在其他图中插入cartopy GeoAxes,所以我很惊讶它在这里使用inset_axes失败了。
更令人困惑的是,该错误被报告为插入轴的脊柱字典中关键字“geo”的 KeyError 。但是,打印插入轴的脊柱会显示关键字和关联的脊柱对象。
要重现的示例代码:
%matplotlib inline #This problem was encountered in a jupyter notebook,
#but I have no reason to think it wouldn't be the same in python
import matplotlib.pyplot as plt
from matplotlib.style import use as usestyle
from matplotlib import colors
from matplotlib.colors import BoundaryNorm
import matplotlib as mpl
import cartopy.crs as ccrs
from cartopy import feature as cfeature
from matplotlib.lines import Line2D
ramscrs = ccrs.Stereographic(central_longitude = -80, central_latitude = 42)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize = (4,8), dpi = 200, layout = "constrained")
axinset = ax1.inset_axes([0.75, 0.75, 0.25, 0.25], projection = ramscrs, zorder = 2)
print(type(axinset))
print(list(axinset.spines.keys()))
print(axinset.spines['geo'])
print(axinset.spines['geo'].stale)
错误回溯:
Error in callback <function _draw_all_if_interactive at 0x7f745c98ea70> (for post_execute):
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/pyplot.py:120, in _draw_all_if_interactive()
118 def _draw_all_if_interactive():
119 if matplotlib.is_interactive():
--> 120 draw_all()
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/_pylab_helpers.py:132, in Gcf.draw_all(cls, force)
130 for manager in cls.get_all_fig_managers():
131 if force or manager.canvas.figure.stale:
--> 132 manager.canvas.draw_idle()
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/backend_bases.py:2082, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
2080 if not self._is_idle_drawing:
2081 with self._idle_draw_cntx():
-> 2082 self.draw(*args, **kwargs)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:400, in FigureCanvasAgg.draw(self)
396 # Acquire a lock on the shared font cache.
397 with RendererAgg.lock, \
398 (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
399 else nullcontext()):
--> 400 self.figure.draw(self.renderer)
401 # A GUI class may be need to update a window using this draw, so
402 # don't forget to call the superclass.
403 super().draw()
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
93 @wraps(draw)
94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95 result = draw(artist, renderer, *args, **kwargs)
96 if renderer._rasterizing:
97 renderer.stop_rasterizing()
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
69 if artist.get_agg_filter() is not None:
70 renderer.start_filter()
---> 72 return draw(artist, renderer)
73 finally:
74 if artist.get_agg_filter() is not None:
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/figure.py:3169, in Figure.draw(self, renderer)
3167 if self.axes and self.get_layout_engine() is not None:
3168 try:
-> 3169 self.get_layout_engine().execute(self)
3170 except ValueError:
3171 pass
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/layout_engine.py:274, in ConstrainedLayoutEngine.execute(self, fig)
271 w_pad = self._params['w_pad'] / width
272 h_pad = self._params['h_pad'] / height
--> 274 return do_constrained_layout(fig, w_pad=w_pad, h_pad=h_pad,
275 wspace=self._params['wspace'],
276 hspace=self._params['hspace'],
277 rect=self._params['rect'],
278 compress=self._compress)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/_constrained_layout.py:119, in do_constrained_layout(fig, h_pad, w_pad, hspace, wspace, rect, compress)
109 return
111 for _ in range(2):
112 # do the algorithm twice. This has to be done because decorations
113 # change size after the first re-position (i.e. x/yticklabels get
(...)
117 # make margins for all the axes and subfigures in the
118 # figure. Add margins for colorbars...
--> 119 make_layout_margins(layoutgrids, fig, renderer, h_pad=h_pad,
120 w_pad=w_pad, hspace=hspace, wspace=wspace)
121 make_margin_suptitles(layoutgrids, fig, renderer, h_pad=h_pad,
122 w_pad=w_pad)
124 # if a layout is such that a columns (or rows) margin has no
125 # constraints, we need to make all such instances in the grid
126 # match in margin size.
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/_constrained_layout.py:371, in make_layout_margins(layoutgrids, fig, renderer, w_pad, h_pad, hspace, wspace)
367 return
369 margin = get_margin_from_padding(ax, w_pad=w_pad, h_pad=h_pad,
370 hspace=hspace, wspace=wspace)
--> 371 pos, bbox = get_pos_and_bbox(ax, renderer)
372 # the margin is the distance between the bounding box of the axes
373 # and its position (plus the padding from above)
374 margin['left'] += pos.x0 - bbox.x0
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/_constrained_layout.py:619, in get_pos_and_bbox(ax, renderer)
617 # pos is in panel co-ords, but we need in figure for the layout
618 pos = pos.transformed(fig.transSubfigure - fig.transFigure)
--> 619 tightbbox = martist._get_tightbbox_for_layout_only(ax, renderer)
620 if tightbbox is None:
621 bbox = pos
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/artist.py:1415, in _get_tightbbox_for_layout_only(obj, *args, **kwargs)
1409 """
1410 Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a
1411 *for_layout_only* kwarg; this helper tries to use the kwarg but skips it
1412 when encountering third-party subclasses that do not support it.
1413 """
1414 try:
-> 1415 return obj.get_tightbbox(*args, **{**kwargs, "for_layout_only": True})
1416 except TypeError:
1417 return obj.get_tightbbox(*args, **kwargs)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axes/_base.py:4408, in _AxesBase.get_tightbbox(self, renderer, call_axes_locator, bbox_extra_artists, for_layout_only)
4405 bbox_artists = self.get_default_bbox_extra_artists()
4407 for a in bbox_artists:
-> 4408 bbox = a.get_tightbbox(renderer)
4409 if (bbox is not None
4410 and 0 < bbox.width < np.inf
4411 and 0 < bbox.height < np.inf):
4412 bb.append(bbox)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:506, in GeoAxes.get_tightbbox(self, renderer, *args, **kwargs)
498 """
499 Extend the standard behaviour of
500 :func:`matplotlib.axes.Axes.get_tightbbox`.
(...)
503 gridliners before calculating the tight bounding box.
504 """
505 # Shared processing steps
--> 506 self._draw_preprocess(renderer)
508 return super().get_tightbbox(renderer, *args, **kwargs)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:487, in GeoAxes._draw_preprocess(self, renderer)
484 # If data has been added (i.e. autoscale hasn't been turned off)
485 # then we should autoscale the view.
486 if self.get_autoscale_on() and self.ignore_existing_data_limits:
--> 487 self.autoscale_view()
489 # Adjust location of background patch so that new gridlines below are
490 # clipped correctly.
491 self.patch._adjust_location()
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:897, in GeoAxes.autoscale_view(self, tight, scalex, scaley)
890 def autoscale_view(self, tight=None, scalex=True, scaley=True):
891 """
892 Autoscale the view limits using the data limits, taking into
893 account the projection of the geoaxes.
894
895 See :meth:`~matplotlib.axes.Axes.imshow()` for more details.
896 """
--> 897 super().autoscale_view(tight=tight, scalex=scalex, scaley=scaley)
898 # Limit the resulting bounds to valid area.
899 if scalex and self.get_autoscalex_on():
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axes/_base.py:2930, in _AxesBase.autoscale_view(self, tight, scalex, scaley)
2927 set_bound(x0, x1)
2928 # End of definition of internal function 'handle_single_axis'.
-> 2930 handle_single_axis(
2931 scalex, self._shared_axes["x"], 'x', self.xaxis, self._xmargin,
2932 x_stickies, self.set_xbound)
2933 handle_single_axis(
2934 scaley, self._shared_axes["y"], 'y', self.yaxis, self._ymargin,
2935 y_stickies, self.set_ybound)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axes/_base.py:2927, in _AxesBase.autoscale_view.<locals>.handle_single_axis(scale, shared_axes, name, axis, margin, stickies, set_bound)
2925 if not self._tight:
2926 x0, x1 = locator.view_limits(x0, x1)
-> 2927 set_bound(x0, x1)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axes/_base.py:3530, in _AxesBase.set_xbound(self, lower, upper)
3527 if upper is None:
3528 upper = old_upper
-> 3530 self.set_xlim(sorted((lower, upper),
3531 reverse=bool(self.xaxis_inverted())),
3532 auto=None)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/_api/deprecation.py:454, in make_keyword_only.<locals>.wrapper(*args, **kwargs)
448 if len(args) > name_idx:
449 warn_deprecated(
450 since, message="Passing the %(name)s %(obj_type)s "
451 "positionally is deprecated since Matplotlib %(since)s; the "
452 "parameter will become keyword-only %(removal)s.",
453 name=name, obj_type=f"parameter of {func.__name__}()")
--> 454 return func(*args, **kwargs)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axes/_base.py:3650, in _AxesBase.set_xlim(self, left, right, emit, auto, xmin, xmax)
3648 raise TypeError("Cannot pass both 'right' and 'xmax'")
3649 right = xmax
-> 3650 return self.xaxis._set_lim(left, right, emit=emit, auto=auto)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axis.py:1225, in Axis._set_lim(self, v0, v1, emit, auto)
1222 self._set_autoscale_on(bool(auto))
1224 if emit:
-> 1225 self.axes.callbacks.process(f"{name}lim_changed", self.axes)
1226 # Call all of the other axes that are shared with this one
1227 for other in self.axes._shared_axes[name].get_siblings(self.axes):
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/cbook/__init__.py:314, in CallbackRegistry.process(self, s, *args, **kwargs)
312 except Exception as exc:
313 if self.exception_handler is not None:
--> 314 self.exception_handler(exc)
315 else:
316 raise
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/cbook/__init__.py:98, in _exception_printer(exc)
96 def _exception_printer(exc):
97 if _get_running_interactive_framework() in ["headless", None]:
---> 98 raise exc
99 else:
100 traceback.print_exc()
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/cbook/__init__.py:309, in CallbackRegistry.process(self, s, *args, **kwargs)
307 if func is not None:
308 try:
--> 309 func(*args, **kwargs)
310 # this does not capture KeyboardInterrupt, SystemExit,
311 # and GeneratorExit
312 except Exception as exc:
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:2317, in _trigger_patch_reclip(event)
2315 axes = event.axes
2316 # trigger the outline and background patches to be re-clipped
-> 2317 axes.spines['geo'].stale = True
2318 axes.patch.stale = True
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/spines.py:574, in Spines.__getitem__(self, key)
570 else:
571 raise ValueError(
572 'Spines does not support slicing except for the fully '
573 'open slice [:] to access all spines.')
--> 574 return self._dict[key]
KeyError: 'geo'
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/IPython/core/formatters.py:340, in BaseFormatter.__call__(self, obj)
338 pass
339 else:
--> 340 return printer(obj)
341 # Finally look for special method names
342 method = get_real_method(obj, self.print_method)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/IPython/core/pylabtools.py:152, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
149 from matplotlib.backend_bases import FigureCanvasBase
150 FigureCanvasBase(fig)
--> 152 fig.canvas.print_figure(bytes_io, **kw)
153 data = bytes_io.getvalue()
154 if fmt == 'svg':
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/backend_bases.py:2342, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2336 renderer = _get_renderer(
2337 self.figure,
2338 functools.partial(
2339 print_method, orientation=orientation)
2340 )
2341 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2342 self.figure.draw(renderer)
2344 if bbox_inches:
2345 if bbox_inches == "tight":
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
93 @wraps(draw)
94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95 result = draw(artist, renderer, *args, **kwargs)
96 if renderer._rasterizing:
97 renderer.stop_rasterizing()
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
69 if artist.get_agg_filter() is not None:
70 renderer.start_filter()
---> 72 return draw(artist, renderer)
73 finally:
74 if artist.get_agg_filter() is not None:
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/figure.py:3169, in Figure.draw(self, renderer)
3167 if self.axes and self.get_layout_engine() is not None:
3168 try:
-> 3169 self.get_layout_engine().execute(self)
3170 except ValueError:
3171 pass
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/layout_engine.py:274, in ConstrainedLayoutEngine.execute(self, fig)
271 w_pad = self._params['w_pad'] / width
272 h_pad = self._params['h_pad'] / height
--> 274 return do_constrained_layout(fig, w_pad=w_pad, h_pad=h_pad,
275 wspace=self._params['wspace'],
276 hspace=self._params['hspace'],
277 rect=self._params['rect'],
278 compress=self._compress)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/_constrained_layout.py:119, in do_constrained_layout(fig, h_pad, w_pad, hspace, wspace, rect, compress)
109 return
111 for _ in range(2):
112 # do the algorithm twice. This has to be done because decorations
113 # change size after the first re-position (i.e. x/yticklabels get
(...)
117 # make margins for all the axes and subfigures in the
118 # figure. Add margins for colorbars...
--> 119 make_layout_margins(layoutgrids, fig, renderer, h_pad=h_pad,
120 w_pad=w_pad, hspace=hspace, wspace=wspace)
121 make_margin_suptitles(layoutgrids, fig, renderer, h_pad=h_pad,
122 w_pad=w_pad)
124 # if a layout is such that a columns (or rows) margin has no
125 # constraints, we need to make all such instances in the grid
126 # match in margin size.
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/_constrained_layout.py:371, in make_layout_margins(layoutgrids, fig, renderer, w_pad, h_pad, hspace, wspace)
367 return
369 margin = get_margin_from_padding(ax, w_pad=w_pad, h_pad=h_pad,
370 hspace=hspace, wspace=wspace)
--> 371 pos, bbox = get_pos_and_bbox(ax, renderer)
372 # the margin is the distance between the bounding box of the axes
373 # and its position (plus the padding from above)
374 margin['left'] += pos.x0 - bbox.x0
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/_constrained_layout.py:619, in get_pos_and_bbox(ax, renderer)
617 # pos is in panel co-ords, but we need in figure for the layout
618 pos = pos.transformed(fig.transSubfigure - fig.transFigure)
--> 619 tightbbox = martist._get_tightbbox_for_layout_only(ax, renderer)
620 if tightbbox is None:
621 bbox = pos
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/artist.py:1415, in _get_tightbbox_for_layout_only(obj, *args, **kwargs)
1409 """
1410 Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a
1411 *for_layout_only* kwarg; this helper tries to use the kwarg but skips it
1412 when encountering third-party subclasses that do not support it.
1413 """
1414 try:
-> 1415 return obj.get_tightbbox(*args, **{**kwargs, "for_layout_only": True})
1416 except TypeError:
1417 return obj.get_tightbbox(*args, **kwargs)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axes/_base.py:4408, in _AxesBase.get_tightbbox(self, renderer, call_axes_locator, bbox_extra_artists, for_layout_only)
4405 bbox_artists = self.get_default_bbox_extra_artists()
4407 for a in bbox_artists:
-> 4408 bbox = a.get_tightbbox(renderer)
4409 if (bbox is not None
4410 and 0 < bbox.width < np.inf
4411 and 0 < bbox.height < np.inf):
4412 bb.append(bbox)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:506, in GeoAxes.get_tightbbox(self, renderer, *args, **kwargs)
498 """
499 Extend the standard behaviour of
500 :func:`matplotlib.axes.Axes.get_tightbbox`.
(...)
503 gridliners before calculating the tight bounding box.
504 """
505 # Shared processing steps
--> 506 self._draw_preprocess(renderer)
508 return super().get_tightbbox(renderer, *args, **kwargs)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:487, in GeoAxes._draw_preprocess(self, renderer)
484 # If data has been added (i.e. autoscale hasn't been turned off)
485 # then we should autoscale the view.
486 if self.get_autoscale_on() and self.ignore_existing_data_limits:
--> 487 self.autoscale_view()
489 # Adjust location of background patch so that new gridlines below are
490 # clipped correctly.
491 self.patch._adjust_location()
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:897, in GeoAxes.autoscale_view(self, tight, scalex, scaley)
890 def autoscale_view(self, tight=None, scalex=True, scaley=True):
891 """
892 Autoscale the view limits using the data limits, taking into
893 account the projection of the geoaxes.
894
895 See :meth:`~matplotlib.axes.Axes.imshow()` for more details.
896 """
--> 897 super().autoscale_view(tight=tight, scalex=scalex, scaley=scaley)
898 # Limit the resulting bounds to valid area.
899 if scalex and self.get_autoscalex_on():
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axes/_base.py:2930, in _AxesBase.autoscale_view(self, tight, scalex, scaley)
2927 set_bound(x0, x1)
2928 # End of definition of internal function 'handle_single_axis'.
-> 2930 handle_single_axis(
2931 scalex, self._shared_axes["x"], 'x', self.xaxis, self._xmargin,
2932 x_stickies, self.set_xbound)
2933 handle_single_axis(
2934 scaley, self._shared_axes["y"], 'y', self.yaxis, self._ymargin,
2935 y_stickies, self.set_ybound)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axes/_base.py:2927, in _AxesBase.autoscale_view.<locals>.handle_single_axis(scale, shared_axes, name, axis, margin, stickies, set_bound)
2925 if not self._tight:
2926 x0, x1 = locator.view_limits(x0, x1)
-> 2927 set_bound(x0, x1)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axes/_base.py:3530, in _AxesBase.set_xbound(self, lower, upper)
3527 if upper is None:
3528 upper = old_upper
-> 3530 self.set_xlim(sorted((lower, upper),
3531 reverse=bool(self.xaxis_inverted())),
3532 auto=None)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/_api/deprecation.py:454, in make_keyword_only.<locals>.wrapper(*args, **kwargs)
448 if len(args) > name_idx:
449 warn_deprecated(
450 since, message="Passing the %(name)s %(obj_type)s "
451 "positionally is deprecated since Matplotlib %(since)s; the "
452 "parameter will become keyword-only %(removal)s.",
453 name=name, obj_type=f"parameter of {func.__name__}()")
--> 454 return func(*args, **kwargs)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axes/_base.py:3650, in _AxesBase.set_xlim(self, left, right, emit, auto, xmin, xmax)
3648 raise TypeError("Cannot pass both 'right' and 'xmax'")
3649 right = xmax
-> 3650 return self.xaxis._set_lim(left, right, emit=emit, auto=auto)
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/axis.py:1225, in Axis._set_lim(self, v0, v1, emit, auto)
1222 self._set_autoscale_on(bool(auto))
1224 if emit:
-> 1225 self.axes.callbacks.process(f"{name}lim_changed", self.axes)
1226 # Call all of the other axes that are shared with this one
1227 for other in self.axes._shared_axes[name].get_siblings(self.axes):
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/cbook/__init__.py:314, in CallbackRegistry.process(self, s, *args, **kwargs)
312 except Exception as exc:
313 if self.exception_handler is not None:
--> 314 self.exception_handler(exc)
315 else:
316 raise
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/cbook/__init__.py:98, in _exception_printer(exc)
96 def _exception_printer(exc):
97 if _get_running_interactive_framework() in ["headless", None]:
---> 98 raise exc
99 else:
100 traceback.print_exc()
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/cbook/__init__.py:309, in CallbackRegistry.process(self, s, *args, **kwargs)
307 if func is not None:
308 try:
--> 309 func(*args, **kwargs)
310 # this does not capture KeyboardInterrupt, SystemExit,
311 # and GeneratorExit
312 except Exception as exc:
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:2317, in _trigger_patch_reclip(event)
2315 axes = event.axes
2316 # trigger the outline and background patches to be re-clipped
-> 2317 axes.spines['geo'].stale = True
2318 axes.patch.stale = True
File ~/miniconda3/envs/paperplots/lib/python3.10/site-packages/matplotlib/spines.py:574, in Spines.__getitem__(self, key)
570 else:
571 raise ValueError(
572 'Spines does not support slicing except for the fully '
573 'open slice [:] to access all spines.')
--> 574 return self._dict[key]
KeyError: 'geo'
<Figure size 800x1600 with 2 Axes>
相关软件包的版本:
python: 3.10.12 卡托皮:0.22.0 matplotlib:3.7.2 朱皮特:1.0.0
如果我需要提供更多信息,请告诉我。
我原以为 ax1.inset_axes(projection = ramscrs) 能够正常工作。它在使用Figure.add_axes时有效,那么为什么在使用Axes.inset_axes时不行呢?
对于未来的读者,答案将是升级到 Cartopy v0.24 或更高版本。 但是,该版本尚未发布,因此您可以使用旧版工具包版本的
inset_axes
来解决该问题:
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
import cartopy.crs as ccrs
from cartopy.mpl.geoaxes import GeoAxes
ramscrs = ccrs.Stereographic(central_longitude=-80, central_latitude=42)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(4,8), dpi=200, layout='constrained')
axinset = inset_axes(ax1, width='25%', height='25%', loc='upper right',
axes_class=GeoAxes, axes_kwargs={'projection': ramscrs})
plt.show()