Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix clearing subfigures #22138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 43 additions & 31 deletions lib/matplotlib/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,45 @@ def _break_share_link(ax, grouper):
# Break link between any twinned axes
_break_share_link(ax, ax._twinned_axes)

def clf(self, keep_observers=False):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def clf(self, keep_observers=False):
def clear(self, keep_observers=False):

"""
Clear the figure.

Parameters
----------
keep_observers: bool, default: False
Set *keep_observers* to True if, for example,
a gui widget is tracking the Axes in the figure.
"""
self.suppressComposite = None
self.callbacks = cbook.CallbackRegistry()

# first clear the axes in any subfigures
for subfig in self.subfigs:
subfig.clf(keep_observers=keep_observers)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
subfig.clf(keep_observers=keep_observers)
subfig.clear(keep_observers=keep_observers)

self.subfigs = []

for ax in tuple(self.axes): # Iterate over the copy.
ax.cla()
self.delaxes(ax) # Remove ax from self._axstack.

self.artists = []
self.lines = []
self.patches = []
self.texts = []
self.images = []
self.legends = []
if not keep_observers:
self._axobservers = cbook.CallbackRegistry()
self._suptitle = None
self._supxlabel = None
self._supylabel = None

self.stale = True

# synonym for `clf`."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra trailing quotes.

clear = clf
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
clear = clf


# Note: in the docstring below, the newlines in the examples after the
# calls to legend() allow replacing it with figlegend() to generate the
# docstring of pyplot.figlegend.
Expand Down Expand Up @@ -2801,40 +2840,13 @@ def set_figheight(self, val, forward=True):
self.set_size_inches(self.get_figwidth(), val, forward=forward)

def clf(self, keep_observers=False):
"""
Clear the figure.

Set *keep_observers* to True if, for example,
a gui widget is tracking the Axes in the figure.
"""
self.suppressComposite = None
self.callbacks = cbook.CallbackRegistry()

for ax in tuple(self.axes): # Iterate over the copy.
ax.cla()
self.delaxes(ax) # Remove ax from self._axstack.

# docstring inherited
super().clf(keep_observers=keep_observers)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
super().clf(keep_observers=keep_observers)
super().clear(keep_observers=keep_observers)

# FigureBase.clf does not clear toolbars, as
# only Figure can have toolbars
toolbar = self.canvas.toolbar
if toolbar is not None:
toolbar.update()
self._axstack = _AxesStack()
self.artists = []
self.lines = []
self.patches = []
self.texts = []
self.images = []
self.legends = []
if not keep_observers:
self._axobservers = cbook.CallbackRegistry()
self._suptitle = None
self._supxlabel = None
self._supylabel = None

self.stale = True

def clear(self, keep_observers=False):
"""Clear the figure -- synonym for `clf`."""
self.clf(keep_observers=keep_observers)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def clear(self, keep_observers=False):
"""Clear the figure -- synonym for `clf`."""
self.clf(keep_observers=keep_observers)

@_finalize_rasterization
@allow_rasterization
Expand Down
81 changes: 81 additions & 0 deletions lib/matplotlib/tests/test_figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,87 @@ def test_removed_axis():
fig.canvas.draw()


def test_figure_clear():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a mild preference to split each of these cases into its own test, but maybe that you can keep re-using the same figure is part of the test?

# we test the following figure clearing scenarios:
fig = plt.figure()

# a) an empty figure
fig.clear()
assert fig.axes == []

# b) a figure with a single unnested axes
ax = fig.add_subplot(111)
fig.clear()
assert fig.axes == []

# c) a figure multiple unnested axes
axes = [fig.add_subplot(2, 1, i+1) for i in range(2)]
fig.clear()
assert fig.axes == []

# d) a figure with a subfigure
gs = fig.add_gridspec(ncols=2, nrows=1)
subfig = fig.add_subfigure(gs[0])
subaxes = subfig.add_subplot(111)
fig.clear()
assert subfig not in fig.subfigs
assert fig.axes == []

# e) a figure with a subfigure and a subplot
subfig = fig.add_subfigure(gs[0])
subaxes = subfig.add_subplot(111)
mainaxes = fig.add_subplot(gs[1])

# e.1) removing just the axes leaves the subplot
mainaxes.remove()
assert fig.axes == [subaxes]

# e.2) removing just the subaxes leaves the subplot
# and subfigure
mainaxes = fig.add_subplot(gs[1])
subaxes.remove()
assert fig.axes == [mainaxes]
assert subfig in fig.subfigs

# e.3) clearing the subfigure leaves the subplot
subaxes = subfig.add_subplot(111)
assert mainaxes in fig.axes
assert subaxes in fig.axes
subfig.clear()
assert subfig in fig.subfigs
assert subaxes not in subfig.axes
assert subaxes not in fig.axes
assert mainaxes in fig.axes

# e.4) clearing the whole thing
subaxes = subfig.add_subplot(111)
fig.clear()
assert fig.axes == []
assert fig.subfigs == []

# f) multiple subfigures
subfigs = [fig.add_subfigure(gs[i]) for i in [0, 1]]
subaxes = [sfig.add_subplot(111) for sfig in subfigs]
assert all(ax in fig.axes for ax in subaxes)
assert all(sfig in fig.subfigs for sfig in subfigs)

# f.1) clearing only one subfigure
subfigs[0].clear()
assert subaxes[0] not in fig.axes
assert subaxes[1] in fig.axes
assert subfigs[1] in fig.subfigs

# f.2) clearing the whole thing
subfigs[1].clear()
subfigs = [fig.add_subfigure(gs[i]) for i in [0, 1]]
subaxes = [sfig.add_subplot(111) for sfig in subfigs]
assert all(ax in fig.axes for ax in subaxes)
assert all(sfig in fig.subfigs for sfig in subfigs)
fig.clear()
assert fig.subfigs == []
assert fig.axes == []


@mpl.style.context('mpl20')
def test_picking_does_not_stale():
fig, ax = plt.subplots()
Expand Down