Problem with simple use of draw() in animations of arrays

View: New views
3 Messages — Rating Filter:   Alert me  

Problem with simple use of draw() in animations of arrays

by David Sanders-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I have a problem with draw() to do simple animations of the contents of arrays in matplotlib.

I was trying to use the idea in the animations cookbook (http://www.scipy.org/Cookbook/Matplotlib/Animations)
to animate some "random walkers", but found that the animation did not work.

A minimal example of the problem is given by changing the first recipe in the cookbook to just draw random arrays.
This version correctly animates as expected:

from pylab import *
import time

ion()

tstart = time.time()               # for profiling
x = rand(100)
y = rand(100)
line, = plot(x,y, ',')
for i in arange(1,200):
    x = rand(100)
    y = rand(100)
    line.set_data(x,y)
    draw()                         # redraw the canvas

Now, however, changing the "x =" and "y =" lines as follows:
    x[:] = rand(100)
    y[:] = rand(100)

so that they are modified in place, rather than creating new arrays, no longer animates anything.
I am using version 0.99 on linux (Kubuntu 9.10).
The same behaviour is found from within ipython -pylab  or from the command line with python.

In my real application, I wish to use this as a simple way to animate a collection of random walkers.
I thus have an array of positions which is updated at every step, and this is what I want to animate,
which is the reason why I tried the array updating step above.

So far, my code is as follows:

from pylab import *

ion()

N = 1000
pos = zeros((N,2))

figure(figsize=(8,8))
points, = plot(pos[:,0], pos[:,1], ',')
axis([-20,20,-20,20])

for t in range(1000):
 
    pos += uniform(-1,1,N*2).reshape(N,2)
    points.set_data(pos[:,0].copy(), pos[:,1].copy())
    draw()

The ".copy()" are an attempt at creating new arrays. Nonetheless, there is no animation.
And if I put
points._x
in ipython, then it still has all zeros! Apparently the .set_data() hasn't done anything.

Any help at getting this animation to work are greatly appreciated!

Thanks and best wishes,
David.




------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@...
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Re: Problem with simple use of draw() in animations of arrays

by Jae-Joon Lee :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Nov 2, 2009 at 10:52 PM, David Sanders <dpsanders@...> wrote:

> from pylab import *
>
> ion()
>
> N = 1000
> pos = zeros((N,2))
>
> figure(figsize=(8,8))
> points, = plot(pos[:,0], pos[:,1], ',')
> axis([-20,20,-20,20])
>
> for t in range(1000):
>
>     pos += uniform(-1,1,N*2).reshape(N,2)
>     points.set_data(pos[:,0].copy(), pos[:,1].copy())
>     draw()

The Line2D object keeps the input data as a cache and only update it
(recache) if the new data is different than the cached one.
The problem in this particular case is that the cache is actually a
*pos* itself. And modifying the pos in place, actually modify the
cache in the Line2D object. Thus, set_data sees that the given data is
identical to the cached one, and skip the recaching.
I'm not sure what is the best approach here, and I defer the fix (or
not) to others.
Meanwhile, you can force the recaching with recache method. i.e., call
points.recache() after set_data. You don't need to make a copy also.
As a matter of fact, I think it will give you a best performance (but
not tested) if you directly update the cached data and do not call
set_data.
Note that in this particular case, pos == cache, so you actually don't
need to call get_data, but this is not a general case.

posx, posy = points.get_data(orig=True)

for t in range(100):
    dx, dy = uniform(-1,1,N*2).reshape(2, N) # note the change in the shape
    posx += dx
    posy += dy
    points.recache()
    draw()

Regards,

-JJ

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@...
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Re: Problem with simple use of draw() in animations of arrays

by David Sanders-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Mon, Nov 2, 2009 at 11:51 PM, Jae-Joon Lee <lee.j.joon@...> wrote:
On Mon, Nov 2, 2009 at 10:52 PM, David Sanders <dpsanders@...> wrote:
> from pylab import *
>
> ion()
>
> N = 1000
> pos = zeros((N,2))
>
> figure(figsize=(8,8))
> points, = plot(pos[:,0], pos[:,1], ',')
> axis([-20,20,-20,20])
>
> for t in range(1000):
>
>     pos += uniform(-1,1,N*2).reshape(N,2)
>     points.set_data(pos[:,0].copy(), pos[:,1].copy())
>     draw()

The Line2D object keeps the input data as a cache and only update it
(recache) if the new data is different than the cached one.
The problem in this particular case is that the cache is actually a
*pos* itself. And modifying the pos in place, actually modify the
cache in the Line2D object. Thus, set_data sees that the given data is
identical to the cached one, and skip the recaching.
I'm not sure what is the best approach here, and I defer the fix (or
not) to others.
Meanwhile, you can force the recaching with recache method. i.e., call
points.recache() after set_data. You don't need to make a copy also.
As a matter of fact, I think it will give you a best performance (but
not tested) if you directly update the cached data and do not call
set_data.
Note that in this particular case, pos == cache, so you actually don't
need to call get_data, but this is not a general case.

posx, posy = points.get_data(orig=True)

for t in range(100):
   dx, dy = uniform(-1,1,N*2).reshape(2, N) # note the change in the shape
   posx += dx
   posy += dy
   points.recache()
   draw()


Dear JJ,

Many thanks for your answer -- "points.recache()" is exactly what I was looking for to make my animations work.

It seems to me that this must be a reasonably common question, but I could not find it in the documentation.
Perhaps it could be added to the animation cookbook?

Thanks and best wishes,
David.

PS: Apologies for the late reply -- I was travelling with difficult internet access.



------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@...
https://lists.sourceforge.net/lists/listinfo/matplotlib-users