I'm studying matplotlib and don't know how to just save the graph and not print it on the screen.
So I've done some research on the Internet, many answers said the solution is matplotlib.use('Agg'). And it must be before importing matplotlib.pyplot or pylab.
Then when I added it in the first line of my script, it doesn't work at all.
import matplotlib
matplotlib.use('Agg')
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
E:\Program Files\Anaconda3\lib\site-packages\matplotlib\__init__.py:1401: UserWarning: This call to matplotlib.use() has no effect
because the backend has already been chosen;
matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
or matplotlib.backends is imported for the first time.
warnings.warn(_use_error_msg)
I use Anaconda Spyder, so I restarted kernel and ran my script again, I got same wrong information.
Then I restarted kernel again and directly typed the following code in the console:
In[1]: import matplotlib as mpl
In[2]: mpl.use('Agg')
E:\Program Files\Anaconda3\lib\site-packages\matplotlib\__init__.py:1401: UserWarning: This call to matplotlib.use() has no effect
because the backend has already been chosen;
matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
or matplotlib.backends is imported for the first time.
warnings.warn(_use_error_msg)
Also, if I delete 'plt.show()' at the end of script or add 'plt.ioff()', the graph will always print on the screen.
Thanks for everyone's answer. Now I have two solutions:
just use plt.close() , this will not change the backend and the figure doesn't show up.
use plt.switch_backend('Agg'), this will switch the backend to 'agg' and no figure printed on the screen.
You can try to switch the backend. Apparently Spyder loads matplotlib before you do, and use has no effect. This may be helpful:
How to switch backends in matplotlib / Python
The answer to your original question is simple.
If you don't want to show the graph on screen, just don't use plt.show()
So what you've gotta do is simply:
import matplotlib.pylab as plt
plt.plot(x,y) #whatever the x, y data be
#plt.show() """Important: either comment this line or delete it"""
plt.savefig('path/where/you/want/to/save/filename.ext')
#'filename' is either a new file or an already existing one which will get overwritten at the time of execution. 'ext' can be any valid image format including jpg, png, pdf, etc.
plt.plot(x,y)
plt.savefig('path/figure_filename.jpg',dpi=300)
Related
I am trying to run a simple code to plot my data using matplotlib in python2.7.10 :
import matplotlib.pyplot as plt
y=[23,35,43,54,76]
x=[2,4,5,6,7]
plt.plot(y,x)
I am getting the error:
super(FigureCanvasQTAggBase, self).__init__(figure=figure)
File "/usr/local/lib/python2.7/dist-packages/matplotlib/backends/backend_qt5.py", line 239, in __init__
super(FigureCanvasQT, self).__init__(figure=figure)
TypeError: 'figure' is an unknown keyword argument
How can I fix it?
This seems to be a duplicate of: matplotlib Qt5Agg backend error: 'figure' is an unknown keyword argument, which I just posted an answer for, and duplicated below:
I had the same issue. I found the solution here
Specifically, the following now works:
import matplotlib
matplotlib.use('Qt4Agg')
from matplotlib import pyplot as plt
plt.figure(figsize=(12,8))
plt.title("Score")
plt.show()
Just adding to Marc's answer. If you are using Spyder,
matplotlib.use('Qt4Agg')
may not work well because matplotlib has been imported when you open Spyder.
Instead you can go to (in Spyder) Tools - Preferences -IPython console - Graphics to change the backend and restart Spyder.
adding to this, i ran into this problem when i wanted to plot my values for my KNN training sets and test set results.
using TkAgg also fixes the problem
"matplotlib.use('TkAgg')"
import matplotlib
matplotlib.use('TkAgg')
#matplotlib.use('Qt4Agg')
import matplotlib.pyplot as plt
plt.figure(figsize=(12,8))
plt.title("Score")
plt.show()
Introduction
As I am coming from matlab, I am used to an interactive interface where a script can update figures while it is running. During the processing each figure can be re-sized or even closed. This probably means that each figure is running in its own thread which is obviously not the case with matplotlib.
IPython can imitate the Matlab behavior using the magic command %pylab or %matplotlib which does something that I don't understand yet and which is the very point of my question.
My goal is then to allow standalone Python scripts to work as Matlab does (or as IPython with %matplotlib does). In other words, I would like this script to be executed from the command line. I am expecting a new figure that pop-up every 3 seconds. During the execution I would be able to zoom, resize or even close the figure.
#!/usr/bin/python
import matplotlib.pyplot as plt
import time
def do_some_work():
time.sleep(3)
for i in range(10):
plt.plot([1,2,3,4])
plt.show() # this is way too boilerplate, I'd like to avoid it too.
do_some_work()
What alternative to %matplotlib I can use to manipulate figures while a script is running in Python (not IPython)?
What solutions I've already investigated?
I currently found 3 way to get a plot show.
1. %pylab / %matplotlib
As tom said, the use of %pylab should be avoided to prevent the namespace to be polluted.
>>> %pylab
>>> plot([1,2,3,4])
This solution is sweet, the plot is non-blocking, there is no need for an additionnal show(), I can still add a grid with grid() afterwards and I can close, resize or zoom on my figure with no additional issues.
Unfortunately the %matplotlib command is only available on IPython.
2. from pylab import * or from matplotlib.pyplot import plt
>>> from pylab import *
>>> plot([1,2,3,4])
Things are quite different here. I need to add the command show() to display my figure which is blocking. I cannot do anything but closing the figure to execute the next command such as grid() which will have no effect since the figure is now closed...
** 3. from pylab import * or from matplotlib.pyplot import plt + ion()**
Some suggestions recommend to use the ion() command as follow:
>>> from pylab import *
>>> ion()
>>> plot([1,2,3,4])
>>> draw()
>>> pause(0.0001)
Unfortunately, even if the plot shows, I cannot close the figure manually. I will need to execute close() on the terminal which is not very convenient. Moreover the need for two additional commands such as draw(); pause(0.0001) is not what I am expecting.
Summary
With %pylab, everything is wonderful, but I cannot use it outside of IPython
With from pylab import * followed by a plot, I get a blocking behavior and all the power of IPython is wasted.
from pylab import * followed by ion offers a nice alternative to the previous one, but I have to use the weird pause(0.0001) command that leads to a window that I cannot close manually (I know that the pause is not needed with some backends. I am using WxAgg which is the only one that works well on Cygwin x64.
This question advices to use matplotlib.interactive(True). Unfortunately it does not work and gives the same behavior as ion() does.
Change your do_some_work function to the following and it should work.
def do_some_work():
plt.pause(3)
For interactive backends plt.pause(3) starts the event loop for 3 seconds so that it can process your resize events. Note that the documentation says that it is an experimental function and that for complex animations you should use the animation module.
The, %pylab and %matplotlib magic commands also start an event loop, which is why user interaction with the plots is possible. Alternatively, you can start the event loop with %gui wx, and turn it off with %gui. You can use the IPython.lib.guisupport.is_event_loop_running_wx() function to test if it is running.
The reason for using ion() or ioff() is very well explained in the 'What is interactive mode' page. In principle, user interaction is possible without IPython. However, I could not get the interactive-example from that page to work with the Qt4Agg backend, only with the MacOSX backend (on my Mac). I didn't try with the WX backend.
Edit
I did manage to get the interactive-example to work with the Qt4Agg backend by using PyQt4 instead of PySide (so by setting backend.qt4 : PyQt4 in my ~/.config/matplotlibrc file). I think the example doesn't work with all backends. I submitted an issue here.
Edit 2
I'm afraid I can't think of a way of manipulating the figure while a long calculation is running, without using threads. As you mentioned: Matplotlib doesn't start a thread, and neither does IPython. The %pylab and %matplotlib commands alternate between processing commands from the read-eval-print loop and letting the GUI processing events for a short time. They do this sequentially.
In fact, I'm unable to reproduce your behavior, even with the %matplotlib or %pylab magic. (Just to be clear: in ipython I first call %matplotlib and then %run yourscript.py). The %matplotlib magic puts Matplotlib in interactive-mode, which makes the plt.show() call non-blocking so that the do_some_work function is executed immediately. However, during the time.sleep(3) call, the figure is unresponsive (this becomes even more apparent if I increase the sleeping period). I don't understand how this can work at your end.
Unless I'm wrong you'll have to break up your calculation in smaller parts and use plt.pause (or even better, the animation module) to update the figures.
My advice would be to keep using IPython, since it manages the GUI event loop for you (that's what pylab/pylot does).
I tried interactive plotting in a normal interpreter and it worked the way it is expected, even without calling ion() (Debian unstable, Python 3.4.3+, Matplotlib 1.4.2-3.1). If I recall it right, it's a fairly new feature in Matplotlib.
Alternatively, you can also use Matplotlib's animation capabilities to update a plot periodically:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time
plt.ion()
tt = np.linspace(0, 1, 200)
freq = 1 # parameter for sine
t0 = time.time() # for measuring ellapsed time
fig, ax = plt.subplots()
def draw_func(i):
""" This function gets called repeated times """
global freq # needed because freq is changed in this function
xx = np.sin(2*np.pi*freq*tt)/freq
ax.set_title("Passed Time: %.1f s, " % (time.time()-t0) +
"Parameter i=%d" % i)
ax.plot(tt, xx, label="$f=%d$ Hz" % freq)
ax.legend()
freq += 1
# call draw_func every 3 seconds 1 + 4 times (first time is initialization):
ani = animation.FuncAnimation(fig, draw_func, np.arange(4), interval=3000,
repeat=False)
# plt.show()
Checkout matplotlib.animation.FuncAnimation for details. You'll find further examples in the examples section.
I have a problem using pyplot. I am new to Python so sorry if I am doing some obvious mistake.
After I have plotted something using pyplot it shows the graph, but when I then try and add e.g. ylabel it will not update the current graph. It results in a new graph with only the ylabel, not previously entered information. So to me it seems to be a problem with recognizing the current graph/axis, but the ishold delivers a True statement.
My setup is Python 2.7 in Python(x,y). The problem occurs both in the Spyder IDE and the IPython Qt Console. It does however not occur in the regular IPython console (which, by constrast, is not interactive, but everything is included when using show(). When I turn off interactive in Spyder/Qt console it does not show anything after using the show() command).
import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
Out[2]: [<matplotlib.lines.Line2D at 0x78ca370>]

plt.ylabel('test')
Out[3]: <matplotlib.text.Text at 0x5bd5990>

plt.ishold()
Out[4]: True
matplotlib.get_backend()
Out[6]: 'module://IPython.kernel.zmq.pylab.backend_inline'
Hope any of you have some input. Thanks.
This is one of the things were InlineBackend have to behave differently from other backend or you would have sort of a memory leak. You have to keep explicit handle to matplotlib figure and/or set close_figure to False in config. Usually pyplot is a compatibility layer for matlab for convenience, try to learn to do using the Object Oriented way.
fig,ax = subplots()
ax.plot(range(4))
ax.set_ylabel('my label')
...
I am using the anaconda distribution of ipython/Qt console. I want to plot things inline so I type the following from the ipython console:
%pylab inline
Next I type the tutorial at (http://pandas.pydata.org/pandas-docs/dev/visualization.html) into ipython...
import matplotlib.pyplot as plt
import pandas as pd
ts = pd.Series(randn(1000), index = pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
ts.plot()
... and this is all that i get back:
<matplotlib.axes.AxesSubplot at 0x109253410>
But there is no plot. What could be wrong? Is there another command that I need to supply? The tutorial suggests that that is all that I need to type.
Plots are not displayed until you run
plt.show()
There could be 2 ways to approach this problem:
1) Either invoke the inline/osx/qt/gtk/gtk3/tk backend. Depends on the ipython console that you have been using. So, simply do:
%matplotlib inline #Here the inline backend is invoked, which removes the necessity of calling show after each plot.
or for ipython/qt console, do:
%matplotlib qt #This one works for me, thus, depends on the ipython console you use.
#
2) Or, do the traditional way as aforementioned (already answered above on this page):
plt.show() #However, you will have to call this show function each time.
I'm working to migrate from MatLab to python in Sage.
So I use these commands and I faced this error in Sage:
from scipy import misc
l = misc.lena();
import pylab as pl
pl.imshow(l)
The Error or message (i don't know) is:
matplotlib.image.AxesImage object at 0xb80198c
And it doesn't show any image
It's not an error, just print the object that method returned.
There are two ways to show the figure:
Add pl.show() after calling pl.imshow(l)
Use ipython --pylab to open your python shell,
That is an object being returned from pylab after using the "imshow" command. That is the location of the Axes image object.
documentation:
http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.imshow
Looks like it says it displays the object to the current axes. If you havent already created a plot I imagine you wont see anything
Simple google search suggests this might be what you are looking for
http://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.lena.html
from scipy import misc
l = misc.lena();
import pylab as pl
pl.imshow(l)
####use this
pl.show()