Skip to content

Commit dfb3bf0

Browse files
authored
Merge pull request #14278 from clbarnes/14275-inset-axes
Inset axes bug and docs fix
2 parents 0654800 + 86f5fb0 commit dfb3bf0

File tree

3 files changed

+74
-18
lines changed

3 files changed

+74
-18
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
``matplotlib.axes.Axes.indicate_inset`` returns a 4-tuple as documented
2+
-----------------------------------------------------------------------
3+
4+
In <= 3.1.0, ``matplotlib.axes.Axes.indicate_inset`` and
5+
``matplotlib.axes.Axes.indicate_inset_zoom`` were documented as returning
6+
a 4-tuple of ``matplotlib.patches.ConnectionPatch`` es, where in fact they
7+
returned a 4-length list.
8+
9+
They now correctly return a 4-tuple.
10+
``matplotlib.axes.Axes.indicate_inset`` would previously raise an error if
11+
the optional *inset_ax* was not supplied; it now completes successfully,
12+
and returns *None* instead of the tuple of ``ConnectionPatch`` es.
13+

lib/matplotlib/axes/_axes.py

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,20 @@
88
import numpy as np
99
from numpy import ma
1010

11-
from matplotlib import _preprocess_data, rcParams
11+
import matplotlib.category as _ # <-registers a category unit converter
1212
import matplotlib.cbook as cbook
1313
import matplotlib.collections as mcoll
1414
import matplotlib.colors as mcolors
1515
import matplotlib.contour as mcontour
16-
import matplotlib.category as _ # <-registers a category unit converter
1716
import matplotlib.dates as _ # <-registers a date unit converter
1817
import matplotlib.docstring as docstring
1918
import matplotlib.image as mimage
2019
import matplotlib.legend as mlegend
2120
import matplotlib.lines as mlines
2221
import matplotlib.markers as mmarkers
2322
import matplotlib.mlab as mlab
24-
import matplotlib.path as mpath
2523
import matplotlib.patches as mpatches
24+
import matplotlib.path as mpath
2625
import matplotlib.quiver as mquiver
2726
import matplotlib.stackplot as mstack
2827
import matplotlib.streamplot as mstream
@@ -31,9 +30,10 @@
3130
import matplotlib.ticker as mticker
3231
import matplotlib.transforms as mtransforms
3332
import matplotlib.tri as mtri
34-
from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer
33+
from matplotlib import _preprocess_data, rcParams
3534
from matplotlib.axes._base import _AxesBase, _process_plot_format
3635
from matplotlib.axes._secondary_axes import SecondaryAxis
36+
from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer
3737

