44

Final Edit:

What I found on the subject of closing pyplot windows is that it really probably shouldn't be done using pyplot. SRK gives a great example on how to handle plots that will be updated in his answer below. Also I have stumbled across how to put pyplot plots into a Tkinter window, and Tkinter is much more adept at opening and closing windows than pyplot. Here is how to put a pyplot plot into a Tk window also this is a good example.

/Final Edit

I would like to be able to display several plots and then be able to close (remove from screen) them individually from some code input, but I don't know the code input to do this.

Below is what I have tried so far. I have played around with the position of the show and close commands, but the only real result I have gotten from this is to have one or the other plot not come up, but I have not been able to remove a plot from the screen. I have been inserting a raw_input() to create pauses.

Edit: These plots are being called from a Tkinter gui and if there is a better way to do this from that direction I would be glad to hear it.

Any input would be appreciated, thanks.

import matplotlib.pyplot as plt

a = range(0,10)
b = range(0,20,2)
c = range(0,30,3)
d = range(0,40,4)

plot1 = plt.figure()
plt.plot(a,b, 'r-o')

plt.show()

plt.close()

plot2 = plt.figure()
plt.plot(c,d, 'b-o')

plt.show()
plt.close() 

Edit Code: This didn't work either.

plot1 = plt.figure(1)
plt.plot(a,b, 'r-o')

plot2 = plt.figure(2)
plt.plot(c,d, 'b-o')
#plt.close(1)
#this will prevent plot1 from being displayed
plt.show()
plt.close(1)  # or ('all') or (plot1)

4 Answers 4

84

plt.close() will close current instance.

plt.close(2) will close figure 2

plt.close(plot1) will close figure with instance plot1

plt.close('all') will close all fiures

Found here.

Remember that plt.show() is a blocking function, so in the example code you used above, plt.close() isn't being executed until the window is closed, which makes it redundant.

You can use plt.ion() at the beginning of your code to make it non-blocking, although this has other implications.

EXAMPLE

After our discussion in the comments, I've put together a bit of an example just to demonstrate how the plot functionality can be used.

Below I create a plot:

fig = plt.figure(figsize=plt.figaspect(0.75))
ax = fig.add_subplot(1, 1, 1)
....
par_plot, = plot(x_data,y_data, lw=2, color='red')

In this case, ax above is a handle to a pair of axes. Whenever I want to do something to these axes, I can change my current set of axes to this particular set by calling axes(ax).

par_plot is a handle to the line2D instance. This is called an artist. If I want to change a property of the line, like change the ydata, I can do so by referring to this handle.

I can also create a slider widget by doing the following:

axsliderA = axes([0.12, 0.85, 0.16, 0.075])
sA = Slider(axsliderA, 'A', -1, 1.0, valinit=0.5)
sA.on_changed(update)

The first line creates a new axes for the slider (called axsliderA), the second line creates a slider instance sA which is placed in the axes, and the third line specifies a function to call when the slider value changes (update).

My update function could look something like this:

def update(val):
    A = sA.val
    B = sB.val
    C = sC.val
    y_data = A*x_data*x_data + B*x_data + C
    par_plot.set_ydata(y_data)
    draw()

The par_plot.set_ydata(y_data) changes the ydata property of the Line2D object with the handle par_plot.

The draw() function updates the current set of axes.

Putting it all together:

from pylab import *
import matplotlib.pyplot as plt
import numpy

def update(val):
    A = sA.val
    B = sB.val
    C = sC.val
    y_data = A*x_data*x_data + B*x_data + C
    par_plot.set_ydata(y_data)
    draw()


x_data = numpy.arange(-100,100,0.1);

fig = plt.figure(figsize=plt.figaspect(0.75))
ax = fig.add_subplot(1, 1, 1)
subplots_adjust(top=0.8)

ax.set_xlim(-100, 100);
ax.set_ylim(-100, 100);
ax.set_xlabel('X')
ax.set_ylabel('Y')

axsliderA = axes([0.12, 0.85, 0.16, 0.075])
sA = Slider(axsliderA, 'A', -1, 1.0, valinit=0.5)
sA.on_changed(update)

axsliderB = axes([0.43, 0.85, 0.16, 0.075])
sB = Slider(axsliderB, 'B', -30, 30.0, valinit=2)
sB.on_changed(update)

axsliderC = axes([0.74, 0.85, 0.16, 0.075])
sC = Slider(axsliderC, 'C', -30, 30.0, valinit=1)
sC.on_changed(update)

axes(ax)
A = 1;
B = 2;
C = 1;
y_data = A*x_data*x_data + B*x_data + C;

par_plot, = plot(x_data,y_data, lw=2, color='red')

show()

A note about the above: When I run the application, the code runs sequentially right through (it stores the update function in memory, I think), until it hits show(), which is blocking. When you make a change to one of the sliders, it runs the update function from memory (I think?).

This is the reason why show() is implemented in the way it is, so that you can change values in the background by using functions to process the data.

7
  • I tried that stuff and it didn't work (see edit). It does clear the memory of that instance, but it does not remove the plot from the screen. Any other ideas?
    – deadstump
    Jun 21, 2012 at 15:22
  • I've added the reason why. plt.show() is a blocking function.
    – stanri
    Jun 21, 2012 at 15:35
  • Thanks. So, what does this mean for my closing the shown plot? I guess the real question I have then it how do I deal with the windows created by the plt.show() function. Do you have any other ideas to handle that?
    – deadstump
    Jun 21, 2012 at 15:42
  • Can you give me more of an idea of what you're trying to do? Usually I allow the user to close the windows, or detect when the main window is closed, and then close them all. It's not very common to close windows from within the code in the way you suggest.
    – stanri
    Jun 21, 2012 at 15:46
  • I have a Tk gui that when asked will produce the plots, and if the user needs to tweak the plots then some variables are tweaked and the plots regenerated w/ tweaks. I just wanted to cut down on user input and have the program destroy the old plots before it makes the new ones, but I guess it would not be the end of the world if the user had to manually do this. Are you saying manual is the way to go in this case? Thanks!
    – deadstump
    Jun 21, 2012 at 15:50
10

Please use

plt.show(block=False)
plt.close('all')
0

For those that come here because not wanting to close the matplotlib.pyplot, but actually want it to not be shown at all, change the backend. In my case, I use Jupytext to make both ipynb and .py files. That way, I want the .py file to not opening any windows (useful for pytest for example).

import sys

if 'ipykernel' not in sys.modules:
    import matplotlib
    matplotlib.use('Agg')  # don't show plot

Inspired by this asnwer.

0

Hint to use plt.pause to not block is useful!

You can define a little function like this:

def autoclose_plot(t_show_plot=10):
    print(f'automatically closing plot in {t_show_plot}s...')
    plt.pause(t_show_plot)
    plt.close()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.