66

Say that I have two figures in matplotlib, with one plot per figure:

import matplotlib.pyplot as plt

f1 = plt.figure()
plt.plot(range(0,10))
f2 = plt.figure()
plt.plot(range(10,20))

Then I show both in one shot

plt.show()

Is there a way to show them separately, i.e. to show just f1?

Or better: how can I manage the figures separately like in the following 'wishful' code (that doesn't work):

f1 = plt.figure()
f1.plot(range(0,10))
f1.show()
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Federico A. Ramponi
  • 46,145
  • 29
  • 109
  • 133
  • 1
    Just a tip: you generally really don't need to save your figures (in f1, f2), as Matplotlib draws in the *current* figure, which is generally the latest created figure. – Eric O. Lebigot Mar 08 '10 at 08:09
  • 2
    @EOL, what if I want to draw on the first figure? – Alcott Oct 23 '13 at 10:23
  • 5
    There are multiple ways of writing back to a figure without saving it first in a variable. For example, all figures have a "number" (which can be a number or a string). By default, figures get a number. Thus, `figure(1)` makes the first figure created active, etc. Alternatively, you can create a figure (without saving it) with `figure('rank')` and then make it active again later with `figure('rank')`. That said, the point of my comment was that in the case of this question, there is absolutely no need to save the figures, since `plot()` acts on the current figure (the last one created, here). – Eric O. Lebigot Oct 31 '13 at 17:43
  • 1
    @EOL: that's excellent information, and worthy of its own question, you might add it to: [Creating and referencing separate matplotlib plots](https://stackoverflow.com/questions/35923911/creating-and-referencing-separate-matplotlib-plots) – smci Feb 12 '18 at 09:30

7 Answers7

57

Sure. Add an Axes using add_subplot. (Edited import.) (Edited show.)

import matplotlib.pyplot as plt
f1 = plt.figure()
f2 = plt.figure()
ax1 = f1.add_subplot(111)
ax1.plot(range(0,10))
ax2 = f2.add_subplot(111)
ax2.plot(range(10,20))
plt.show()

Alternatively, use add_axes.

ax1 = f1.add_axes([0.1,0.1,0.8,0.8])
ax1.plot(range(0,10))
ax2 = f2.add_axes([0.1,0.1,0.8,0.8])
ax2.plot(range(10,20))
Steve Tjoa
  • 59,122
  • 18
  • 90
  • 101
  • This is exactly what I'm trying to do, but matplotlib.figure seems a module, not a class. Am I missing something? – Federico A. Ramponi Mar 07 '10 at 20:35
  • My fault. See edit. In fact, I use `from pylab import figure` more often. For some reason, that `pylab.figure` returns a figure with the `show` method, but `matplotlib.figure.Figure` does not. Hmm. – Steve Tjoa Mar 07 '10 at 21:01
  • Uff.. :) Here I'm using python 2.5.2 with matplotlib 0.98.1. f1.show() does nothing, whereas the second show() gets stuck. Probably something is misconfigured. However, on another machine I use python 2.5.5 and matplotlib 0.99.1.1 and everything works fine, so... +1 and accepted, thank you very much. – Federico A. Ramponi Mar 07 '10 at 21:29
  • One really shouldn't use `pylab` any more, `matplotlib.pyplot` is much better and was also used by the questioner. – nikow Mar 07 '10 at 23:15
  • Here is the offical link why `matplotlib.pyplot` is prefered: http://matplotlib.sourceforge.net/faq/usage_faq.html – nikow Mar 07 '10 at 23:16
  • WARNING: calling show multiple times is officially incorrect: http://matplotlib.sourceforge.net/faq/howto_faq.html#use-show. A working solution is to use `draw()` and `raw_input()` (see my answer). – Eric O. Lebigot Mar 08 '10 at 07:57
  • @nikow: As far as I know, Pylab is not deprecated. The link you quote says is that examples in the Matplotlib documentation should not imply "from pylab import *" but instead rely on explicit module attribute access. What is deprectaed is the "from pylab import *" in their examples. – Eric O. Lebigot Mar 08 '10 at 08:16
  • @EOL: Of course it is not deprecated, but that doesn't mean that it is good practice. – nikow Mar 08 '10 at 11:09
  • @nikow: I was referring to your "One really shouldn't use pylab anymore". Pylab can actually still be used ("is not deprecated"), as far as I understand (Matplotlib's examples should not use "from pylab import *", that's all). – Eric O. Lebigot Mar 08 '10 at 13:35
  • 9
    @Steve: I don't understand how your solution answers the question. Frederico asked how to show only f1. Your code shows f1 and f2, and from what I can tell, is pretty much identical to Frederico's example of what he didn't want to do. Did something get lost in the edits? – Emma Sep 02 '11 at 15:54
  • 1
    You make a good point. Something definitely got lost in the edits which were a consequence of all these comments. If you look back at version 2 of this answer, that's what *I* personally do. I don't know about purity, i.e. what the "right way" is supposed to be, but I use code like `fig1 = pylab.figure()` and `fig2 = pylab.figure()` all the time, and then I operate each `figure` separately, and I've been doing that for a couple years now. To me, it is the best way. I agree 100% with your other comment -- it is important to keep the operation of each individual figure modular and separated. – Steve Tjoa Sep 02 '11 at 18:34
  • @EricOLebigot New in version v1.0.0: show now starts the GUI mainloop only if it isn't already running. Therefore, multiple calls to show are now allowed. – NoName Dec 14 '19 at 18:27
  • @NoName It was already officially incorrect as of 2010, as my comment above indicates! :) – Eric O. Lebigot Dec 15 '19 at 11:20
  • @EricOLebigot Just a follow up: So even though we CAN call .show() multiple times now, is it still recommended to plot multiple graphs in `matplotlib.figure.Figure` first using subplots, and then call show all at once in the end on the Figure? – NoName Dec 15 '19 at 23:35
  • I would be surprised if users were forced to use subplots instead of open multiple figures if they choose to do so—and then do show(). – Eric O. Lebigot Dec 19 '19 at 12:15
