Mayavi Cookbook

These are a collection of useful hints and recipes for various tasks.

Animating a visualization

Often users like to animate a visualization without affecting the interactive capabilities of the view. For example you may want to rotate the camera continuously, take a snapshot while continuing to interact with the Mayavi UI. To do this one can use the very convenient animate() decorator provided with Mayavi. Here is a simple example:

from enthought.mayavi import mlab
@mlab.animate
def anim():
    f = mlab.gcf()
    while 1:
        f.scene.camera.azimuth(10)
        f.scene.render()
        yield

a = anim() # Starts the animation.

Notice the use of yield in the above, this is very crucial to this working. This example will continuously rotate the camera without affecting the UI’s interactivity. It also pops up a little UI that lets you start and stop the animation and change the time interval between calls to your function. For more specialized use you can pass arguments to the decorator:

from enthought.mayavi import mlab
@mlab.animate(delay=500, ui=False)
def anim():
    # ...

a = anim() # Starts the animation without a UI.

Note that if you don’t want to import all of mlab, the animate decorator is available from:

from enthought.mayavi.tools.animator import animate

For more details check the documentation of the animate() decorator available in the MLab reference.

Animating a series of images

Lets say you have a stack of PNG or JPEG files that are numbered serially that you want to animate on a mayavi scene. Here is a simple script (called img_movie.py):

# img_movie.py
from enthought.pyface.timer.api import Timer

def animate(src, N=10):
    for j in range(N):
        for i in range(len(src.file_list)):
            src.timestep = i
            yield

if __name__ == '__main__':
    src = mayavi.engine.scenes[0].children[0]
    animator = animate(src)
    t = Timer(250, animator.next)

The Timer class lets you call a function without blocking the running user interface. The first argument is the time after which the function is to be called again in milliseconds. The animate function is a generator and changes the timestep of the source. This script will animate the stack of images 10 times. The script animates the first data source by default. This may be changed easily.

To use this script do this:

$ mayavi2 -d your_image000.png -m ImageActor -x img_movie.py

Making movies from a stack of images

This isn’t really related to mayavi but is a useful trick nonetheless. Lets say you generate a stack of images using mayavi say of the form anim%03d.png (i.e. anim000.png, anim001.png and so on), you can make this into a movie. If you have mencoder installed try this:

$ mencoder "mf://anim%03d.png" -mf fps=10 -o anim.avi \
  -ovc lavc -lavcopts vcodec=msmpeg4v2:vbitrate=500

If you have ffmpeg installed you may try this:

$ ffmpeg -f image2 -r 10 -i anim%03d.png -sameq anim.mov -pass 2

Scripting from the command line

The mayavi application allows for very powerful Command line arguments that lets you build a complex visualization from your shell. What follow is a bunch of simple examples illustrating these.

The following example creates a ParametricSurface source and then visualizes glyphs on its surface colored red:

$ mayavi2 -d ParametricSurface -m Glyph \
-s"glyph.glyph.scale_factor=0.1" \
-s"glyph.color_mode='no_coloring'" \
-s"actor.property.color = (1,0,0)"

Note that -s"string" applies the string on the last object (also available as last_obj), which is the glyph.

This example turns off coloring of the glyph and changes the glyph to display:

$ mayavi2 -d ParametricSurface -m Glyph\
-s"glyph.glyph.scale_factor=0.1" \
-s"glyph.color_mode='no_coloring'" \
-s"glyph.glyph_source.glyph_source = last_obj.glyph.glyph_source.glyph_list[-1]"

Note the use of last_obj in the above.

Texture mapping actors

Here is a simple example showing how to texture map an iso-surface with the data that ships with the mayavi sources (the data files are in the examples directory):

$ mayavi2 -d examples/tvtk/images/masonry.jpg \
 -d examples/mayavi/data/heart.vti \
 -m IsoSurface \
 -s"actor.mapper.scalar_visibility=False" \
 -s"actor.enable_texture=True"\
 -s"actor.tcoord_generator_mode='cylinder'"\
 -s"actor.texture_source_object=script.engine.current_scene.children[0]"

It should be relatively straightforward to change this example to use a ParametricSurface instead and any other image of your choice. Notice how the texture image (masonry.jpg) is set in the last line of the above. The image reader is the first child of the current scene and we set it as the texture_source_object of the isosurface actor.

Shifting data and plotting

Sometimes you need to shift/transform your input data in space and visualize that in addition to the original data. This is useful when you’d like to do different things to the same data and see them on the same plot. This can be done with Mayavi using the TransformData filter for StructuredGrid, PolyData and UnstructuredGrid datasets. Here is an example using the ParametricSurface data source:

$ mayavi2 -d ParametricSurface \
  -m Outline -m Surface \
  -f TransformData -s "transform.translate(1,1,1)" \
  -s "widget.set_transform(last_obj.transform)" \
  -m Outline -m Surface

If you have an ImageData dataset then you can change the origin, spacing and extents alone by using the ImageChangeInformation filter. Here is a simple example with the standard mayavi image data:

$ mayavi2 -d examples/mayavi/data/heart.vti -m Outline \
-m ImagePlaneWidget \
-f ImageChangeInformation \
-s "filter.origin_translation=(20,20,20)" \
-m Outline -m ImagePlaneWidget

Using the UserDefined filter

The UserDefined filter in mayavi lets you wrap around existing VTK filters easily. Here are a few examples:

$ mayavi2 -d ParametricSurface -s "function='dini'" \
-f UserDefined:GeometryFilter \
-s "filter.extent_clipping=True" \
-s "filter.extent = [-1,1,-1,1,0,5]" \
-f UserDefined:CleanPolyData \
-m Surface \
-s "actor.property.representation = 'p'" \
-s "actor.property.point_size=2"

This one uses a tvtk.GeometryFilter to perform extent based clipping of the parametric surface generated. Note the specification of the -f UserDefined:GeometryFilter. This data is then cleaned using the tvtk.CleanPolyData filter.