5

I'm starting programming in Python (and OOP), but I have a solid experience in Fortran (90/95) and Matlab programming.

I'm developing a little tool using animation on tkinter environment. The goal of this tool is to animate multi-lines (an array and not a vector of data). Below, a simple example of my problem. I don't understand why the result of these two ways of plotting data are so different ?

from pylab import *

Nx=10
Ny=20

xx   = zeros( ( Nx,Ny) )
data = zeros( ( Nx,Ny) )

for ii in range(0,Nx):
    for jj in range(0,Ny):
        xx[ii,jj]   = ii
        data[ii,jj] = jj


dline = plot(xx,data)

mline, = plot([],[])
mline.set_data(xx.T,data.T)

show()

If you plot only "dline" each line is plotted separately and with a different color. If you plot only "mline" all the lines are linked and with only one color.

My goal is to make an animation with "mline" changing the data at each loop. Here a simple source code illustrating my purposes :

from pylab import *
from matplotlib import animation

Nx=10
Ny=20

fig = plt.figure()
fig.set_dpi(100)
fig.set_size_inches(7, 6.5)

ax = plt.axes(xlim=(0, Nx), ylim=(0, Ny))

xx   = zeros( ( Nx,Ny) )
data = zeros( ( Nx,Ny) )
odata = zeros( ( Nx,Ny) )

for ii in range(0,Nx):
    for jj in range(0,Ny):
        xx[ii,jj]    = ii
        odata[ii,jj] = jj
        data[ii,jj]  = 0.

#dline = plot(xx,odata)

mline, = plot([],[])

def init():
    mline.set_data([],[])
    return mline,

def animate(coef):
   for ii in range(0,Nx):
        for jj in range(0,Ny):
            data[ii,jj] = odata[ii,jj] * (1.-float(coef)/360.)

   mline.set_data(xx.T,data.T)
   return mline,

anim = animation.FuncAnimation(fig, animate, 
                               init_func=init, 
                               frames=360, 
                               interval=5,
                               blit=True)

plt.show()

I hope that I have clearly exposed my problem.

Thanks, Nicolas.

2
  • 2
    If you pass 2D data to plt.plot() it is transformed into separate items, so dline is a list containing 20 individual line objects. Your mline is just a single line object. If you pass it 2D data, the data is flattened, as if you use dline = ax.plot(xx.flat,data.flat). Commented Oct 22, 2013 at 13:58
  • Thank you Rutger Kassies for your help. I post the solution of my problem below. Commented Oct 23, 2013 at 8:27

2 Answers 2

5

as @Rutger Kassies points out in the comments,

dline = plot(xx,data)

does some magic parsing on the input data, separates your arrays into a bunch of x-y pairs and plots those. Note that dline is a list of Line2D objects. In this case

mline, = plot([],[])
mline.set_data(xx.T,data.T)

you are creating a single Line2D object and the library does it's best to shove 2D data, into a 1D plotting objects and does so by flattening the input.

To animate N lines, you just need N Line2D objects:

lines = [plot([],[])[0] for j in range(Ny)] # make a whole bunch of lines

def init():
    for mline in lines:
        mline.set_data([],[])
    return lines

def animate(coef):
   data = odata * (1.-float(coef)/360.)
   for mline, x, d in zip(lines, data.T, xx.T):
       mline.set_data(x, d)
   return lines

You also don't need to pre-allocate data and doing the loops in python is much slower than letting numpy do them for you.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you tcaswell for your help. The solution of my problem is posted below.
0

Many thanks to Rutger Kassies and tcaswell. Here the same example as above but now it works as I want. I hope that it will help another python programmers.

from pylab import *
from matplotlib import animation

Nx=10
Ny=20

fig = plt.figure()
fig.set_dpi(100)
fig.set_size_inches(7, 6.5)
axis([0, Nx-1, 0, Ny])

xx    = zeros( ( Nx,Ny) )
data  = zeros( ( Nx,Ny) )
odata = zeros( ( Nx,Ny) )

for ii in range(0,Nx):
    xx[ii,:]    = float(ii)

for jj in range(0,Ny):
    odata[:,jj] = float(jj)

#dline = plot(xx,odata)

lines = [plot([],[])[0] for j in range(Ny)] # make a whole bunch of lines


def init():
    for mline in lines:
        mline.set_data([],[])
    return lines

def animate(coef):

   data = odata * (1.-float(coef)/360.)

   for mline, x, d in zip(lines, xx.T, data.T,):
       mline.set_data(x, d)

   return lines

anim = animation.FuncAnimation(fig, animate, 
                               init_func=init, 
                               frames=360, 
                               interval=5,
                               blit=True)

plt.show()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.