3838
try:
3939
from numpy.lib.histograms import histogram_bin_edges
@@ -514,9 +514,12 @@ def indicate_inset(self, bounds, inset_ax=None, *, transform=None,
514514
rectangle_patch : `.Patches.Rectangle`
515515
Rectangle artist.
516516
517-
connector_lines : 4-tuple of `.Patches.ConnectionPatch`
518-
One for each of four connector lines. Two are set with visibility
519-
to *False*, but the user can set the visibility to True if the
517+
connector_lines : optional 4-tuple of `.Patches.ConnectionPatch`
518+
Each of four connector lines coming from the given rectangle
519+
on this axes in the order lower left, upper left, lower right,
520+
upper right: *None* if *inset_ax* is *None*.
521+
Two are set with visibility to *False*,
522+
but the user can set the visibility to *True* if the
520523
automatic choice is not deemed correct.
521524
522525
"""
@@ -535,25 +538,31 @@ def indicate_inset(self, bounds, inset_ax=None, *, transform=None,
535538
zorder=zorder, label=label, transform=transform, **kwargs)
536539
self.add_patch(rectpatch)
537540

541+
connects = []
542+
538543
if inset_ax is not None:
539544
# want to connect the indicator to the rect....
540-
connects = []
541545
xr = [bounds[0], bounds[0]+bounds[2]]
542546
yr = [bounds[1], bounds[1]+bounds[3]]
543547
for xc in range(2):
544548
for yc in range(2):
545549
xyA = (xc, yc)
546550
xyB = (xr[xc], yr[yc])
547-
connects += [mpatches.ConnectionPatch(xyA, xyB,
551+
connects.append(
552+
mpatches.ConnectionPatch(
553+
xyA, xyB,
548554
'axes fraction', 'data',
549555
axesA=inset_ax, axesB=self, arrowstyle="-",
550-
zorder=zorder, edgecolor=edgecolor, alpha=alpha)]
556+
zorder=zorder, edgecolor=edgecolor, alpha=alpha
557+
)
558+
)
551559
self.add_patch(connects[-1])
552560
# decide which two of the lines to keep visible....
553561
pos = inset_ax.get_position()
554562
bboxins = pos.transformed(self.figure.transFigure)
555563
rectbbox = mtransforms.Bbox.from_bounds(
556-
*bounds).transformed(transform)
564+
*bounds
565+
).transformed(transform)
557566
x0 = rectbbox.x0 < bboxins.x0
558567
x1 = rectbbox.x1 < bboxins.x1
559568
y0 = rectbbox.y0 < bboxins.y0
@@ -563,7 +572,7 @@ def indicate_inset(self, bounds, inset_ax=None, *, transform=None,
563572
connects[2].set_visible(x1 == y0)
564573
connects[3].set_visible(x1 ^ y1)
565574

566-
return rectpatch, connects
575+
return rectpatch, tuple(connects) if connects else None
567576

568577
def indicate_inset_zoom(self, inset_ax, **kwargs):
569578
"""
@@ -583,25 +592,29 @@ def indicate_inset_zoom(self, inset_ax, **kwargs):
583592
chosen so as to not overlap with the indicator box.
584593
585594
**kwargs
586-
Other *kwargs* are passed on to `.Axes.inset_rectangle`
595+
Other *kwargs* are passed on to `.Axes.indicate_inset`
587596
588597
Returns
589598
-------
590599
rectangle_patch : `.Patches.Rectangle`
591600
Rectangle artist.
592601
593602
connector_lines : 4-tuple of `.Patches.ConnectionPatch`
594-
One for each of four connector lines. Two are set with visibility
595-
to *False*, but the user can set the visibility to True if the
596-
automatic choice is not deemed correct.
603+
Each of four connector lines coming from the rectangle drawn on
604+
this axis, in the order lower left, upper left, lower right,
605+
upper right.
606+
Two are set with visibility to *False*, but the user can
607+
set the visibility to *True* if the automatic choice is not deemed
608+
correct.
597609
598610
"""
599611

600612
xlim = inset_ax.get_xlim()
601613
ylim = inset_ax.get_ylim()
602-
rect = [xlim[0], ylim[0], xlim[1] - xlim[0], ylim[1] - ylim[0]]
614+
rect = (xlim[0], ylim[0], xlim[1] - xlim[0], ylim[1] - ylim[0])
603615
rectpatch, connects = self.indicate_inset(
604-
rect, inset_ax, **kwargs)
616+
rect, inset_ax, **kwargs
617+
)
605618

606619
return rectpatch, connects
607620

lib/matplotlib/tests/test_axes.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5959,6 +5959,35 @@ def test_tick_padding_tightbbox():
59595959
assert bb.y0 < bb2.y0
59605960

59615961

5962+
def test_inset():
5963+
"""
5964+
Ensure that inset_ax argument is indeed optional
5965+
"""
5966+
dx, dy = 0.05, 0.05
5967+
# generate 2 2d grids for the x & y bounds
5968+
y, x = np.mgrid[slice(1, 5 + dy, dy),
5969+
slice(1, 5 + dx, dx)]
5970+
z = np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
5971+
5972+
fig, ax = plt.subplots()
5973+
ax.pcolormesh(x, y, z)
5974+
ax.set_aspect(1.)
5975+
ax.apply_aspect()
5976+
# we need to apply_aspect to make the drawing below work.
5977+
5978+
xlim = [1.5, 2.15]
5979+
ylim = [2, 2.5]
5980+
5981+
rect = [xlim[0], ylim[0], xlim[1] - xlim[0], ylim[1] - ylim[0]]
5982+
5983+
rec, connectors = ax.indicate_inset(bounds=rect)
5984+
assert connectors is None
5985+
fig.canvas.draw()
5986+
xx = np.array([[1.5, 2.],
5987+
[2.15, 2.5]])
5988+
assert np.all(rec.get_bbox().get_points() == xx)
5989+
5990+
59625991
def test_zoom_inset():
59635992
dx, dy = 0.05, 0.05
59645993
# generate 2 2d grids for the x & y bounds
@@ -5981,6 +6010,7 @@ def test_zoom_inset():
59816010
axin1.set_aspect(ax.get_aspect())
59826011

59836012
rec, connectors = ax.indicate_inset_zoom(axin1)
6013+
assert len(connectors) == 4
59846014
fig.canvas.draw()
59856015
xx = np.array([[1.5, 2.],
59866016
[2.15, 2.5]])

0 commit comments

Comments
 (0)