Skip to content

Commit 68d2dc2

Browse files
authored
Merge pull request #22418 from anntzer/ov
Deprecate auto-removal of overlapping Axes by plt.subplot{,2grid}.
2 parents d38f93f + 23338c7 commit 68d2dc2

File tree

4 files changed

+38
-21
lines changed

4 files changed

+38
-21
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Auto-removal of overlapping Axes by ``plt.subplot`` and ``plt.subplot2grid``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Previously, `.pyplot.subplot` and `.pyplot.subplot2grid` would automatically
4+
remove preexisting Axes that overlap with the newly added Axes. This behavior
5+
was deemed confusing, and is now deprecated. Explicitly call ``ax.remove()``
6+
on Axes that need to be removed.

lib/matplotlib/pyplot.py

+15-14
Original file line numberDiff line numberDiff line change
@@ -1303,13 +1303,13 @@ def subplot(*args, **kwargs):
13031303

13041304
fig.sca(ax)
13051305

1306-
bbox = ax.bbox
1307-
axes_to_delete = []
1308-
for other_ax in fig.axes:
1309-
if other_ax == ax:
1310-
continue
1311-
if bbox.fully_overlaps(other_ax.bbox):
1312-
axes_to_delete.append(other_ax)
1306+
axes_to_delete = [other for other in fig.axes
1307+
if other != ax and ax.bbox.fully_overlaps(other.bbox)]
1308+
if axes_to_delete:
1309+
_api.warn_deprecated(
1310+
"3.6", message="Auto-removal of overlapping axes is deprecated "
1311+
"since %(since)s and will be removed %(removal)s; explicitly call "
1312+
"ax.remove() as needed.")
13131313
for ax_to_del in axes_to_delete:
13141314
delaxes(ax_to_del)
13151315

@@ -1596,13 +1596,14 @@ def subplot2grid(shape, loc, rowspan=1, colspan=1, fig=None, **kwargs):
15961596

15971597
subplotspec = gs.new_subplotspec(loc, rowspan=rowspan, colspan=colspan)
15981598
ax = fig.add_subplot(subplotspec, **kwargs)
1599-
bbox = ax.bbox
1600-
axes_to_delete = []
1601-
for other_ax in fig.axes:
1602-
if other_ax == ax:
1603-
continue
1604-
if bbox.fully_overlaps(other_ax.bbox):
1605-
axes_to_delete.append(other_ax)
1599+
1600+
axes_to_delete = [other for other in fig.axes
1601+
if other != ax and ax.bbox.fully_overlaps(other.bbox)]
1602+
if axes_to_delete:
1603+
_api.warn_deprecated(
1604+
"3.6", message="Auto-removal of overlapping axes is deprecated "
1605+
"since %(since)s and will be removed %(removal)s; explicitly call "
1606+
"ax.remove() as needed.")
16061607
for ax_to_del in axes_to_delete:
16071608
delaxes(ax_to_del)
16081609

lib/matplotlib/tests/test_axes.py

+2
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,8 @@ def test_inverted_cla():
442442
assert not ax.xaxis_inverted()
443443
assert ax.yaxis_inverted()
444444

445+
for ax in fig.axes:
446+
ax.remove()
445447
# 5. two shared axes. Inverting the leader axis should invert the shared
446448
# axes; clearing the leader axis should bring axes in shared
447449
# axes back to normal.

lib/matplotlib/tests/test_pyplot.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ def test_subplot_replace_projection():
206206
ax = plt.subplot(1, 2, 1)
207207
ax1 = plt.subplot(1, 2, 1)
208208
ax2 = plt.subplot(1, 2, 2)
209-
# This will delete ax / ax1 as they fully overlap
210-
ax3 = plt.subplot(1, 2, 1, projection='polar')
209+
with pytest.warns(MatplotlibDeprecationWarning):
210+
ax3 = plt.subplot(1, 2, 1, projection='polar')
211211
ax4 = plt.subplot(1, 2, 1, projection='polar')
212212
assert ax is not None
213213
assert ax1 is ax
@@ -228,6 +228,7 @@ def test_subplot_kwarg_collision():
228228
ax1 = plt.subplot(projection='polar', theta_offset=0)
229229
ax2 = plt.subplot(projection='polar', theta_offset=0)
230230
assert ax1 is ax2
231+
ax1.remove()
231232
ax3 = plt.subplot(projection='polar', theta_offset=1)
232233
assert ax1 is not ax3
233234
assert ax1 not in plt.gcf().axes
@@ -274,13 +275,16 @@ def test_subplot_projection_reuse():
274275
assert ax1 is plt.gca()
275276
# make sure we get it back if we ask again
276277
assert ax1 is plt.subplot(111)
278+
# remove it
279+
ax1.remove()
277280
# create a polar plot
278281
ax2 = plt.subplot(111, projection='polar')
279282
assert ax2 is plt.gca()
280283
# this should have deleted the first axes
281284
assert ax1 not in plt.gcf().axes
282285
# assert we get it back if no extra parameters passed
283286
assert ax2 is plt.subplot(111)
287+
ax2.remove()
284288
# now check explicitly setting the projection to rectilinear
285289
# makes a new axes
286290
ax3 = plt.subplot(111, projection='rectilinear')
@@ -302,15 +306,19 @@ def test_subplot_polar_normalization():
302306

303307

304308
def test_subplot_change_projection():
309+
created_axes = set()
305310
ax = plt.subplot()
311+
created_axes.add(ax)
306312
projections = ('aitoff', 'hammer', 'lambert', 'mollweide',
307313
'polar', 'rectilinear', '3d')
308314
for proj in projections:
309-
ax_next = plt.subplot(projection=proj)
310-
assert ax_next is plt.subplot()
311-
assert ax_next.name == proj
312-
assert ax is not ax_next
313-
ax = ax_next
315+
ax.remove()
316+
ax = plt.subplot(projection=proj)
317+
assert ax is plt.subplot()
318+
assert ax.name == proj
319+
created_axes.add(ax)
320+
# Check that each call created a new Axes.
321+
assert len(created_axes) == 1 + len(projections)
314322

315323

316324
def test_polar_second_call():

0 commit comments

Comments
 (0)