26

With Matplotlib prior to version 1.0.1, show() should only be called once per program, even if it seems to work within certain environments (some backends, on some platforms, etc.).

The relevant drawing function is actually draw():

import matplotlib.pyplot as plt

plt.plot(range(10))  # Creates the plot.  No need to save the current figure.
plt.draw()  # Draws, but does not block
raw_input()  # This shows the first figure "separately" (by waiting for "enter").

plt.figure()  # New window, if needed.  No need to save it, as pyplot uses the concept of current figure
plt.plot(range(10, 20))
plt.draw()
# raw_input()  # If you need to wait here too...

# (...)

# Only at the end of your program:
plt.show()  # blocks

It is important to recognize that show() is an infinite loop, designed to handle events in the various figures (resize, etc.). Note that in principle, the calls to draw() are optional if you call matplotlib.ion() at the beginning of your script (I have seen this fail on some platforms and backends, though).

I don't think that Matplotlib offers a mechanism for creating a figure and optionally displaying it; this means that all figures created with figure() will be displayed. If you only need to sequentially display separate figures (either in the same window or not), you can do like in the above code.

Now, the above solution might be sufficient in simple cases, and for some Matplotlib backends. Some backends are nice enough to let you interact with the first figure even though you have not called show(). But, as far as I understand, they do not have to be nice. The most robust approach would be to launch each figure drawing in a separate thread, with a final show() in each thread. I believe that this is essentially what IPython does.

The above code should be sufficient most of the time.

