Plotting from a script or loop with spyder

4,377 views
Skip to first unread message

Andrew Collette

unread,
Mar 1, 2012, 1:30:14 PM3/1/12
to spyd...@googlegroups.com
Hi,

I'm transitioning from using IDL to using Python for analysis.
There's one (important) thing I can't get working, which is plotting
from a loop or script. The simplest fragment I could find that
reproduces the problem is:

import numpy as np
import time
import pylab as p

a = np.arange(10)

for x in xrange(10):
p.plot(x)
time.sleep(1)

Whether in a .py file or entered manually at the console, the result
is the same: a plot window appears but is blank and frozen (won't
respond to clicks); when the loop exits, all ten plots suddenly show
up in the figure at once.

I've tried various combinations of pylab.ion(), draw(), show() with no
success. This is a real problem as it's very common in the IDL world
to plot many time series one after another, sometimes reading input
from the user for each one. For example, I need to manually go
through a dataset and throw out the bad traces, using input() in place
of the sleep command.

Any ideas? I am using Spyder 2.0.13 as part of PythonXY.

Thanks,
Andrew Collette

Jonatan Hjul

unread,
Mar 2, 2012, 3:04:47 AM3/2/12
to spyder
I have had the same problem - but I thought it was a problem with
matplotlib and not Spyder, so I did not investigate a lot more.

/Jonatan

David Verelst

unread,
Mar 2, 2012, 4:12:21 AM3/2/12
to spyd...@googlegroups.com
two changes that made it work for me:

import numpy as np

#import time

import pylab as p

a = np.arange(10)

for x in xrange(5):

p.figure()

p.plot(a)


1. p.plot(a) instead of p.plot(x): x is just one point so the plot looks a bit empty
2. p.figure() will force matplotlib to open a new figure

You could also save the figure (p.savefig()) than optionally close it (p.close()) before moving on the next.

Is this solving your problem?

Regards,
David

Andrew Collette

unread,
Mar 2, 2012, 12:04:02 PM3/2/12
to spyd...@googlegroups.com
Hi,

> two changes that made it work for me:
>
> import numpy as np
>
> #import time
>
> import pylab as p
>
> a = np.arange(10)
>
> for x in xrange(5):
>
> p.figure()
>
> p.plot(a)

I tried this, and it created ten empty windows one at a time, all of
which are blank until the loop finishes. There's something about how
the plot command works that doesn't actually draw anything until the
script is over. ion() and p.draw() don't seem to do anything when put
in the script.

Andrew

David Verelst

unread,
Mar 3, 2012, 5:41:21 AM3/3/12
to spyd...@googlegroups.com
Hi,

Ok, I actually observe the same problem as you are having. Since I hardly use the interactive plotting mode  I never came across this issue before. When I create figures in a loop I always save them directly to a .png and/or .eps file and watch them from there. This allows me to easily inspect many different figures while the script is still doing other stuff.

It is important to note that this issue is not related to spyder, but two other factors (at least, that is what I think, but not that I am not a developer):
1) the loop in the script prevents the event loop to kick in and actually draw the figure (based on this: http://www.mail-archive.com/matplotl...@lists.sourceforge.net/msg13375.html)
2) different matplotlib plotting backends deal with this differently, and maybe the Qt4Agg backend has some issues on this department (http://www.mail-archive.com/matplotl...@lists.sourceforge.net/msg13383.html)

My matplotlib backend is set to Qt4Agg. You can change the backend as follows (note that each backend comes with it own dependencies...):
* directly in Spyder: Tools > Preferences > Console > External modules > Matplotlib GUI backend
* matplotlib.use('backendname') (do this before importing pylab!), more info on the backends can be found here: http://matplotlib.sourceforge.net/faq/usage_faq.html#what-is-a-backend
* in the matplotlib config file, but I'll ignore that here (http://matplotlib.sourceforge.net/users/customizing.html#customizing-matplotlib)

I played a bit with the different backends, and adding two draw() statements behind each other, but it never got really better on my end. GTKAgg came close, but while the script is running the figures are not redrawn automatically (or something): when moving figure 2 over figure 1, figure 1 changed grey.

import numpy as np

import time

import pylab as p

a = np.arange(10)

for x in xrange(3):

p.figure()

p.plot(a)

p.draw()

p.draw()

p.show()

time.sleep(2)


Short term conclusion as far as I am concerned: if you want to browse through different figures that are made in a script and while the script is still running: save them to disc and watch from there.

Note that if I execute the script in a "dedicated interpreter" (contrary to "current interpreter", you can change those settings by pressing F6 to see the "run configurations" for each script), the figure gets drawn correctly, but the scripts only advances after you closed the figure again.

Disclaimer: I am not a developer so I only have limited knowledge on these matters.

Regards,
David

Chris

unread,
Mar 10, 2012, 3:29:49 PM3/10/12
to spyd...@googlegroups.com
Hi,
I find that this similar loop, which uses raw_input() to step through plot updates, can be accomplished when run directly from python command-line or from ipython, but when run in a Spyder python or ipython console it waits until after the loop to show the figure:


import numpy as np

import pylab as p

p.ion()

for x in xrange(1,10):

p.plot(np.linspace(x,x*2,10),np.linspace(0,x,10))

p.show()

raw_input('input: ')


Using time.sleep(), as you have below, does not work when run from a spyder console or from python/ipython command lines.

Pierre Raybaut

unread,
Mar 26, 2012, 4:16:19 PM3/26/12
to spyd...@googlegroups.com
Hi,

In your code, simply replace this:
       time.sleep(1)
by that:
       p.waitforbuttonpress(1)

Using time.sleep will freeze the GUI because it will block the scripts
execution hence preventing the Qt event loop from processing events
and updating the GUI.

HTH,
Pierre

> --
> You received this message because you are subscribed to the Google Groups "spyder" group.
> To post to this group, send email to spyd...@googlegroups.com.
> To unsubscribe from this group, send email to spyderlib+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/spyderlib?hl=en.
>

Andrew Collette

unread,
Mar 26, 2012, 4:22:07 PM3/26/12
to spyd...@googlegroups.com
> In your code, simply replace this:
>         time.sleep(1)
> by that:
>         p.waitforbuttonpress(1)

Awesome! Thanks; this makes analysis in Python so much easier.

Andrew

Reply all
Reply to author
Forward
0 new messages