Matplotlib offers these functions:
cla() # Clear axis
clf() # Clear figure
close() # Close a figure window
When should I use each function and what exactly does it do?
Matplotlib offers these functions:
cla() # Clear axis
clf() # Clear figure
close() # Close a figure window
When should I use each function and what exactly does it do?
They all do different things, since matplotlib uses a hierarchical order in which a figure window contains a figure which may consist of many axes. Additionally, there are functions from the pyplot interface and there are methods on the Figure
class. I will discuss both cases below.
pyplot
is a module that collects a couple of functions that allow matplotlib to be used in a functional manner. I here assume that pyplot
has been imported as import matplotlib.pyplot as plt
.
In this case, there are three different commands that remove stuff:
See matplotlib.pyplot
Functions:
plt.cla()
clears an axis, i.e. the currently active axis in the current figure. It leaves the other axes untouched.plt.clf()
clears the entire current figure with all its axes, but leaves the window opened, such that it may be reused for other plots.plt.close()
closes a window, which will be the current window, if not specified otherwise.Which functions suits you best depends thus on your use-case.
The close()
function furthermore allows one to specify which window should be closed. The argument can either be a number or name given to a window when it was created using figure(number_or_name)
or it can be a figure instance fig
obtained, i.e., usingfig = figure()
. If no argument is given to close()
, the currently active window will be closed. Furthermore, there is the syntax close('all')
, which closes all figures.
Additionally, the Figure
class provides methods for clearing figures.
I'll assume in the following that fig
is an instance of a Figure
:
fig.clf()
clears the entire figure. This call is equivalent to plt.clf()
only if fig
is the current figure.
fig.clear()
is a synonym for fig.clf()
Note that even del fig
will not close the associated figure window. As far as I know the only way to close a figure window is using plt.close(fig)
as described above.
There is just a caveat that I discovered today.
If you have a function that is calling a plot a lot of times you better use plt.close(fig)
instead of fig.clf()
somehow the first does not accumulate in memory. In short if memory is a concern use plt.close(fig) (Although it seems that there are better ways, go to the end of this comment for relevant links).
So the the following script will produce an empty list:
for i in range(5):
fig = plot_figure()
plt.close(fig)
# This returns a list with all figure numbers available
print(plt.get_fignums())
Whereas this one will produce a list with five figures on it.
for i in range(5):
fig = plot_figure()
fig.clf()
# This returns a list with all figure numbers available
print(plt.get_fignums())
From the documentation above is not clear to me what is the difference between closing a figure and closing a window. Maybe that will clarify.
If you want to try a complete script there you have:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1000)
y = np.sin(x)
for i in range(5):
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(x, y)
plt.close(fig)
print(plt.get_fignums())
for i in range(5):
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(x, y)
fig.clf()
print(plt.get_fignums())
If memory is a concern somebody already posted a work-around in SO see: Create a figure that is reference counted
plt.clf()
followed by plt.close()
then the memory is freed correctly. Just using plt.close()
still leads to residual memory increase per plot opened. –
Caritacaritas plt.cla() means clear current axis
plt.clf() means clear current figure
also, there's plt.gca() (get current axis) and plt.gcf() (get current figure)
Read more here: Matplotlib, Pyplot, Pylab etc: What's the difference between these and when to use each?
As David Zwicker explained, all these methods clear different things. This post adds some examples to help clarify when to use them.
If you want to re-use particular configurations of a figure (facecolor, dpi, layout etc.) for another figure, use fig.clf()
to clear the current objects (including Axes) on the figure. Note that this doesn't delete a previously instantiated Figure instance, but only clears objects on it. So in the following code, a single Figure instance is re-used to produce 2 image files.
fig, ax = plt.subplots() # instantiate a Figure and an Axes
ax.plot([0,1,2]) # draw a line plot
fig.savefig('images/img1.png')
fig.clf() # clear Figure (removes Axes)
ax = fig.add_subplot() # add new Axes to previously instantiated `fig`
ax.plot([1,2,0,0,2,1], 'o') # draw a scatter plot
fig.savefig('images/img2.png')
Since fig.clf()
removes the Axes, it's important to add a new one on it in order to plot something.
If you want to re-use a figure but change an Axes on it, then use ax.cla()
to clear the current objects (e.g. ticks, titles, plots etc.) on the Axes. In particular, the position of an Axes on a figure is an important attribute that could be re-used (e.g. the figure has a small Axes could be superimposed on a larger Axes).
If want to close a figure window, use plt.close()
. This is especially useful if you use an IDE with an interactive mode such as Jupyter or Spyder and you don't want to see the figure(s) your script creates. If you use a Python shell such as IDLE (that comes with a Python installation), then it literally closes the window that shows a figure. Even though it closes the window, the Figure instance is still in memory along with whatever objects defined on it. For example in the following code, even though fig
is closed, it can still be worked on. However, because the figure/Axes was not cleared, whatever was in fig
persists.
fig, ax = plt.subplots() # instantiate a Figure and an Axes
ax.plot([0,1,2]) # draw a line plot
fig.savefig('images/img1.png') # save the line plot
plt.close(fig) # close `fig`
ax.plot([1,2,0,0,2,1], 'o') # draw a scatter plot on top of the previously plotted lineplot
fig.savefig('images/img2.png') # save scatter + line plot
Heberto Mayorquin points out that plt.close()
saves memory. However, as the following memory allocation traces show, if a lot of similar images need to be created in a loop, clearing with clf()
or cla()
is actually more memory efficient than closing a window and creating a new figure instance with plt.close()
.
However, there's a caveat that since cla()
/clf()
are meant to re-use a previously defined Axes/Figure, it's important to define the Figure object to be re-used outside the loop (that creates image files). I also included "wrong" ways to use cla()
and clf()
in the test (where a new Figure instance is created every time a new figure is drawn) which are indeed more costly than creating a new Figure and closing it in a loop.
close:
current memory usage is 12,456 KB; peak was 13,402 KB.
======================================================
cla:
current memory usage is 899 KB; peak was 1,451 KB.
======================================================
clf:
current memory usage is 3,806 KB; peak was 8,061 KB.
======================================================
clf_wrong:
current memory usage is 7,392 KB; peak was 10,494 KB.
======================================================
cla_wrong:
current memory usage is 29,174 KB; peak was 29,650 KB.
======================================================
Code used to the produce the above result:
import os
import tracemalloc
import matplotlib.pyplot as plt
def close(n):
for i in range(n):
fig = plt.figure(facecolor='white', figsize=(6,3), dpi=36)
ax = fig.add_subplot()
ax.plot([100, 0, i])
fig.savefig(f'{i}.png')
plt.close(fig)
def cla(n):
fig = plt.figure(facecolor='white', figsize=(6,3), dpi=36)
ax = fig.add_subplot()
for i in range(n):
ax.plot([100, 0, i])
fig.savefig(f'{i}.png')
ax.cla()
def clf(n):
fig = plt.figure(facecolor='white', figsize=(6,3), dpi=36)
for i in range(n):
ax = fig.add_subplot()
ax.plot([100, 0, i])
fig.savefig(f'{i}.png')
fig.clf()
def cla_wrong(n):
for i in range(n):
fig = plt.figure(facecolor='white', figsize=(6,3), dpi=36)
ax = fig.add_subplot()
ax.plot([100, 0, i])
fig.savefig(f'{i}.png')
ax.cla()
def clf_wrong(n):
for i in range(n):
fig = plt.figure(facecolor='white', figsize=(6,3), dpi=36)
ax = fig.add_subplot()
ax.plot([100, 0, i])
fig.savefig(f'{i}.png')
fig.clf()
if __name__ == '__main__':
for func in (close, cla, clf, clf_wrong, cla_wrong):
tracemalloc.start()
func(100)
size, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
# delete the saved image files
for f in os.listdir():
if f.endswith('.png'):
os.remove(f)
print(f"{func.__name__}:\ncurrent memory usage is {size/1024:,.0f} KB; \
peak was {peak/1024:,.0f} KB.")
print("======================================================")
© 2022 - 2024 — McMap. All rights reserved.
pyplot
API. – Ison