简体   繁体   English

Python,Matplotlib,绘制多条线(数组)和动画

[英]Python, Matplotlib, plot multi-lines (array) and animation

I'm starting programming in Python (and OOP), but I have a solid experience in Fortran (90/95) and Matlab programming. 我开始使用Python(和OOP)进行编程,但是我在Fortran(90/95)和Matlab编程方面有丰富的经验。

I'm developing a little tool using animation on tkinter environment. 我正在开发一个在tkinter环境上使用动画的小工具。 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. 如果仅绘制“ dline”,则每条线将分别绘制并使用不同的颜色。 If you plot only "mline" all the lines are linked and with only one color. 如果仅绘制“ mline”,则所有线都是链接的,并且只有一种颜色。

My goal is to make an animation with "mline" changing the data at each loop. 我的目标是制作一个动画,其中“ mline”在每个循环中更改数据。 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. 谢谢,尼古拉斯。

as @Rutger Kassies points out in the comments, 正如@Rutger Kassies在评论中指出的那样,

dline = plot(xx,data)

does some magic parsing on the input data, separates your arrays into a bunch of xy pairs and plots those. 对输入数据进行一些魔术分析,将您的数组分成一堆xy对,并绘制它们。 Note that dline is a list of Line2D objects. 请注意, dlineLine2D对象的列表 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. 您正在创建一个Line2D对象,并且库最好将2D数据推入1D绘图对象中,并通过展平输入来做到这一点。

To animate N lines, you just need N Line2D objects: 要制作N条线的动画,您只需要N Line2D对象:

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. 您也不需要预先分配data并且在python中执行循环比让numpy为您完成循环要慢得多。

Many thanks to Rutger Kassies and tcaswell. 非常感谢Rutger Kassies和tcaswell。 Here the same example as above but now it works as I want. 这里与上面相同的示例,但是现在它可以按我的要求工作。 I hope that it will help another python programmers. 我希望它将对其他python程序员有所帮助。

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM