Closed
Description
Bug summary
I'm trying to work with the inset_axes()
function for the first time, using geographic data plotted with matplotlib and CartoPy, but have been running into a variety of issues. For simplicity's sake, point #3 on #29174 is a good representation of what I am trying to do (recreated below).
Code for reproduction
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
main_map_proj = ccrs.TransverseMercator()
pcarree = ccrs.PlateCarree()
fig, ax = plt.subplots(subplot_kw={"projection": main_map_proj})
ax.set_extent([-50, 15, 50, 70], crs=pcarree)
ax.add_feature(cfeature.OCEAN.with_scale('50m'), facecolor="lightsteelblue", zorder=1,
edgecolor="k", lw=0.2)
inset_ax = ax.inset_axes((0.05, 0.05, 0.3, 0.3), projection=pcarree)
inset_extent = [-44, -38, 63, 66]
inset_ax.set_extent(inset_extent, crs=pcarree)
inset_ax.add_feature(cfeature.OCEAN, facecolor="lightsteelblue", zorder=1)
ax.indicate_inset_zoom(inset_ax, edgecolor="black", transform=pcarree)
x = [inset_extent[0], inset_extent[1], inset_extent[1], inset_extent[0]]
y = [inset_extent[2], inset_extent[2], inset_extent[3], inset_extent[3]]
for a in ax, inset_ax:
a.scatter(x, y, c=range(4), s=150, transform=pcarree)
plt.show()
Actual outcome
ValueError: Axes should be an instance of GeoAxes, got <class 'NoneType'>
.
This is happening even though I am verifying that both ax
and inset_ax
are GeoAxes using type()
.
Expected outcome
Additional information
I am posting this in matplotlib as it seems to be more of an issue with the inset_axes()
function rather than the GeoAxes
class.
Full Stack Trace >
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
File \personalpath\to\env\site-packages\IPython\core\formatters.py:402, in BaseFormatter.__call__(self, obj)
400 pass
401 else:
--> 402 return printer(obj)
403 # Finally look for special method names
404 method = get_real_method(obj, self.print_method)
File \personalpath\to\env\site-packages\IPython\core\pylabtools.py:170, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
167 from matplotlib.backend_bases import FigureCanvasBase
168 FigureCanvasBase(fig)
--> 170 fig.canvas.print_figure(bytes_io, **kw)
171 data = bytes_io.getvalue()
172 if fmt == 'svg':
File \personalpath\to\env\site-packages\matplotlib\backend_bases.py:2155, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2152 # we do this instead of `self.figure.draw_without_rendering`
2153 # so that we can inject the orientation
2154 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2155 self.figure.draw(renderer)
2156 if bbox_inches:
2157 if bbox_inches == "tight":
File \personalpath\to\env\site-packages\matplotlib\artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File \personalpath\to\env\site-packages\matplotlib\artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File \personalpath\to\env\site-packages\matplotlib\figure.py:3257, in Figure.draw(self, renderer)
3254 # ValueError can occur when resizing a window.
3256 self.patch.draw(renderer)
-> 3257 mimage._draw_list_compositing_images(
3258 renderer, self, artists, self.suppressComposite)
3260 renderer.close_group('figure')
3261 finally:
File \personalpath\to\env\site-packages\matplotlib\image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File \personalpath\to\env\site-packages\matplotlib\artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File \personalpath\to\env\site-packages\cartopy\mpl\geoaxes.py:524, in GeoAxes.draw(self, renderer, **kwargs)
519 self.imshow(img, extent=extent, origin=origin,
520 transform=factory.crs, *factory_args[1:],
521 **factory_kwargs)
522 self._done_img_factory = True
--> 524 return super().draw(renderer=renderer, **kwargs)
File \personalpath\to\env\site-packages\matplotlib\artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File \personalpath\to\env\site-packages\matplotlib\axes\_base.py:3210, in _AxesBase.draw(self, renderer)
3207 if artists_rasterized:
3208 _draw_rasterized(self.get_figure(root=True), artists_rasterized, renderer)
-> 3210 mimage._draw_list_compositing_images(
3211 renderer, self, artists, self.get_figure(root=True).suppressComposite)
3213 renderer.close_group('axes')
3214 self.stale = False
File \personalpath\to\env\site-packages\matplotlib\image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File \personalpath\to\env\site-packages\matplotlib\artist.py:38, in _prevent_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
35 renderer.stop_rasterizing()
36 renderer._rasterizing = False
---> 38 return draw(artist, renderer, *args, **kwargs)
File \personalpath\to\env\site-packages\matplotlib\inset.py:230, in InsetIndicator.draw(self, renderer)
226 conn_same_style = []
228 # Figure out which connectors have the same style as the box, so should
229 # be drawn as a single path.
--> 230 for conn in self.connectors or []:
231 if conn.get_visible():
232 drawn = False
File \personalpath\to\env\site-packages\matplotlib\inset.py:221, in InsetIndicator.connectors(self)
219 if self._auto_update_bounds:
220 self._rectangle.set_bounds(self._bounds_from_inset_ax())
--> 221 self._update_connectors()
222 return tuple(self._connectors)
File \personalpath\to\env\site-packages\matplotlib\inset.py:192, in InsetIndicator._update_connectors(self)
189 pos = self._inset_ax.get_position()
190 bboxins = pos.transformed(self.get_figure(root=False).transSubfigure)
191 rectbbox = transforms.Bbox.from_bounds(x, y, width, height).transformed(
--> 192 self._rectangle.get_transform())
193 x0 = rectbbox.x0 < bboxins.x0
194 x1 = rectbbox.x1 < bboxins.x1
File \personalpath\to\env\site-packages\matplotlib\patches.py:309, in Patch.get_transform(self)
307 def get_transform(self):
308 """Return the `~.transforms.Transform` applied to the `Patch`."""
--> 309 return self.get_patch_transform() + artist.Artist.get_transform(self)
File \personalpath\to\env\site-packages\matplotlib\artist.py:454, in Artist.get_transform(self)
451 self._transform = IdentityTransform()
452 elif (not isinstance(self._transform, Transform)
453 and hasattr(self._transform, '_as_mpl_transform')):
--> 454 self._transform = self._transform._as_mpl_transform(self.axes)
455 return self._transform
File \personalpath\to\env\site-packages\cartopy\crs.py:267, in CRS._as_mpl_transform(self, axes)
265 import cartopy.mpl.geoaxes as geoaxes
266 if not isinstance(axes, geoaxes.GeoAxes):
--> 267 raise ValueError(
268 'Axes should be an instance of GeoAxes, got %s' % type(axes)
269 )
270 return (
271 geoaxes.InterProjectionTransform(self, axes.projection) +
272 axes.transData
273 )
ValueError: Axes should be an instance of GeoAxes, got <class 'NoneType'>
Operating system
No response
Matplotlib Version
3.10.1
Matplotlib Backend
No response
Python version
3.12.9
Jupyter version
No response
Installation
conda
Metadata
Metadata
Assignees
Labels
No labels