Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8a30509

Browse filesBrowse files
committed
Rebase subfigure-clear
1 parent 5218653 commit 8a30509
Copy full SHA for 8a30509

File tree

Expand file treeCollapse file tree

3 files changed

+129
-22
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+129
-22
lines changed
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Figure & subfigure clearing
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Fixed a bug in which ``Figure.clf()`` and ``Figure.clear()`` were broken
4+
when ``Figure`` contained axes not stored in ``Figure._localaxes``. Moved the
5+
``clear`` and ``clf`` methods to ``FigureBase``, so ``Subfigure``s can now be
6+
independently cleared. Added a routine to clear ``Figure.subfigs`` when
7+
``Figure.clear()`` is called. This effects the API as it removes active
8+
subfigure references when clearing a figure.

‎lib/matplotlib/figure.py

Copy file name to clipboardExpand all lines: lib/matplotlib/figure.py
+41-22Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,43 @@ def _break_share_link(ax, grouper):
940940
# Break link between any twinned axes
941941
_break_share_link(ax, ax._twinned_axes)
942942

943+
def clf(self, keep_observers=False):
944+
"""
945+
Clear the figure.
946+
Set *keep_observers* to True if, for example,
947+
a gui widget is tracking the Axes in the figure.
948+
"""
949+
self.suppressComposite = None
950+
self.callbacks = cbook.CallbackRegistry()
951+
952+
for subfig in self.subfigs:
953+
# first clear the axes in any subfigures
954+
subfig.clf(keep_observers=keep_observers)
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._axstack = _AxesStack()
961+
self.artists = []
962+
self.subfigs = []
963+
self.lines = []
964+
self.patches = []
965+
self.texts = []
966+
self.images = []
967+
self.legends = []
968+
if not keep_observers:
969+
self._axobservers = cbook.CallbackRegistry()
970+
self._suptitle = None
971+
self._supxlabel = None
972+
self._supylabel = None
973+
974+
self.stale = True
975+
976+
def clear(self, keep_observers=False):
977+
"""Clear the figure -- synonym for `clf`."""
978+
self.clf(keep_observers=keep_observers)
979+
943980
# Note: in the docstring below, the newlines in the examples after the
944981
# calls to legend() allow replacing it with figlegend() to generate the
945982
# docstring of pyplot.figlegend.
@@ -2824,35 +2861,17 @@ def clf(self, keep_observers=False):
28242861
Set *keep_observers* to True if, for example,
28252862
a gui widget is tracking the Axes in the figure.
28262863
"""
2827-
self.suppressComposite = None
2828-
self.callbacks = cbook.CallbackRegistry()
2829-
2830-
for ax in tuple(self.axes): # Iterate over the copy.
2831-
ax.cla()
2832-
self.delaxes(ax) # Remove ax from self._axstack.
2833-
2864+
super().clf(keep_observers=keep_observers)
2865+
# FigureBase.clf does not clear toolbars, as
2866+
# only Figure can have toolbars
28342867
toolbar = self.canvas.toolbar
28352868
if toolbar is not None:
28362869
toolbar.update()
2837-
self._axstack.clear()
2838-
self.artists = []
2839-
self.lines = []
2840-
self.patches = []
2841-
self.texts = []
2842-
self.images = []
2843-
self.legends = []
2844-
if not keep_observers:
2845-
self._axobservers = cbook.CallbackRegistry()
2846-
self._suptitle = None
2847-
self._supxlabel = None
2848-
self._supylabel = None
2849-
2850-
self.stale = True
28512870

28522871
def clear(self, keep_observers=False):
28532872
"""Clear the figure -- synonym for `clf`."""
28542873
self.clf(keep_observers=keep_observers)
2855-
2874+
28562875
@_finalize_rasterization
28572876
@allow_rasterization
28582877
def draw(self, renderer):

‎lib/matplotlib/tests/test_figure.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_figure.py
+80Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,86 @@ def test_removed_axis():
709709
fig.canvas.draw()
710710

711711

712+
def test_figure_clear():
713+
# we test the following figure clearing scenarios:
714+
fig = plt.figure()
715+
716+
# a) an empty figure
717+
fig.clear()
718+
assert fig.axes == []
719+
720+
# b) a figure with a single unnested axes
721+
ax = fig.add_subplot(111)
722+
fig.clear()
723+
assert fig.axes == []
724+
725+
# c) a figure multiple unnested axes
726+
axes = [fig.add_subplot(2, 1, i+1) for i in range(2)]
727+
fig.clear()
728+
assert fig.axes == []
729+
730+
# d) a figure with a subfigure
731+
gs = fig.add_gridspec(ncols=2, nrows=1)
732+
subfig = fig.add_subfigure(gs[0])
733+
subaxes = subfig.add_subplot(111)
734+
fig.clear()
735+
assert subfig not in fig.subfigs
736+
assert fig.axes == []
737+
738+
# e) a figure with a subfigure and a subplot
739+
subfig = fig.add_subfigure(gs[0])
740+
subaxes = subfig.add_subplot(111)
741+
mainaxes = fig.add_subplot(gs[1])
742+
743+
# e.1) removing just the axis leaves the subplot
744+
mainaxes.remove()
745+
assert [subaxes] == fig.axes
746+
747+
# e.2) removing just the subaxis leaves the subplot
748+
# and subfigure
749+
mainaxes = fig.add_subplot(gs[1])
750+
subaxes.remove()
751+
assert [mainaxes] == fig.axes
752+
assert subfig in fig.subfigs
753+
754+
# e.3) clearing the subfigure leaves the subplot
755+
subaxes = subfig.add_subplot(111)
756+
assert all(ax in fig.axes for ax in [mainaxes, subaxes])
757+
subfig.clear()
758+
assert subfig in fig.subfigs
759+
assert subaxes not in subfig.axes
760+
assert subaxes not in fig.axes
761+
assert mainaxes in fig.axes
762+
763+
# e.4) clearing the whole thing
764+
subaxes = subfig.add_subplot(111)
765+
fig.clear()
766+
assert fig.axes == []
767+
assert fig.subfigs == []
768+
769+
# f) multiple subfigures
770+
subfigs = [fig.add_subfigure(gs[i]) for i in [0, 1]]
771+
subaxes = [sfig.add_subplot(111) for sfig in subfigs]
772+
assert all(ax in fig.axes for ax in subaxes)
773+
assert all(sfig in fig.subfigs for sfig in subfigs)
774+
775+
# f.1) clearing only one subfigure
776+
subfigs[0].clear()
777+
assert subaxes[0] not in fig.axes
778+
assert subaxes[1] in fig.axes
779+
assert subfigs[1] in fig.subfigs
780+
781+
# f.2) clearing the whole thing
782+
subfigs[1].clear()
783+
subfigs = [fig.add_subfigure(gs[i]) for i in [0, 1]]
784+
subaxes = [sfig.add_subplot(111) for sfig in subfigs]
785+
assert all(ax in fig.axes for ax in subaxes)
786+
assert all(sfig in fig.subfigs for sfig in subfigs)
787+
fig.clear()
788+
assert fig.subfigs == []
789+
assert fig.axes == []
790+
791+
712792
@mpl.style.context('mpl20')
713793
def test_picking_does_not_stale():
714794
fig, ax = plt.subplots()

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.