PS: now, with Matplotlib version 1.0.1+, show() can be called multiple times (with most backends).

Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
  • Edited my answer to use single `show`. I still prefer the manual way of saving individual axis and figure handles, because I find that I frequently need them later on. Furthermore, that is what the initial question asked. – Steve Tjoa Mar 08 '10 at 10:03
  • You really do not need to name the figures in order to display them sequentially… Whether to save the result of figure() or not really depends on one's specific needs; I almost never save it. – Eric O. Lebigot Mar 08 '10 at 13:47
  • 1
    What if you don't want to create the figure in the same place you show it? This can be very useful for keeping code modular. Say I have a function that does a lot of number crunching. I would like to produce all of my plots inside this function, since it's the one that has knowledge of the data being plotted. Then I would like to return the figures to my main function, which decides what to do with them (for example it might want to save some and display others, or display them in a certain order). – Emma Sep 02 '11 at 16:57
  • @Emma: According to the discussion at http://stackoverflow.com/questions/6130341/exact-semantics-of-matplotlibs-interactive-mode-ion-ioff/6446392#6446392, you can do non-drawing graph "calculations" when you do not use the `pyplot.*` functions (but use instead Axes.* plotting functions). You can then probably do `fig.savefig()` on the appropriate figures in order to save them, and maybe `fig.draw()` on the other ones (not tested). – Eric O. Lebigot Sep 02 '11 at 19:16
  • I found it quite annoying that, if I call `show()` once, and close the image, then I'm not able to call `show()` again to show the image. So if I want to show the image again, do I have to replot again? – Alcott Oct 23 '13 at 11:50
  • As far as I know, you do need to replot again. You may consider just minimizing the figures that you intend to keep, or maybe saving them to a file if they are really important. – Eric O. Lebigot Oct 31 '13 at 17:44
  • This solution did not help me. I have two figures, but I just want to plot one of them. `plt.show()` shows both. All I want is something like `f1.show()` or `draw()` for that matter, only if they worked :( I cannot get a level of control of which figure to show. – Shailen Jan 15 '15 at 14:39
  • Can you describe more precisely what you need? Do you want to plot one figure, then replace it with another one (after the user types enter)? – Eric O. Lebigot Jan 19 '15 at 12:40
11

I think I am a bit late to the party but... In my opinion, what you need is the object oriented API of matplotlib. In matplotlib 1.4.2 and using IPython 2.4.1 with Qt4Agg backend, I can do the following:

import matplotlib.pyplot as plt
fig, ax = plt.subplots(1) # Creates figure fig and add an axes, ax.
fig2, ax2 = plt.subplots(1) # Another figure

ax.plot(range(20)) #Add a straight line to the axes of the first figure.
ax2.plot(range(100)) #Add a straight line to the axes of the first figure.

fig.show() #Only shows figure 1 and removes it from the "current" stack.
fig2.show() #Only shows figure 2 and removes it from the "current" stack.
plt.show() #Does not show anything, because there is nothing in the "current" stack.
fig.show() # Shows figure 1 again. You can show it as many times as you want.

In this case plt.show() shows anything in the "current" stack. You can specify figure.show() ONLY if you are using a GUI backend (e.g. Qt4Agg). Otherwise, I think you will need to really dig down into the guts of matplotlib to monkeypatch a solution.

Remember that most (all?) plt.* functions are just shortcuts and aliases for figure and axes methods. They are very useful for sequential programing, but you will find blocking walls very soon if you plan to use them in a more complex way.

  • Even using GUI Backend TkAgg, `fig.show()` shows the figure in a window and closes immediately, so that we cannot see the figure. See [documentation on figure.show()](https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.figure.Figure.html?highlight=show%20figure#matplotlib.figure.Figure.show) – loved.by.Jesus Dec 17 '19 at 11:56
2

Perhaps you need to read about interactive usage of Matplotlib. However, if you are going to build an app, you should be using the API and embedding the figures in the windows of your chosen GUI toolkit (see examples/embedding_in_tk.py, etc).

Jouni K. Seppänen
  • 43,139
  • 5
  • 71
  • 100
1

None of the above solutions seems to work in my case, with matplotlib 3.1.0 and Python 3.7.3. Either both the figures show up on calling show() or none show up in different answers posted above.

Building upon @Ivan's answer, and taking hint from here, the following seemed to work well for me:

import matplotlib.pyplot as plt
fig, ax = plt.subplots(1) # Creates figure fig and add an axes, ax.
fig2, ax2 = plt.subplots(1) # Another figure

ax.plot(range(20)) #Add a straight line to the axes of the first figure.
ax2.plot(range(100)) #Add a straight line to the axes of the first figure.

# plt.close(fig) # For not showing fig
plt.close(fig2) # For not showing fig2
plt.show()
arpanmangal
  • 1,770
  • 1
  • 17
  • 34
1

As @arpanmangal, the solutions above do not work for me (matplotlib 3.0.3, python 3.5.2).

It seems that using .show() in a figure, e.g., figure.show(), is not recommended, because this method does not manage a GUI event loop and therefore the figure is just shown briefly. (See figure.show() documentation). However, I do not find any another way to show only a figure.

In my solution I get to prevent the figure for instantly closing by using click events. We do not have to close the figure — closing the figure deletes it.

I present two options: - waitforbuttonpress(timeout=-1) will close the figure window when clicking on the figure, so we cannot use some window functions like zooming. - ginput(n=-1,show_clicks=False) will wait until we close the window, but it releases an error :-.

Example:

import matplotlib.pyplot as plt

fig1, ax1 = plt.subplots(1) # Creates figure fig1 and add an axes, ax1
fig2, ax2 = plt.subplots(1) # Another figure fig2 and add an axes, ax2

ax1.plot(range(20),c='red') #Add a red straight line to the axes of fig1.
ax2.plot(range(100),c='blue') #Add a blue straight line to the axes of fig2.

#Option1: This command will hold the window of fig2 open until you click on the figure
fig2.waitforbuttonpress(timeout=-1) #Alternatively, use fig1

#Option2: This command will hold the window open until you close the window, but
#it releases an error.
#fig2.ginput(n=-1,show_clicks=False) #Alternatively, use fig1

#We show only fig2
fig2.show() #Alternatively, use fig1
loved.by.Jesus
  • 2,266
  • 28
  • 34
0

As of November 2020, in order to show one figure at a time, the following works:

import matplotlib.pyplot as plt

f1, ax1 = plt.subplots()
ax1.plot(range(0,10))
f1.show()
input("Close the figure and press a key to continue")
f2, ax2 = plt.subplots()
ax2.plot(range(10,20))
f2.show()
input("Close the figure and press a key to continue")

The call to input() prevents the figure from opening and closing immediately.

Hari
  • 1,561
  • 4
  • 17
  • 26