.. _mlab-animating-data: Animating the data ------------------ Often it isn't sufficient to just plot the data. You may also want to change the data of the plot and update the plot without having to recreate the entire visualization, for instance to do animations, or in an interactive application. Indeed, recreating the entire visualization is very inefficient and leads to very jerky looking animations. To do this, mlab provides a very convenient way to change the data of an existing mlab visualization. Consider a very simple example. The `mlab.test_simple_surf_anim` function has this code:: 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') The first two lines define a simple plane and view that. The next three lines animate that data by changing the scalars producing a plane that rotates about the origin. The key here is that the `s` object above has a special attribute called `mlab_source`. This sub-object allows us to manipulate the points and scalars. If we wanted to change the `x` values we could set that too by:: s.mlab_source.x = new_x The only thing to keep in mind here is that the shape of `x` should not be changed. Note that many of the examples discussed here may not appear to be animated at all and you may just see the final state of the animation. If you save a screenshot of the image at each stage of the animation, you would get the correct result. However, you will not get the visual effect on screen. See the section :ref:`animating_a_visualization` to learn more on the use of the `@animate` decorator (:func:`mayavi.mlab.animate`) to achieve this. We show a small example here, where we rewrite the above to animate nicely:: 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() In the above, note that we wrap the iteration in a function which is a generator and decorate it with the `@mlab.animate` decorator. If multiple values have to be changed, you can use the `set` method of the `mlab_source` to set them as shown in the more complicated example below:: # 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) Notice the use of the `set` method above. With this method, the visualization is recomputed only once. In this case, the shape of the new arrays has not changed, only their values have. If the shape of the array changes then one should use the `reset` method as shown below:: 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() Many standard examples for animating data are provided with mlab. Try the examples with the name `mlab.test__anim`, i.e. where the name ends with an `_anim` to see how these work and run. .. note:: It is important to remember distinction between `set` and `reset`. Use `set` or directly set the attributes (`x`, `y`, `scalars` etc.) when you are not changing the shape of the data but only the values. Use `reset` when the arrays are changing shape and size. Reset usually regenerates all the data and can be inefficient when compared to `set` or directly setting the traits. .. warning:: When creating a Mayavi pipeline, as explained in the following subsection, instead of using ready-made plotting function, the `mlab_source` attribute is created only on sources created via `mlab`. Pipeline created entirely using `mlab` will present this attribute. .. note:: If you are animating several plot objects, each time you modify the data with there `mlab_source` attribute, Mayavi will trigger a refresh of the scene. This operation might take time, and thus slow your animation. In this case, the tip :ref:`acceleration_mayavi_scripts` may come in handy. .. Local Variables: mode: rst indent-tabs-mode: nil sentence-end-double-space: t fill-column: 70 End: