将数据做成动画

有时数据可视化并不能满足需求,我们希望能改变数据并更新它并重新可视化,比如动画。事实上,重新创建全部的可视化是非常低效的,而且会非常不稳定。为了解决这个问题,mlab提供了非常方便的方法,我们在这里给出一个非常简单的示例。 请参考:mlab.test_simple_surf_anim

import numpy as np
from mayavi import mlab
x, y = np.mgrid[0:3:1,0:3:1]
s = mlab.surf(x, y, np.asarray(x*0.1, 'd'))

for i in range(10):
    s.mlab_source.scalars = np.asarray(x*0.1*(i+1), 'd')

代码的前两行绘制了一个简单的平面。定义的函数体内部通过循环的方式,不断改变标量值使平面绕原点旋转。这里的关键之处在于传标量数据的`s`对象,它有一个特殊的属性`.mlab_source`,我们可以对它的子对象`.scalars`进行修改。如果我们相对坐标信息进行修改,我们同样可以这样做。

s.mlab_source.x = new_x

我们仅需记住,不应该改变x的数组维度

需要引起注意的是,这里所讨论的一些案例不一定是动画,仅仅是动画的最后一帧。如果将图像的每帧截图都保存下来,虽然您也将会得到相应的结果,但是您无法得到想要的效果。参考`animating_a_visualization`,学习`@animate`装饰器的用法来完成它。我们在这里展示一个简单的案例重写上面的动画。

import numpy as np
from mayavi import mlab
x, y = np.mgrid[0:3:1,0:3:1]
s = mlab.surf(x, y, np.asarray(x*0.1, 'd'))

@mlab.animate
def anim():
    for i in range(10):
        s.mlab_source.scalars = np.asarray(x*0.1*(i+1), 'd')
        yield

anim()
mlab.show()

如上面的案例,我们对生成器进行装饰,并将迭代封装在函数体中。

如果有多个值需要更新,您可以使用mlab的属性`mlab_source`,调用该属性的`set`方法,从而完成更加复杂的动画,案例如下:

# Produce some nice data.
n_mer, n_long = 6, 11
pi = np.pi
dphi = pi/1000.0
phi = np.arange(0.0, 2*pi + 0.5*dphi, dphi, 'd')
mu = phi*n_mer
x = np.cos(mu)*(1+np.cos(n_long*mu/n_mer)*0.5)
y = np.sin(mu)*(1+np.cos(n_long*mu/n_mer)*0.5)
z = np.sin(n_long*mu/n_mer)*0.5

# View it.
l = mlab.plot3d(x, y, z, np.sin(mu), tube_radius=0.025, colormap='Spectral')

# Now animate the data.
ms = l.mlab_source
for i in range(10):
    x = np.cos(mu)*(1+np.cos(n_long*mu/n_mer +
                                      np.pi*(i+1)/5.)*0.5)
    scalars = np.sin(mu + np.pi*(i+1)/5)
    ms.trait_set(x=x, scalars=scalars)

需要注意的是`set`方法使用的场合,使用该方法,渲染智慧重新计算一次。在这个案例中,数组的维度并没有发生变化,仅仅是其数值的更新。当数值的维度也发生变化的时候,我们需要用 `reset`方法,案例如下:

x, y = np.mgrid[0:3:1,0:3:1]
s = mlab.surf(x, y, np.asarray(x*0.1, 'd'),
              representation='wireframe')
# Animate the data.
fig = mlab.gcf()
ms = s.mlab_source
for i in range(5):
    x, y = np.mgrid[0:3:1.0/(i+2),0:3:1.0/(i+2)]
    sc = np.asarray(x*x*0.05*(i+1), 'd')
    ms.reset(x=x, y=y, scalars=sc)
    fig.scene.reset_zoom()

Mayavi提供了许多使用mlab动画的标准案例。您可以运行mlab.test_<name>_anim 说明:案例的名字都以anim结尾,这些例子用以说明是它们如何工作的。

备注

需要引起重视的是,set 和 reset 方法是有所差别的。当你没有改变数据的维度仅仅是对数值进行修改,使用 set 方法可以直接定义属性 (x, y, scalars 等)。但当数组的维度发生变化时候,则需要使用`reset`方法,它的行为通常是重新生成是所有的数据,相比`set`方法和设置特性而言,这种做法效率更低。

警告

如果不直接使用预制好的绘图函数,而是要配置Mayavi的pipeline管线,则`mlab_source` 属性只能先从sources数据源,经由mlab进行创建,更多细节将在子章节进行介绍。完全由mlab创建的管线,将提供这个属性。

备注

如果您有多个动画对象,每次您使用`mlab_source`属性进行修改,Mayavi都会对当前的scene层级弹出一个refresh用于更新的对话框。这个操作会耗费一定时间,会使您的动画变慢。下面这个案例能帮到您:acceleration_mayavi_scripts