データのアニメート

多くの場合,データをプロットするだけでは十分ではありません.また,プロットのデータを変更してプロットを更新しても,アニメーションを実行したり,インタラクティブアプリケーションで表示全体を再作成する必要はありません.実際,視覚化全体を再作成するのは非常に非効率的で,アニメーションがぎこちなくなります.そのために,mlabは既存の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')

最初の2行では単純な平面を定義しそれを表示します.次の3行では,スカラーを変更してそのデータをアニメートし,原点を中心に回転するプレーンを作成します.ここで重要なのは,上記の s オブジェクトには mlab_source という特別な属性があることです.このサブオブジェクトを使用すると,ポイントとスカラを操作できます. x の値を変更する場合は,次のように設定します.

s.mlab_source.x = new_x

ここで気をつけなければならないのは, x の形を変えてはならないということです.

ここで説明する例の多くは,まったくアニメートされていないように見える場合があり,アニメーションの最終的な状態を確認することができます.アニメーションの各段階でイメージのスクリーンショットを保存すると,正しい結果が得られます.ただし,画面上の視覚効果は得られません. @animate デコレータ (mayavi.mlab.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.animate デコレーターで修飾しています.

複数の値を変更する必要がある場合は, mlab_sourceset メソッドを使用して,次の例のようにより複雑に値を設定できます.

# 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 メソッドの使用に注意してください.この方法では,視覚化は1回だけ再計算されます.この場合,新しい配列のシェイプは変更されず,値だけが変更されます.配列の形状が変化した場合,以下のように 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()

mlabには,データのアニメーション化に関する多くの標準的な例が用意されています. mlab.test_<name>_anim という名前のサンプルを試してみてください.つまり名前の最後が _anim である,これらがどのように動作し実行されるかを確認します.

注釈

setreset を区別することが重要です.データの形状を変更せずに値だけを変更する場合は, set を使用するか,属性( x, y, scalars など)を直接設定します.配列の形や大きさが変わってきたら reset を使います.Resetは通常,すべてのデータを再生成し, set やtraitを直接設定する場合に比べて非効率です.

警告

Mayaviパイプラインを作成する場合,以下のサブセクションで説明するように,既製のプロット関数を使用する代わりに, mlab_source 属性が mlab によって作成されたソース上にのみ作成されます.mlab を使用してパイプライン全体を作成すると,この属性が表示されます.

注釈

複数のプロットオブジェクトをアニメートする場合, mlab_source アトリビュートを使用してデータを修正するたびに,Mayaviによってシーンのリフレッシュがトリガされます.この操作には時間がかかり,アニメーションの速度が遅くなることがあります.この場合, Mayaviスクリプトの高速化 が便利です.