0

I have a script that produces a number of different figures and saves the handles to a dictionary. Usually I want to plot all of them but sometimes I am working on a single one, and just want to plot that one.

My understanding is that plt.show() will show all the plots. It seems logical that if I allocate the figures handles (i.e. do fig1 = plt.figure()) and then use fig1.show() that should only show the figure associated with that handle.

Here is a MWE:

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 100)
y1 = np.random.rand(100)
y2 = np.random.rand(100)

fig1 = plt.figure()
plt.plot(x, y1, 'o')

fig2 = plt.figure()
plt.plot(x, y2, 'o')

fig1.show()

This seems to work but the figure immediately disappears after it is created. My understanding is that fig1.show() needs to be in a loop, since the class Figure.show() method does not invoke a while loop like plt.show() does.

I realise this is similar to the following question: How can I show figures separately in matplotlib? but the accepted answer doesn't seem to address the original problem (as is pointed out in the comments).

Is placing fig1.show() in a while loop the correct way? If so, how do you do that?

krg
  • 317
  • 3
  • 11

2 Answers2

2

You could add a statement that waits for user input, then the figure will show, and close after you press a key:

fig1.show() 
raw_input()
rinkert
  • 6,593
  • 2
  • 12
  • 31
  • So simple, yet does the trick perfectly! I was under the impression that the `show()` only appears momentarily before disappearing. I guess it displays the figure until the entire script is processed. Makes sense. For Python 3 users, `raw_input()` was replaced with `input()` – krg Oct 31 '18 at 17:16
2

You might close all other figures except the one you want to show. Then calling plt.show() will only show the one figure that hasn't been closed.

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 100)
y1 = np.random.rand(100)
y2 = np.random.rand(100)

fig1 = plt.figure()
plt.plot(x, y1, 'o')

fig2 = plt.figure()
plt.plot(x, y2, 'o')

def figshow(figure):
    for i in plt.get_fignums():
        if figure != plt.figure(i):
            plt.close(plt.figure(i))
    plt.show()

figshow(fig2)
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • That works but I get bombarded with warning messages (`can't invoke "event" command: application has been destroyed`). I like your function though. Can be edited to allow for a list of figures, which is much faster than writing them all out. – krg Nov 01 '18 at 12:37
  • The warnings could come from running this in interactive mode perhaps? Would `plt.ioff()` get rid of them? – ImportanceOfBeingErnest Nov 01 '18 at 13:00
  • No, `plt.ioff()` doesnt seem to change the warnings. Here is the full message. I get one of these for every closed plot: 'can't invoke "event" command: application has been destroyed while executing "event generate $w <>" (procedure "ttk::ThemeChanged" line 6) invoked from within "ttk::ThemeChanged"' – krg Nov 01 '18 at 16:46
  • There seems to be a more severe problem with the tk backend involved. I tried with `import matplotlib; matplotlib.use("Qt5Agg")` and it works fine. – ImportanceOfBeingErnest Nov 01 '18 at 17:48
  • 1
    Note that this should be fixed by https://github.com/matplotlib/matplotlib/pull/12707 now. The bugfix may make it into the 3.0.2 release of matplotlib which is to appear pretty soon. – ImportanceOfBeingErnest Nov 04 '18 at 11:48