I have noticed that when I run:
import pylab as pl
pl.ion()
# Plot something
pl.show()
pl.close()
The last statement does not fully close the Figure. The figure goes dark, and the contents go away, but the Figure stays on the screen until I exit IPython as shown below
I am using the latest stable version of matplotlib (1.3.1) using an Anaconda distribution, on Linux 64 bit, and I connect remotely using ssh -X.
The backend I am using is below:
backend : QT4Agg
backend.qt4 : PySide
you have to specify wich figure you want to close. In case you want to close all of them:
pl.close('all')
Also, there is a way to just clear but not close a figure:
pl.clf()
Also, seen below from another SO question:
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.
You can also use the following lines after your plotting
#Your Plotting function
plt.waitforbuttonpress(0)
plt.close(fig)
The plt.waitforbuttonpress(0) will wait until a user input (Key press) is given. After that it will properly close the matplotlib window properly. It is very important to specify which figure to close.
Related
I want to show plots in a separate window. Currently I have the IPython graphics backend set to "automatic".
When I re-run the code (or plot another figure), Spyder opens a new plot window. Is it possible to refresh the figure in the window that is already opened instead of opening a new one?
The GUI window that opens when you call plt.show() is bound to a figure. You cannot change the figure inside it. (Well, to be precise, there might be an option of obtaining a handle from the operating system and manipulating its content, but I assume this is not worth the effort.)
Re-running the code actually means that you produce a new figure since the code does not know that it's been run before.
So, exchanging the figure or reusing the window to plot a different figure is not possible.
What is possible however is to use the figure and manipulate the figure while it's open. This is done via plt.ion(). After calling this command in IPython you can adapt the figure, e.g. adding new lines to it etc.
See this example:
At IN [6] the window opens and when IN [7] is executed, the figure stays open and the content changes.
Sure, it is possible with Spyder while in the same running kernel. Try the following example using num as parameter to plt.figure(), where num will always refer to the same figure and refresh it if already opened. Also works with plt.subplots().
import matplotlib.pyplot as plt
from scipy import *
t = linspace(0, 0.1,1000)
w = rand(1)*60*2*pi
fig = plt.figure(num=10, clear=True, figsize = [10,8])
plt.plot(t,cos(w*t))
plt.plot(t,cos(w*t-2*pi/3))
plt.plot(t,cos(w*t-4*pi/3))
So I have some python code that plots a few graphs using pyplot. Every time I run the script new plot windows are created that I have to close manually. How do I close all open pyplot windows at the start of the script? Ie. closing windows that were opened during previous executions of the script?
In MatLab this can be done simply by using closeall.
To close all open figures from a script, you can call
plt.close('all')
or you can terminate the associated Python process.
This solution won't allow you to close plots from previous runs, but will prevent you from leaving them open!
The only way I have found to close these "hanging" figures is to find the process and kill.
Plot in a non blocking manner then ask for input. This should prevent you from forgetting to properly close the plot.
plt.show(block=False)
plt.pause(0.001) # Pause for interval seconds.
input("hit[enter] to end.")
plt.close('all') # all open plots are correctly closed after each run
import matplotlib.pyplot as plt
plt.close("all")
(In case you have pyplot already imported, you obviously don't need to import it again. In that case just make sure to replace plt in plt.close("all") with whatever alias you chose for pyplot when you imported it.)
I just had the same problem. I call a function that generates multiple plot windows. Each time I call the function the popped up plot windows accumulate in number. Trying matplotlib.pyplot.close('All') at the begining of the function didn't solve the problem. I solved the problem by calling matplotlib.pyplot.close(figure), where figure is a plot figure instance (object).
I maintain a list of my plot figure objects. So, it is a good idea to maintain a list, and then call matplotlib.pyplot.close(figure) for each instance of a figure object:
import matplotlib.pyplot as plot
Add plot instance objects (figure,axis) to a list:
fig, (ax1,ax2) = plt.subplots(nrows=2)
figAxisDict = {'figure': fig, 'axis1': ax1, 'axis2':ax2}
figAxisList.append(figAxisDict)
Call the function for figure closing, and clear the list afterwards:
if len(figAxisList) !=0:
for figAxis in figAxisList:
figure=figAxis['figure']
plot.close(figure)
figAxisList[:]=[]
As there seems no absolutely trivial solution to do this automatically from the script itself: the possibly simplest way to close all existing figures in pycharm is killing the corresponding processes (as jakevdp suggested in his comment):
Menu Run\Stop... (Ctrl-F2). You'll find the windows closed with a delay of few seconds.
Honestly, the developer needs to make this a simple function like it is in MATLAB.
My temporary solution for Spyder:
first install keyboard and pynput via the Anaconda Prompt
in Spyder run "mouse.position" with your mouse over the position where your plots pane is
These coordinates are the ones you need to replace in the code below.
import keyboard
from pynput.mouse import Button, Controller
#%% Clear Old Plots
#Selects the mouse as the controller
mouse = Controller()
#Record current mouse position
recmp = mouse.position
#Set pointer position on plots pane
mouse.position = (1136,370) # <-- replace coordinates here with yours!
#Opens the plot pane
keyboard.press_and_release('ctrl+shift+g')
#Click and release left mouse button
mouse.press(Button.left)
mouse.release(Button.left)
#Runs close all in the plots pane
keyboard.press_and_release('ctrl+shift+w')
#Resets mouse position to the original location
mouse.position = recmp
On *nix you can use killall command.
killall app
closes every instance of window with app for the window name.
You can also use the same command from inside your python script.
You can use os.system("bashcommand") to run the bashcommand.
I'm plotting some graphs and then I interact with them using the canvas.mpl_connect commands. So when I show the plot, I want the window to be the active one since the beginning.
At the moment, when the script is run, the plot pops up but it's not the active window, the terminal still is (i.e. if I type a key, that is written in the Terminal, and not interpreted by the plot-window). I need to click on the plot-window to make it the active one and then I'm able to interact with the graphs. It would be way nicer if it was already active the first time it pops up.
Working on MacOSX 10.10.3 with python 2.7.5 and matplotlib 1.3.1
EDIT
I don't just need to bring the window in front, I want to be able to interact with the window without having to click on it. So if I type some keys, the graph will respond and not the terminal.
You can set the order windows are displayed in using canvas manager but it only works with some graphical backends. The following example uses the TkAgg backend which works but the same idea won't work the macosx backend.
import matplotlib
matplotlib.use('TkAgg')
from matplotlib import pyplot as plt
from pylab import get_current_fig_manager
fig1 = plt.figure()
fig2 = plt.figure()
fig1.canvas.manager.window.attributes('-topmost', 1)
plt.show()
Figure 1 should show up on top of figure 2.
So, I've finally found a solution here https://github.com/matplotlib/matplotlib/pull/663
Apparently a work around is to import
from AppKit import NSApplication
and issuing just before show():
NSApplication.sharedApplication().activateIgnoringOtherApps_(True)
I'm not really sure what it does, and apparently it works just in non-interactive mode, but that worked perfectly for me.
You might also want to check here
https://github.com/matplotlib/matplotlib/issues/665/
At the end of the last function I call in one of my programs, I have the following code to plot a simple color plot.
plt.figure()
plt.pcolormesh(X,Y,Z)
plt.colorbar()
plt.show()
Afterwords I return to main and my program is complete. The plot displays as expected, however when I go to close it using the x button in the corner (on ubuntu), my program doesn't end. It just hangs there with a process running. How can I correct this?
your matplotlib might be running in non-interactive mode for some reason.
I am not sure how to prevent that in your local configuration but if you add either this:
plt.ion()
or this:
matplotlib.interactive(True)
somewhere at the beginning of your script, it should change the behaviour of your plots.
For interactive mode, You need this at the head of file:
import matplotlib
matplotlib.use("TkAgg")
The documentation for the "interactive mode" in Matplotlib's pyplot reads:
The interactive property of the pyplot interface controls whether a figure canvas is drawn on every pyplot command. If interactive is False, then the figure state is updated on every plot command, but will only be drawn on explicit calls to draw(). When interactive is True, then every pyplot command triggers a draw.
This seems clear enough: when the interactive mode is on, one can do plot() without having to do draw(). However, doing draw() in the following code does not do anything:
from matplotlib import pyplot as pp
# Interactive mode is off by default
pp.plot([10, 20, 50])
pp.draw()
raw_input('Press enter...') # No graph displayed?!!
(on Windows XP, Matplotlib 1.0.1).
Adding ion() at the beginning makes the figure(s) appear, while waiting for the user to type enter (which conveniently closes all the figures):
from matplotlib import pyplot as pp
ion()
pp.plot([10, 20, 50]) # No draw() is necessary
raw_input('Press enter...') # The graph is interactive *and* the terminal responds to enter
Thus, it looks like ion() does more than just adding automatic graph updates after each plotting command, and I unfortunately can't find anything in the documentation. Another, more important problem with the latter program is that ion() makes all plot commands update the graph, which is time consuming when a single graph is updated multiple times.
So, is there a way of:
having the terminal wait for enter, after which all the figures are automatically closed,
having interactive Matplotlib graphs,
… without forcing the interactive mode to be on at the beginning (so as to not force auto-updates of the graphs, which could be time consuming)?
Here is the summary of an interesting discussion on this subject in the Matplotlib mailing list. The executive summary is:
The interactive mode (activated with ion()) automates many things. In particular, pyplot.* commands automatically update on the screen the relevant axes. However, method calls on Matplotlib objects like ax.plot() (ax being an Axes object) do not normally perform automatic updates; in this case, pyplot.draw() performs the necessary update.)
The non-interactive mode is less convenient. draw() does not normally update the figure on screen. The fact that draw() is somewhat "inactive" in non-interactive mode is not mentioned in the current documentation, but will hopefully be included there soon.
In the mean time, more information on the interactive and non-interactive modes can be found in a current branch of Matplotlib. A better documentation for draw(), show() and friends can also be found in the same branch.
I would suggest that you follow the last comment of 'Thomas K'. I remember a similar question on the mailing list, but I couldn't find it after several minutes of searching. Sorry.
I had also this problem and the better easier way for me was/is to use ipython --pylab. I have a much older version of matplotlib installed which have some problems with ion(). Beside this, matplotlib had also some problems with draw() on Windows. Maybe it was fixed in the last versions.
p.s.: Sorry that I couldn't helped you really well.
Best regards.