I would like to save my figures to disk without rendering them on the screen and without having to change my rendering backend.
I tried the instructions in here, namely avoiding calling fig.show() nor fig.draw() and just calling fig.savefig, but I noticed that the mere statement fig = plt.figure() already opens a figure on the screen.
How can I save a figure to disk without having to render it, and without having to change my backend?
pyplot has an interactive functionality which will automatically call draw() after most plt.* calls for you.
draw is not automatically called if you don't go through the state machine interface (ex gca().plot(...) would not automatically redraw, but plt.plot(...) would).
See the code, the important function in draw_if_interactive.
This can be turn off via plt.ioff() or by not calling plt.ion() (ipython --pylab automatically turns it on for you).
doc
Related
With a single script, I have to produce dozens of figures with matplotlib using spyder. I would like spyder to create figures while I can work with other browsers or windows without interruption. Here were the methods I tried. Let us say that there are 40 plots to be created. Each plot contains multiple subplots
(1) From How do I get interactive plots again in Spyder/IPython/matplotlib?. I used %matplotlib inline. The plots will be created inline at the end of the program. However, the usage of computation memory keeps accumulating. At some point, python will show an error message due to lack of memory and then crash. The message is like: "More than 20 figures have been opened. Figures created through the pyplot interface (matplotlib.pyplot.figure) are retained until explicitly closed and may consume too much memory."
(2) Then, I use plt.close() to close each figure after saving it. The memory issue is resolved. However, even if the figure is not shown, every time python close a figure and open another one, all other browsers and windows will be affected. If I am typing on a window, after the interruption, I have to click the window again in order to continue typing.
Previously, when I used MATLAB, I could simply specify h=figure and then set(h,'visible','off') to avoid this issue. I wonder if I can do similar things with python.
Thank you for the help!
I want to save figures plotted by a function that I don't want to have to touch (because it is an external function, and also because if tomorrow I don't want to save them and just display on the console, I don't want to have to edit the source code again and again). Is it possible to save the figures into a folder from ipython? Whether the figures are plotted in iPython or not is not a concern. I just want to be able to save them in a folder automatically, as they are a lot in number.
I have tried most of the solutions mentioned here, but they don't work - they just save a blank image file.
import matplotlib.pyplot as pl
fig = pl.figure()
external_function(parameters) # this function plots a figure
fig.savefig(r'path\to\folder\image.png') # saves a blank image.png into the folder
fig.savefig must be before show because when you close the figure, it is destroyed and only an empty (will appear blank) figure is saved.
There are several approaches, all of which require a modification of the external function that you don't want to change:
1 - modify the external function by adding a parameter to indicate if the figure must be saved or not, then using a conditional to save the figure or not.
def external function(params, dosave=False):
...
if dosave:
fig.savefig...
fig.show()
2 - modify the external function to return a figure that you can then choose to save prior to displaying it.
3 - Possibly decorate the external function so it saves the figure.
There may be a 'hacky way' to use ipython internals to keep a handle on the figures you are closing, but I don't know it.
I'm writing an app that allows you to drag and drop datafiles unto a gui which then plots it. However using plt.show() causes the interface to become non-interactive, that means I need to first close the plot before dragging and dropping another file. I wanted to avoid doing this.
I've tried using plt.ion() but doing that causes the plot gui from updating when you resize it or try to manually close it.
This is highly related to an earlier question by another person a couple of years ago: Matplotlib - Force plot display and then return to main code
I am using Canopy 1.5.5 on MacOSX 10.8.5, with matplotlib 1.4.3.
I will need to load data, look at it, press enter to approve and move to the next dataset (and do that a few thousand times, so it's kind of critical to get this functionality). Here is my MWE:
import numpy as np
from matplotlib import pyplot as plt
plt.ion()
plt.figure()
ind=np.arange(5)
for i in ind:
plt.clf()
plt.scatter(ind,ind+i)
plt.title('this is plot number %i' % i)
plt.show()
u=raw_input("Press any button")
The code seems to do everything EXCEPT actually showing me the plot. If I finish the script (or interrupt it), then I see the current figure.
I have tried everything from the previous answer: with and without interactive mode, with and without plt.show(block=False), every permutation of plt.draw and plt.show, and every backend on my available list.
This seems like a very basic functionality! Please tell me that this can be done. I find it weird that matplolib says here http://matplotlib.org/users/shell.html that "by default the drawing is deferred until the end of the script", but does not have suggestions on how to override the default. Please help!
Your example works for me (my backend is osx), although the figure window appears behind other windows at first. I needed to use alt-tab to raise it to the front.
Try starting your script with the --matplotlib option of IPython. You can select a backend or let it be auto-detected like so: ipython --matplotlib auto yourscript.py
Not sure if you now, but the raw_input function waits for you to press the return key, not just any key.
Edit:
About your last remark: this section explains how to force drawing before the end of the script. This can be done with the draw function. In interactive mode every pyplot command calls draw as well. Drawing in this context means rendering the figure by the backend.
I'm following a book by Wes McKinney and in the section introducing pandas, he's given a simple example of plotting a pandas Data Frame. Here're the lines I wrote:
tz_counts = frame['tz'].value_counts() # frame is a Data Frame
tz_counts[:10] # works fine till here. I can see the key-value I wanted
tz_counts[:10].plot(kind='barh', rot=0)
It just prints a line on screen that says
<matplotlib.axes.AxesSubplot object at 0x3d14ed0>
rather than displaying a plot window as I'd expect with matplotlib's plot function. What's wrong here? How can I make it work?
Matplotlib doesn't show the plot until you tell it to, unless you're in "interactive" mode.
Short Answer: Call plt.show() when you're ready to display the plot.
This starts the gui mainloop of whatever backend you're using, so it is blocking. (i.e. execution will stop until you close the window)
If you want it to show up automatically without stopping execution, you can turn on interactive mode either with plt.ion() or by using ipython --pylab.
However, using --pylab mode in ipython will import all of numpy, matplotlib.pyplot, and a few other things into the global namespace. This is convenient for interactive use, but teaches very bad habits and overwrites functions in the standard library (e.g. min, max, etc).
You can still use matplotlib's interactive mode in ipython without using "pylab" mode to avoid the global import. Just call plt.ion()
Matplotlib's default TkAgg backend will work in interactive mode with any python shell (not just ipython). However, other backends can't avoid blocking further execution without the gui mainloop being run in a separate thread. If you're using a different backend, then you'll need to tell ipython this with the --gui=<backend> option.
Try using:
%matplotlib
tz_counts = frame['tz'].value_counts()
tz_counts[:10].plot(kind='barh', rot=0)
Using % matplotlib prevents importing * from pylab and numpy which in turn prevents variable clobbering.