Is there a way to close a pyplot figure in OS X using the keyboard (as far as I can see you can only close it by clicking the window close button)?
I tried many key combinations like command-Q, command-W, and similar, but none of them appear to work on my system.
I also tried this code posted here:
#!/usr/bin/env python
import matplotlib.pyplot as plt
plt.plot(range(10))
def quit_figure(event):
if event.key == 'q':
plt.close(event.canvas.figure)
cid = plt.gcf().canvas.mpl_connect('key_press_event', quit_figure)
plt.show()
However, the above doesn't work on OS X either. I tried adding print statements to quit_figure, but it seems like it's never called.
I'm trying this on the latest public OS X, matplotlib version 1.1.1, and the standard Python that comes with OS X (2.7.3). Any ideas on how to fix this? It's very annoying to have to reach for the mouse every time.
This is definitely a bug in the default OS X backend used by pyplot. Adding the following two lines at the top of the file switches to a different backend that works for me, if this helps anyone else.
import matplotlib
matplotlib.use('TKAgg')
I got around this by replacing
plt.show()
with
plt.show(block=False)
input("Hit Enter To Close")
plt.close()
A hack at its best, but I hope that helps someone
use interactive mode:
import matplotlib.pyplot as plt
# Enable interactive mode:
plt.ion()
# Make your plot: No need to call plt.show() in interactive mode
plt.plot(range(10))
# Close the active plot:
plt.close()
# Plots can also be closed via plt.close('all') to close all open plots or
# plt.close(figure_name) for named figures.
Checkout the "What is interactive mode?" section in this documentation
Interactive mode can be turned off at any point with plt.ioff()
When you have focus in the matplotlib window, the official keyboard shortcut is ctrl-W by this:
http://matplotlib.org/1.2.1/users/navigation_toolbar.html
As this is a very un-Mac way to do things, it is actually cmd-W. Not so easy to guess, is it?
If you are using an interactive shell, you can also close the window programmatically. See:
When to use cla(), clf() or close() for clearing a plot in matplotlib?
So, if you use pylab or equivalent (everything in the same namespace), it is just close(fig). If you are loading the libraries manually, you need to take close from the right namespace, for example:
import matplotlib.pyplot as plt
fig = plt.figure()
plt.plot([0,1,2],[0,1,0],'r')
fig.show()
plt.close(fig)
The only catch here is that there is no such thing as fig.close even though one would expect. On the other hand, you can use plt.close('all') to regain your desktop.
Related
In the following example code...
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
with PdfPages('multipage_pdf.pdf') as pdf:
for i in range(10):
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter([0, 1, 2], [0, 1, 2])
pdf.savefig()
plt.close()
... every single plot pops up a windows with the actual canvas. Is there an elegant solution to skip the actual drawing of the canvas on the screen and draw the plot directly into a multipage pdf?
PS: Problem only caused when running code within spyder, so related to spyder and not to anything else. Running code directly using python does not cause this popping up of windows.
I think what you are looking for is to clear the figure.
first_page = plt.figure(figsize=(11.69, 8.27))
first_page.clf()
Check out the documentation:
https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.clf.html
Some examples:
https://www.programcreek.com/python/example/102298/matplotlib.pyplot.clf
The problem did not arise from matplotlib or anything similar, but just running the code from within Spyder caused this problem. Running the code using python directly does not cause the issues I had before.
I'm working with matplotlib plotting and use ioff() to switch interactive mode off to suppress the automatic opening of the plotting window on figrue creation. I want to have full control over the figure and only see it when explicitely using the show() command.
Now apparently the built-in commands to clear figures and axes do not work properly anymore.
Example:
import numpy as np
import matplotlib.pyplot as mpp
class PlotTest:
def __init__(self,nx=1,ny=1):
# Switch off interactive mode:
mpp.ioff()
# Create Figure and Axes:
self.createFigure(nx, ny)
def createFigure(self,nx=1,ny=1):
self.fig, self.axes = mpp.subplots(nx,ny)
if nx*ny == 1:
self.axes = np.array([self.axes])
def linePlot(self):
X = np.linspace(0,20,21)
Y = np.random.rand(21)
self.axes[0].plot(X,Y)
P = PlotTest()
P.linePlot()
P.fig.show()
Now I was thinking I could use P.fig.clear() any time to simply clear P.fig, but apparently that's not the case.
Writing P.fig.clear() directly into the script and execute it together it works and all I see is an empty figure. However that's rather pointless as I never get to see the actual plot like that.
Doing P.fig.clear() manually in the console does not do anything, regardless if the plot window is open or not, all other possible commands fail as well:
P.fig.clf()
P.axes[0].clear()
P.axes[0].cla()
mpp.clf()
mpp.cla()
mpp.close(P.fig)
Wrapping the command into a class method doesn't work either:
def clearFig(self):
self.fig.clear()
EDIT ================
After a clear() fig.axes is empty, yet show() still shows the old plot with the axes still being plotted.
/EDIT ================
Is it because I switched off interactive mode?
If you add a call to plt.draw() after P.fig.clear() it clears the figure. From the docs,
This is used in interactive mode to update a figure that has been altered, but not automatically re-drawn. This should be only rarely needed, but there may be ways to modify the state of a figure with out marking it as stale. Please report these cases as bugs.
I guess this is not a bug as you have switched off interactive mode so it is now your responsibility to explicitly redraw when you want to.
You can also use P.fig.canvas.draw_idle() which could be wrapper in the class as clearFigure method.
I am trying to plot in Jupyter notebook (Python 2.7), then prompt user for input, save it and then change the plot (this is a crucial point: I don't want to create a new plot, I need to modify the old one after user input). This completely fails to work. Instead of showing the figure and then prompting for input, it opens the figure window, but freezes (doesn't display anything) until I respond to the raw_input() prompt. Only then it plots.
Simple version of the code to show the error:
import matplotlib.pyplot as plt
%matplotlib qt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1,2,3],[1,2,3])
plt.show(block=False)
my_input = raw_input()
This bug only appears when I use %matplotlib qt, but I have to use it, because with %matplotlib inline I am unable to modify the plot after it was displayed (at least as far as I am aware).
In fact, I noticed that it freezes until the end of the cell execution, even if it is just time.sleep().
Am I missing something? Some settings of how matplotlib displays figures?
Since I am using Python3 I had to change raw_input() to input() and removed the block=False because IPython told me that this is an unknown attribute.
This should work nice:
import matplotlib.pyplot as plt
%matplotlib inline
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1,2,3], [1,2,3])
plt.show()
my_input = input()
Fur sure, you need to adapt this back to Python2 to fit your needs.
This question already has answers here:
Interactive(?) plotting in Spyder with matplotlib
(2 answers)
Closed 3 months ago.
I need to use interactive mode when plotting with matplotlib (it should be a script, not python or ipython console). But setting plt.ion() causes a strange bug (?). When I try to plot my figure (I don't think it really matters, what I do exactly, because in non-interactive mode it works perfectly fine) I don't see it - I get a blank grey window for split-second, which momentarily disappears and the programme exits.
If I explicitly add plt.draw() (and plt.pause(1) to see the result), I see that the figure appears as expected. If I do the same after modifications I want to do to the figure when it is visible, the figure changes. But the window still disappears after the pause is over.
I run it in Spyder with Qt4Agg as a backend under Ubuntu. Tried running the script from terminal as python my_script.py, the result is identical.
What could be the problem? How do I stop the figure from disappearing when in interactive mode?
UPDATE
Working example:
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
x = np.linspace(1, 10)
y = np.sin(x)
plt.plot(x, y)
plt.draw()
plt.pause(1)
If I run this code I see the sine plot for 1 second, then the window disappears.
UPDATE 2
I found a solution here: https://stackoverflow.com/a/10724654/1304161
If I set the run options in Spyder correctly, it works perfectly fine. Although running it in gnome-terminal doesn't work, I don't really need it. Hopefully, there won't be a problem with this when it becomes a part of a GUI app...
I found a solution here: https://stackoverflow.com/a/10724654/1304161
If I set the run options in Spyder correctly, it works perfectly fine. Although running it in gnome-terminal doesn't work, I don't really need it. Hopefully, there won't be a problem with this when it becomes a part of a GUI app. I will be back, if it will be a problem then :)
You can make it work by adding these two lines at the end:
plt.ioff()
plt.show()
So this program works fine:
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
x = np.linspace(1, 10)
y = np.sin(x)
plt.plot(x, y)
plt.draw()
plt.ioff()
plt.show()
To display multiple figures at different times, you can use code.interact(local=locals()), after plt.show() to pause the Python interpreter until a Ctrl-Z is pressed in the Python Shell:
import code
import matplotlib.pyplot as plt
import numpy as np
# Start pyplot's "interactive mode" which lets you run plt.show multiple times
plt.ion()
x = np.linspace(1, 10)
y = np.sin(x)
# PLOT #1 - displayed
plt.plot(x, y)
plt.draw()
plt.show()
# Wait for figure to be closed AND Ctrl-Z pressed in Python Shell
code.interact(local=locals())
print("Some more code can go here...")
# PLOT #2 - displayed
plt.plot(x, y)
plt.show()
# Wait for figure to be closed AND Ctrl-Z pressed in Python Shell
code.interact(local=locals())
in windows I try to run this code. Serial works fine and compass value converted to float matplotlib figure opened but matplotlib window "not responding" not draws anything.
import serial
import numpy
import matplotlib.pyplot as plt
ser = serial.Serial('COM8',9600,timeout=2)
ciz,=plt.plot([],[])
def update_ciz(ciz,newdata):
ciz.set_xdata(numpy.append(ciz.get_xdata(),newdata))
ciz.set_ydata(numpy.append(ciz.get_ydata(),newdata))
plt.draw()
while (True):
line = ser.readline()
k=line.split(":")
temperature=k[0]
pressure= k[1]
attitude=k[2]
realAttitude=k[3]
compass=float(k[4])
gx=k[5]
gy=k[6]
gz=k[7]
ax=k[8]
ay=k[9]
az=k[10]
acond=k[11]
update_ciz(ciz,compass)
In matplotlib you need to use "plt.show()" to display the plot. Since you are using "plt.draw()" to update the plot, you probably also want to use the interactive mode.
Try including this after your "ciz,=plt.plot([],[])" command:
plt.ion()
plt.show()