Skip to content

Commit 9a03861

Browse files
jklymaktacaswell
authored andcommitted
Backport PR #22138: Fix clearing subfigures
Merge pull request #22138 from stanleyjs/subfigure-clear Fix clearing subfigures (cherry picked from commit a395083)
1 parent 6bbedd4 commit 9a03861

File tree

2 files changed

+125
-32
lines changed

2 files changed

+125
-32
lines changed

lib/matplotlib/figure.py

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,45 @@ def _break_share_link(ax, grouper):
935935
# Break link between any twinned axes
936936
_break_share_link(ax, ax._twinned_axes)
937937

938+
def clf(self, keep_observers=False):
939+
"""
940+
Clear the figure.
941+
942+
Parameters
943+
----------
944+
keep_observers: bool, default: False
945+
Set *keep_observers* to True if, for example,
946+
a gui widget is tracking the Axes in the figure.
947+
"""
948+
self.suppressComposite = None
949+
self.callbacks = cbook.CallbackRegistry()
950+
951+
# first clear the axes in any subfigures
952+
for subfig in self.subfigs:
953+
subfig.clf(keep_observers=keep_observers)
954+
self.subfigs = []
955+
956+
for ax in tuple(self.axes): # Iterate over the copy.
957+
ax.cla()
958+
self.delaxes(ax) # Remove ax from self._axstack.
959+
960+
self.artists = []
961+
self.lines = []
962+
self.patches = []
963+
self.texts = []
964+
self.images = []
965+
self.legends = []
966+
if not keep_observers:
967+
self._axobservers = cbook.CallbackRegistry()
968+
self._suptitle = None
969+
self._supxlabel = None
970+
self._supylabel = None
971+
972+
self.stale = True
973+
974+
# synonym for `clf`."""
975+
clear = clf
976+
938977
# Note: in the docstring below, the newlines in the examples after the
939978
# calls to legend() allow replacing it with figlegend() to generate the
940979
# docstring of pyplot.figlegend.
@@ -2748,40 +2787,13 @@ def set_figheight(self, val, forward=True):
27482787
self.set_size_inches(self.get_figwidth(), val, forward=forward)
27492788

27502789
def clf(self, keep_observers=False):
2751-
"""
2752-
Clear the figure.
2753-
2754-
Set *keep_observers* to True if, for example,
2755-
a gui widget is tracking the Axes in the figure.
2756-
"""
2757-
self.suppressComposite = None
2758-
self.callbacks = cbook.CallbackRegistry()
2759-
2760-
for ax in tuple(self.axes): # Iterate over the copy.
2761-
ax.cla()
2762-
self.delaxes(ax) # removes ax from self._axstack
2763-
2764-
toolbar = getattr(self.canvas, 'toolbar', None)
2790+
# docstring inherited
2791+
super().clf(keep_observers=keep_observers)
2792+
# FigureBase.clf does not clear toolbars, as
2793+
# only Figure can have toolbars
2794+
toolbar = self.canvas.toolbar
27652795
if toolbar is not None:
27662796
toolbar.update()
2767-
self._axstack.clear()
2768-
self.artists = []
2769-
self.lines = []
2770-
self.patches = []
2771-
self.texts = []
2772-
self.images = []
2773-
self.legends = []
2774-
if not keep_observers:
2775-
self._axobservers = cbook.CallbackRegistry()
2776-
self._suptitle = None
2777-
self._supxlabel = None
2778-
self._supylabel = None
2779-
2780-
self.stale = True
2781-
2782-
def clear(self, keep_observers=False):
2783-
"""Clear the figure -- synonym for `clf`."""
2784-
self.clf(keep_observers=keep_observers)
27852797

27862798
@_finalize_rasterization
27872799
@allow_rasterization

lib/matplotlib/tests/test_figure.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,87 @@ def test_removed_axis():
689689
fig.canvas.draw()
690690

691691

692+
def test_figure_clear():
693+
# we test the following figure clearing scenarios:
694+
fig = plt.figure()
695+
696+
# a) an empty figure
697+
fig.clear()
698+
assert fig.axes == []
699+
700+
# b) a figure with a single unnested axes
701+
ax = fig.add_subplot(111)
702+
fig.clear()
703+
assert fig.axes == []
704+
705+
# c) a figure multiple unnested axes
706+
axes = [fig.add_subplot(2, 1, i+1) for i in range(2)]
707+
fig.clear()
708+
assert fig.axes == []
709+
710+
# d) a figure with a subfigure
711+
gs = fig.add_gridspec(ncols=2, nrows=1)
712+
subfig = fig.add_subfigure(gs[0])
713+
subaxes = subfig.add_subplot(111)
714+
fig.clear()
715+
assert subfig not in fig.subfigs
716+
assert fig.axes == []
717+
718+
# e) a figure with a subfigure and a subplot
719+
subfig = fig.add_subfigure(gs[0])
720+
subaxes = subfig.add_subplot(111)
721+
mainaxes = fig.add_subplot(gs[1])
722+
723+
# e.1) removing just the axes leaves the subplot
724+
mainaxes.remove()
725+
assert fig.axes == [subaxes]
726+
727+
# e.2) removing just the subaxes leaves the subplot
728+
# and subfigure
729+
mainaxes = fig.add_subplot(gs[1])
730+
subaxes.remove()
731+
assert fig.axes == [mainaxes]
732+
assert subfig in fig.subfigs
733+
734+
# e.3) clearing the subfigure leaves the subplot
735+
subaxes = subfig.add_subplot(111)
736+
assert mainaxes in fig.axes
737+
assert subaxes in fig.axes
738+
subfig.clear()
739+
assert subfig in fig.subfigs
740+
assert subaxes not in subfig.axes
741+
assert subaxes not in fig.axes
742+
assert mainaxes in fig.axes
743+
744+
# e.4) clearing the whole thing
745+
subaxes = subfig.add_subplot(111)
746+
fig.clear()
747+
assert fig.axes == []
748+
assert fig.subfigs == []
749+
750+
# f) multiple subfigures
751+
subfigs = [fig.add_subfigure(gs[i]) for i in [0, 1]]
752+
subaxes = [sfig.add_subplot(111) for sfig in subfigs]
753+
assert all(ax in fig.axes for ax in subaxes)
754+
assert all(sfig in fig.subfigs for sfig in subfigs)
755+
756+
# f.1) clearing only one subfigure
757+
subfigs[0].clear()
758+
assert subaxes[0] not in fig.axes
759+
assert subaxes[1] in fig.axes
760+
assert subfigs[1] in fig.subfigs
761+
762+
# f.2) clearing the whole thing
763+
subfigs[1].clear()
764+
subfigs = [fig.add_subfigure(gs[i]) for i in [0, 1]]
765+
subaxes = [sfig.add_subplot(111) for sfig in subfigs]
766+
assert all(ax in fig.axes for ax in subaxes)
767+
assert all(sfig in fig.subfigs for sfig in subfigs)
768+
fig.clear()
769+
assert fig.subfigs == []
770+
assert fig.axes == []
771+
772+
692773
@mpl.style.context('mpl20')
693774
def test_picking_does_not_stale():
694775
fig, ax = plt.subplots()

0 commit comments

Comments
 (0)