I am working in linux and I don't know why using python and matplotlib commands draws me only once the chart I want.
The first time I call show() the plot is drawn, wihtout any problem, but not the second time and the following.
I close the window showing the chart between the two calls. Do you know why and hot to fix it?
Thanks AFG
from numpy import *
from pylab import *
data = array( [ 1,2,3,4,5] )
plot(data)
[<matplotlib.lines.Line2D object at 0x90c98ac>]
show() # this call shows me a plot
#..now I close the window...
data = array( [ 1,2,3,4,5,6] )
plot(data)
[<matplotlib.lines.Line2D object at 0x92dafec>]
show() # this one doesn't shows me anything
in windows this works perfect:
from pylab import *
plot([1,2,3,4])
[<matplotlib.lines.Line2D object at 0x03442C10>]
#close window here
plot([1,2,3,4])
[<matplotlib.lines.Line2D object at 0x035BC570>]
did you try with:
from matplotlib import interactive
interactive(True)
sometimes matplotlib produces some headaches because we have to remember that some options are set in matplotlibrc (such as the backend or the interactive parameters). If you use matplotlib from different editors (IDLE-tk, pycrust-wxpython) or alternating interactive with scripting, then you have to take into account that the configuration that works in one mode could give you problems in the other mode and must be modified programmatically or using a dedicated configuration file.
The example I give, works directly (and without show()) because in matplotlibrc I have interactive set to True as default
You likely have conflicts between your editor/IDE windowing system, and your plot windows.
A very good way around this is to use IPython. IPython is a great interactive environment, and has worked out these issues plus has many other advantages. At the beginning, start IPython with the command (from a terminal window) ipython -pylab to put it in the interactive pylab mode.
I'm guessing that you are doing this in IDLE on Windows because that's where I've noticed this same problem.
From what I've deduced, there is a problem with using the TkAgg backend,which comes with the basic Python dist and appears to be the default for matplotlib, when using matplotlib with IDLE. It has something to do with the way IDLE uses subprocesses because if I start IDLE with the -n option, which disables subprocesses, I don't have this problem. An easy way to start it IDLE with the -n option on Windows is to right click and file and select 'Open with IDLE'. If you do this you should get an IDLE shell which says
=== No Subprocess ===
just above the prompt. For instance, borrowing code from joaquin's solution, you could try this simple code:
from matplotlib import interactive
interactive(True)
from pylab import *
plot([1,2,3,4])
then close the window and type the last line into the console again. It works for me in IDLE with the -n option.
So what can you do? You can always run IDLE in the mode without subprocesses, but there are dangers to that. You can use a different IDE. Many people suggest IPython though I'm not sold on it yet myself. You could also try a different backend for matplotlib. I'm going to try that in a little while cause I've been wondering whether it will work.
show() is only meant to be used once in a program, at the very end: it is a never ending loop that checks for events in the graphic windows.
The normal way of doing what you want is:
# … plot …
draw() # Draws for real
raw_input() # Or anything that waits for user input
# … 2nd plot …
draw()
raw_input()
# Last plot
show() # or, again, draw(); raw_input()
You could try to see whether this works for you.
Alternatively, you can try to change the backend, as some backends work better than others:
import matplotlib
matplotlib.use('TkAgg') # For other backends, do matplotlib.use('') in a shell
Related
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.
I am running Python 2.7.2 on Mac 10.8 with matplotlib 1.1.1. The backend I am using is MacOSX. If I run any plotting code e.g.
import matplotlib.pyplot as plt
plt.plot([1,2,3], [4,5,6])
plt.show()
the plot window always appears on a different desktop from the one I am working on. This behaviour is the same if I use ipython or if I run a script. Is there a way around this? It's annoying to have to go and hunt for the plot each time!
If you previously moved it with OSX's desktop management commands you can fix it like this:
Right click (Command click) on the Python Icon of the Matplotlib Icon in the Dock. Under Options there are options to assign the "application" to Desktops. Set to none. If it still opens in another desktop, move it to desktop you want it on (one way is to click and hold the header of the window... press Ctrl-#, where # is the desktop you want it on)
Source
import matplotlib
matplotlib.use("wx")
from pylab import *
figure(1)
plot([1,2,3,4,5])
thismanager = get_current_fig_manager()
thismanager.window.SetPosition((500, 0))
show()
For TkAgg, just change it to:
thismanager.window.wm_geometry("+500+0")
I found this to be pretty helpful actually:
matplotlib window layout questions
Although, it seems that Brian has beat me to it. Have you checked out WXAgg?
>>> import matplotlib
>>> matplotlib.get_backend()
'WXAgg'
I've been trying for hours to get this simple script working, but nothing I do seems to help. It's a slight modification of the most basic animated plot sample code from the Matplotlib website, that should just show a few frames of noise (I have the same issue with the unmodified code from their website BTW).
On my computer with the TkAgg backend I get about 20 frames (out of 60) before the plot window freezes. With Qt4Agg I just get a frozen, black window and no frames at all are plotted. I've tried multiple combinations of different NumPy, PyQt, Python and Matplotlib versions, but always get the same result.
Please let me know if this works for you or if anything looks wrong. I'm pretty sure this did work in the past, so I'm thinking it may be a Windows issue or something related to ion().
FYI I'm using Windows 7 (32 bit) and I've tested with Python 2.6/2.7, MPL 1.0.0/0.9.9.8, PyQt 4.6/4.7, Numpy 1.4/1.5b.
import matplotlib
matplotlib.use('TkAgg') # Qt4Agg gives an empty, black window
from pylab import *
import time
ion()
hold(False)
# create initial plot
z = zeros(10)
line, = plot(z)
ylim(-3, 3)
for i in range(60):
print 'frame:', i
d = randn(10)
line.set_ydata(d)
draw()
time.sleep(10e-3)
This simpler version also freezes after the first couple frames:
from pylab import *
ion()
hold(False)
for i in range(40):
plot(randn(10))
draw()
show()
Thanks!
EDIT: These people seem to be having the same or a similar problem as me:
mail-archive.com/matplotlib-users#lists.sourceforge.net/msg10844.html
stackoverflow.com/questions/2604119/matplotlib-pyplot-pylab-not-updating-figure-while-isinteractive-using-ipython
mail-archive.com/matplotlib-users#lists.sourceforge.net/msg01283.html
Doesn't look like any of them were able to fix it either :(
Typically, GUI frameworks need to 'own' the main loop of the program. Sitting in a tight loop with sleeps to delay iterations will usually 'break' GUI applications (your problem description is consistent with typical breakage along these lines). It's possible that the matplotlib devs have implemented some behind the scenes logic to pevent these lockups from happening for certain toolkits but restructuring your program slightly should eliminate any chance of mainloop ownership being the problem (which is very likely I think). The matplotlib animation wiki also suggests using native event loops for anything nontrivial (probably for this reason)
Rather than sitting in a loop with sleeps, I suggest that, instead, you use the GUI toolkit to schedule a function call after a certain delay.
def update_function():
# do frame calculation here
refresh_timer = QtCore.QTimer()
QtCore.QObject.connect( refresh_timer, QtCore.SIGNAL('timeout()'), update_function )
refresh_timer.start( 1.0 / 30 ) # have update_function called at 30Hz
Looking at the matplotlib documentation suggests that it may be possible to use their API natively but I couldn't find any good examples using just a quick search.
When you say freezes after the first couple of frames do you mean 2 or 3, or say, 40 or 60, as those are the upper limits of your loop?
If you want the animation to continue indefinitely you need something like
while True:
d = randn(10)
line.set_ydata(d)
draw()
time.sleep(10e-3)
But you'll have to force quit your program.
Generally you can't use show() and draw() like this. As the Posts are suggesting, you need a small GUI loop, just look at the Animations examples on the Matplotlib page.
After many hours fighting with this same issue I think I've found the answer: To do these simple animations with matplotlib you can only use the GTKAgg backend. This is stated as a passing remark in the scipy cookbook, but I think it should be stressed more clearly. When I use it, I can run your animations until the end without freezes or any other problem.
Beware that to use this backend you need to install PyGTK. I don't know what else you need on Windows (because I'm on Linux) but that seems the minimum. Besides, if you want to use it by default you have to add this line to your matplotlibrc (on Linux placed on ~/.matplotlib/matplotlibrc):
backend : GTKAgg
To use the other backends you need to follow the official matplotlib examples, but that means you have to build a mini-gui application just to run a simple animation, and I find that quite awful!
I was struggling with this same problem for quite a while. I would recommend taking a look at this example: http://matplotlib.sourceforge.net/examples/animation/strip_chart_demo.html
I thought I was following this example exactly, but it wasn't working. It would only run the "update" function one time. Turns out the only difference in my code was that the animation.FuncAnimation() was not assigned to a variable. As soon as I assigned the return value of animation.FuncAnimation() to a value, everything worked.
I was having (I think) the same trouble, where the window would freeze if I took the focus off it or tried to drag it around, using Python 2.7 on Windows 7 with Matplotlib 1.3, and TKAgg backend. I had a call to time.sleep(1) in my main while loop, and when I replaced that with plt.pause(1), that fixed the problem. So, try and use matplotlib's pause function rather than time module sleep function, it worked for me.
calling time.sleep() or plt.pause() causes flicker on the graph window when using blitting, but I got good results by simply calling the event loop explicitely :
fig.canvas.blit() # or draw()
fig.canvas.start_event_loop(0.001) #1 ms seems enough
greetings from the future.
Here's how you'd do it in python 3:
import matplotlib
matplotlib.use('TkAgg') # Qt4Agg gives an empty, black window
import matplotlib.pylab as plt
import time
# create initial plot
z = zeros(10)
line, = plot(z)
ylim(-3, 3)
for i in range(60):
print('frame:', i)
d = randn(10)
line.set_ydata(d)
draw()
#replace time.sleep() with plt.pause()
plt.pause(0.5)
I got rid of the call to ion() and hold(False). I also replaced time.sleep with plt.pause
I just installed matplotlib in Ubuntu 9.10 using the synaptic package system.
However, when I try the following simple example
>>> from pylab import plot;
>>> plot([1,2,3],[1,2,3])
[<matplotlib.lines.Line2D object at 0x9aa78ec>]
I get no plot window. Any ideas on how to get the plot window to show?
You can type
import pylab
pylab.show()
or better, use ipython -pylab.
Since the use of pylab is not recommended anymore, the solution would nowadays be
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.show()
pylab.show() works but blocks (you need to close the window).
A much more convenient solution is to do pylab.ion() (interactive mode on) when you start: all (the pylab equivalents of) pyplot.* commands display their plot immediately. More information on the interactive mode can be found on the official web site.
I also second using the even more convenient ipython -pylab (--pylab, in newer versions), which allows you to skip the from … import … part (%pylab works, too, in newer IPython versions).
Try this:
import matplotlib
matplotlib.use('TkAgg')
BEFORE import pylab
The code snippet below works on both Eclipse and the Python shell:
import numpy as np
import matplotlib.pyplot as plt
# Come up with x and y
x = np.arange(0, 5, 0.1)
y = np.sin(x)
# Just print x and y for fun
print x
print y
# Plot the x and y and you are supposed to see a sine curve
plt.plot(x, y)
# Without the line below, the figure won't show
plt.show()
Any errors show up? This might an issue of not having set the backend. You can set it from the Python interpreter or from a config file (.matplotlib/matplotlibrc) in you home directory.
To set the backend in code you can do
import matplotlib
matplotlib.use('Agg')
where 'Agg' is the name of the backend. Which backends are present depend on your installation and OS.
http://matplotlib.sourceforge.net/faq/installing_faq.html#backends
http://matplotlib.org/users/customizing.html
Modern IPython uses the "--matplotlib" argument with an optional backend parameter. It defaults to "auto", which is usually good enough on Mac and Windows. I haven't tested it on Ubuntu or any other Linux distribution, but I would expect it to work.
ipython --matplotlib
If you encounter an issue in which pylab.show() freezes the IPython window (this may be Mac OS X specific; not sure), you can cmd-c in the IPython window, switch to the plot window, and it will break out.
Apparently, future calls to pylab.show() will not freeze the IPython window, only the first call. Unfortunately, I've found that the behavior of the plot window / interactions with show() changes every time I reinstall matplotlib, so this solution may not always hold.
If you are starting IPython with the --pylab option, you shouldn't need to call show() or draw(). Try this:
ipython --pylab=inline
--pylab no longer works for Jupyter, but fortunately we can add a tweak in the ipython_config.py file to get both pylab as well as autoreload functionalities.
c.InteractiveShellApp.extensions = ['autoreload', 'pylab']
c.InteractiveShellApp.exec_lines = ['%autoreload 2', '%pylab']
If you are user of Anaconda and Spyder then best solution for you is that :
Tools
-->
Preferences
-->
Ipython console
-->
Graphic Section
Then in the Support for graphics (Matplotlib) section:
select two avaliable options
and in the Graphics Backend:
select Automatic
Another possibility when using easy_install is that you need to require the most recent version of matplotlib.
Try:
import pkg_resources
pkg_resources.require("matplotlib")
before you import matplotlib or any of its modules.