diff --git a/doc/users/next_whats_new/inset_axes_improvements.rst b/doc/users/next_whats_new/inset_axes_improvements.rst new file mode 100644 index 000000000000..8ff7d82cfb28 --- /dev/null +++ b/doc/users/next_whats_new/inset_axes_improvements.rst @@ -0,0 +1,6 @@ +Axes.inset_axes Flexibility +--------------------------- + +`matplotlib.axes.Axes.inset_axes` now accepts the *projection*, *polar* and +*axes_class* keyword arguments, so that subclasses of `matplotlib.axes.Axes` may +be returned. \ No newline at end of file diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 3026e681f742..5399b14374ce 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -326,13 +326,27 @@ def inset_axes(self, bounds, *, transform=None, zorder=5, **kwargs): Defaults to `ax.transAxes`, i.e. the units of *rect* are in Axes-relative coordinates. + projection : {None, 'aitoff', 'hammer', 'lambert', 'mollweide', \ +'polar', 'rectilinear', str}, optional + The projection type of the inset `~.axes.Axes`. *str* is the name + of a custom projection, see `~matplotlib.projections`. The default + None results in a 'rectilinear' projection. + + polar : bool, default: False + If True, equivalent to projection='polar'. + + axes_class : subclass type of `~.axes.Axes`, optional + The `.axes.Axes` subclass that is instantiated. This parameter + is incompatible with *projection* and *polar*. See + :ref:`axisartist_users-guide-index` for examples. + zorder : number Defaults to 5 (same as `.Axes.legend`). Adjust higher or lower to change whether it is above or below data plotted on the parent Axes. **kwargs - Other keyword arguments are passed on to the child `.Axes`. + Other keyword arguments are passed on to the inset Axes class. Returns ------- @@ -358,7 +372,10 @@ def inset_axes(self, bounds, *, transform=None, zorder=5, **kwargs): # This puts the rectangle into figure-relative coordinates. inset_locator = _TransformedBoundsLocator(bounds, transform) bounds = inset_locator(self, None).bounds - inset_ax = Axes(self.figure, bounds, zorder=zorder, **kwargs) + projection_class, pkw = self.figure._process_projection_requirements( + bounds, **kwargs) + inset_ax = projection_class(self.figure, bounds, zorder=zorder, **pkw) + # this locator lets the axes move if in data coordinates. # it gets called in `ax.apply_aspect() (of all places) inset_ax.set_axes_locator(inset_locator) diff --git a/lib/matplotlib/tests/baseline_images/test_axes/inset_polar.png b/lib/matplotlib/tests/baseline_images/test_axes/inset_polar.png new file mode 100644 index 000000000000..b7b7faf198ec Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_axes/inset_polar.png differ diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index b2bc70ff6143..358b911c45fa 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -26,10 +26,13 @@ import matplotlib.markers as mmarkers import matplotlib.patches as mpatches import matplotlib.path as mpath +from matplotlib.projections.geo import HammerAxes +from matplotlib.projections.polar import PolarAxes import matplotlib.pyplot as plt import matplotlib.text as mtext import matplotlib.ticker as mticker import matplotlib.transforms as mtransforms +import mpl_toolkits.axisartist as AA from numpy.testing import ( assert_allclose, assert_array_equal, assert_array_almost_equal) from matplotlib.testing.decorators import ( @@ -2543,8 +2546,6 @@ def get_next_color(): def test_as_mpl_axes_api(): # tests the _as_mpl_axes api - from matplotlib.projections.polar import PolarAxes - class Polar: def __init__(self): self.theta_offset = 0 @@ -6614,6 +6615,31 @@ def test_zoom_inset(): axin1.get_position().get_points(), xx, rtol=1e-4) +@image_comparison(['inset_polar.png'], remove_text=True, style='mpl20') +def test_inset_polar(): + _, ax = plt.subplots() + axins = ax.inset_axes([0.5, 0.1, 0.45, 0.45], polar=True) + assert isinstance(axins, PolarAxes) + + r = np.arange(0, 2, 0.01) + theta = 2 * np.pi * r + + ax.plot(theta, r) + axins.plot(theta, r) + + +def test_inset_projection(): + _, ax = plt.subplots() + axins = ax.inset_axes([0.2, 0.2, 0.3, 0.3], projection="hammer") + assert isinstance(axins, HammerAxes) + + +def test_inset_subclass(): + _, ax = plt.subplots() + axins = ax.inset_axes([0.2, 0.2, 0.3, 0.3], axes_class=AA.Axes) + assert isinstance(axins, AA.Axes) + + @pytest.mark.parametrize('x_inverted', [False, True]) @pytest.mark.parametrize('y_inverted', [False, True]) def test_indicate_inset_inverted(x_inverted, y_inverted):