1

if I create a figure then do plt.close() :

from matplotlib import pyplot as plt

fig1 = plt.figure()
fig2 = plt.figure()

fig1.show()
plt.close()
fig1.show()
fig2.show()

the fig1 will only show once, because the plt.close() will destroy the figure object referred by fig1. How can I only close the window without destroy the figure?

So far nothing really works. after each plt.figure(), a new figure_manager is going to be generated. And will be put into a list in plt instance.

>>> print plt.get_fignums()
[1, 2]

however, after plt.close(), the figure_manager of the specific figure will be pop out.

>>> print plt.get_fignums()
[2]

As @John Sharp mentioned plt._backend_mod.new_figure_manager_given_figure(plt.get_fignums()[-1]+1,fig1) will create a new figure_manager for the fig1. However, it has not been added to the plt. So it is impossible to control those figure_manager while plt:

>>> plt._backend_mod.new_figure_manager_given_figure(plt.get_fignums()[-1]+1,fig1)
<matplotlib.backends.backend_tkagg.FigureManagerTkAgg instance at 0x2b0f680>

>>> print plt.get_fignums()
[2]

>>> plt.new_figure_manager(1)
<matplotlib.backends.backend_tkagg.FigureManagerTkAgg instance at 0x2b1e3f8>
>>> plt.get_fignums()
[2]

So it cannot be closed by plt.close(), except directly call figure_manager.destroy()

The suggestion to set current fm directly will be worse:

fm = plt.get_current_fig_manager()
fm.canvas.figure = fig1
fig1.canvas = fm.canvas

at the first glance, this seems work. However, it will directly change the fig2's fm to point to fig1, which will cause lots of trouble.

If there is any way, we can make the pyplot to register manually generated fm, that may work. So far have no luck there.

Wang
  • 7,250
  • 4
  • 35
  • 66

1 Answers1

1

Since the Figure is still referenced by the name fig1 it is not destroyed. You just need to create a new figure manager for the figure. One way to do this is to get a new figure manager by generating a new blank figure and manually set the canvas figure to be fig1:

plt.figure()
fm = plt.get_current_fig_manager()
fm.canvas.figure = fig1
fig1.canvas = fm.canvas

Once you've done this you can show and then close the figure with:

fig1.show()
plt.close()

Alternatively, if you were showing two figures at once and only wanted to close a particular one, instead of using plt.close() you can call the fm.destroy() method to close the window showing only the particular figure referenced by that frame manager.

John Sharp
  • 801
  • 4
  • 5
  • Thanks a lot. I found that not just wxagg, tkagg or any agg will have the same new_figure_manager_given_figure() function. However this seems only work for 1.3.1 not in old version. In the old one it will trigger some bug. I haven't accept your answer yet. Because I had some problem to close those figure again. plt.close() will not work any more. – Wang Aug 22 '14 at 06:06
  • Oh I didn't notice that! I've edited my answer so that it uses the current figure manager of the matplotlib.pyplot module. This way plt.close() behaves as expected. – John Sharp Aug 22 '14 at 09:24
  • Does just generating a fresh, blank figure and setting that one's canvas to point to fig1's canvas get round the problems you mentioned in your question? From looking at the docs I can't see an elegant way to automatically register a new frame manager. – John Sharp Aug 23 '14 at 10:21