Mlab - Python Scripting For 3D Plotting - Mayavi 4.5.0 Documentation PDF
Mlab - Python Scripting For 3D Plotting - Mayavi 4.5.0 Documentation PDF
Sec on summary
This sec on describes the mlab API, for use of Mayavi as a simple plo ng in scripts or interac ve sessions. This is the main entry point for people
interested in doing 3D plo ng à la Matlab or IDL in Python. If you are interested in a list of all the func ons exposed in mlab, see the MLab reference.
The mayavi.mlab module, that we call mlab, provides an easy way to visualize data in a script or from an interac ve prompt with one-liners as done in the
matplotlib pylab interface but with an emphasis on 3D visualiza on using Mayavi2. This allows users to perform quick 3D visualiza on while being able to
use Mayavi’s powerful features.
Mayavi’s mlab is designed to be used in a manner well-suited to scrip ng and does not present a fully object-oriented API. It is can be used interac vely
with IPython.
Warning: When using IPython with mlab, as in the following examples, IPython must be invoked with the --gui=qt command line op on like this:
$ ipython --gui=qt
On recent versions of IPython, this can be turned on from within IPython itself by:
In []: %gui qt
This is the result of incompa ble setups between PyQt and PySide. The solu on is to run QT_API=pyqt ETS_TOOLKIT=qt4 ipython . More details can be
found at the ipython documenta on page.
If for some reason Mayavi fails with the Qt backend, you can also try using the wxPython backend by doing:
$ ETS_TOOLKIT=wx
$ ipython --gui=wx
For more details on using mlab and running scripts, read the sec on Running mlab scripts
In this sec on, we first introduce simple plo ng func ons, to create 3D objects as representa ons of numpy arrays. Then we explain how proper es such
as color or glyph size can be modified or used to represent data, we show how the visualiza on created through mlab can be modified interac vely with
dialogs, we show how scripts and anima ons can be ran. Finally, we expose a more advanced use of mlab in which full visualiza on pipeline are built in
scripts, and we give some detailed examples of applying these tools to visualizing volumetric scalar and vector data.
Sec on contents
A demo
3D Plo ng func ons for numpy arrays
Changing the looks of the visual objects created
Figures, legends, camera and decora ons
Running mlab scripts
Anima ng the data
Assembling pipelines with mlab
Case studies of some visualiza ons
A demo
To get you started, here is a pre y example showing a spherical harmonic as a surface:
# View it.
from mayavi import mlab
s = mlab.mesh(x, y, z)
mlab.show()
Bulk of the code in the above example is to create the data. One line suffices to visualize it. This produces the following visualiza on:
The visualiza on is created by the single func on mesh() in the above.
Several examples of this kind are provided with mlab (see test_contour3d, test_points3d, test_plot3d_anim etc.). The above demo is available as
test_mesh. Under IPython these may be found by tab comple ng on mlab.test. You can also inspect the source in IPython via the handy
mlab.test_contour3d??.
The mlab plo ng func ons take numpy arrays as input, describing the x , y , and z coordinates of the data. They build full-blown visualiza ons: they create
the data source, filters if necessary, and add the visualiza on modules. Their behavior, and thus the visualiza on created, can be fine-tuned through
keyword arguments, similarly to pylab. In addi on, they all return the visualiza on module created, thus visualiza on can also be modified by changing the
a ributes of this module.
Note: In this sec on, we only list the different func ons. Each func on is described in detail in the MLab reference, at the end of the user guide, with
figures and examples. Please follow the links.
0D and 1D data
points3d()
Plots glyphs (like points) at the posi on of the supplied data, described by x , y , z numpy arrays of the same
shape.
plot3d()
Plots line between the supplied data, described by x , y , z 1D numpy arrays of the same length.
2D data
imshow()
View a 2D array as an image.
surf()
View a 2D array as a carpet plot, with the z axis representa on through eleva on the value of the array points.
contour_surf()
View a 2D array as line contours, elevated according to the value of the array points.
mesh()
Plot a surface described by three 2D arrays, x , y , z giving the coordinates of the data points as a grid.
Unlike surf() , the surface is defined by its x , y and z coordinates with no privileged direc on. More complex
surfaces can be created.
barchart()
Plot an array s , or a set of points with explicit coordinates arrays, x , y and z , as a bar chart, eg for histograms.
This func on is very versa le and will accept 2D or 3D arrays, but also clouds of points, to posi on the bars.
triangular_mesh()
Plot a triangular mesh, fully specified by x , y and z coordinates of its ver ces, and the (n, 3) array of the indices of
the triangles.
surf() and contour_surf() can be used as 3D representa on of 2D data. By default the z-axis is supposed to be in the same units as the x and y axis, but
it can be auto-scaled to give a 2/3 aspect ra o. This behavior can be controlled by specifying the “warp_scale=’auto’”.
Knowing the posi ons of data points is not enough to define a surface, connec vity informa on is also required. With the func ons surf() and mesh() ,
this connec vity informa on is implicitly extracted from the shape of the input arrays: neighboring data points in the 2D input arrays are connected, and
the data lies on a grid. With the func on triangular_mesh() , connec vity is explicitly specified. Quite o en, the connec vity is not regular, but is not
known in advance either. The data points lie on a surface, and we want to plot the surface implicitly defined. The delaunay2d filter does the required
nearest-neighbor matching, and interpola on, as shown in the (Surface from irregular data example).
3D data
contour3d()
Plot iso-surfaces of volumetric data defined as a 3D array.
quiver3d()
Plot arrows to represent vectors at data points. The x , y , z posi on are specified by numpy arrays, as well as the u , v ,
w components of the vectors.
flow()
Plot a trajectory of par cles along a vector field described by three 3D arrays giving the u , v , w components on a grid.
contour3d() and flow() require ordered data (to be able to interpolate between the points), whereas quiver3d() works with any set of points. The
required structure is detailed in the func ons’ documenta on.
Note: Many richer visualiza ons can be created by assembling data sources filters and modules. See the Assembling pipelines with mlab and the Case
studies of some visualiza ons sec ons.
The easiest way to choose the colormap, most adapted to your visualiza on is to use the GUI (as described in the next paragraph). The dialog to
set the colormap can be found in the Colors and legends node.
To use a custom-defined colormap, for the me being, you need to write specific code, as show in Custom colormap example.
Size of the glyph:
The scalar informa on can also be displayed in many different ways. For instance it can be used to adjust the size of glyphs posi oned at the data
points.
A caveat: Clamping: rela ve or absolute scaling Given six points posi onned on a line with interpoint spacing 1:
x = [1, 2, 3, 4, 5, 6]
y = [0, 0, 0, 0, 0, 0]
z = y
We represent the dataset as spheres, using points3d() , and the scalar is mapped to diameter of the spheres:
By default the diameter of the spheres is not ‘clamped’, in other words, the smallest value of the scalar data is represented as a null diameter,
and the largest is propor onal to inter-point distance. The scaling is only rela ve, as can be seen on the resul ng figure:
This behavior gives visible points for all datasets, but may not be desired if the scalar represents the size of the glyphs in the same unit as the
posi ons specified.
In this case, you shoud turn auto-scaling off by specifying the desired scale factor:
Warning: In earlier versions of Mayavi (up to 3.1.0 included), the glyphs are not auto-scaled, and as a result the visualiza on can seem empty
due to the glyphs being very small. In addi on the minimum diameter of the glyphs is clamped to zero, and thus the glyph are not scaled
absolutely, unless you specify:
pts.glyph.glyph.clamping = False
x, y, z, s, c = np.random.random((5, 10))
pts = mlab.quiver3d(x, y, z, s, s, s, scalars=c, mode='sphere')
pts.glyph.color_mode = 'color_by_scalar'
# Finally, center the glyphs on the data point
pts.glyph.glyph_source.glyph_source.center = [0, 0, 0]
The surf() , contour_surf() , and barchart() func ons, which display 2D arrays by conver ng the values in height, also take a warp_scale parameter, to
control the ver cal scaling.
The Mayavi pipeline tree can be displayed by clicking on the mayavi icon in the figure’s toolbar, or by using show_pipeline() mlab command. One can now
change the visualiza on using this dialog by double-clicking on each object to edit its proper es, as described in other parts of this manual, or add new
modules or filters by using this icons on the pipeline, or through the right-click menus on the objects in the pipeline.
A very useful feature of this dialog can be found by pressing the red round bu on of the toolbar of the pipeline view. This opens up a recorder that
tracks the changes made interac vely to the visualiza on via the dialogs, and generates valid lines of Python code. To find out about naviga ng through
a program in the pipeline, see Organisa on of Mayavi visualiza ons: the pipeline.
In addi on, for every object returned by a mlab func on, this_object.edit_traits() brings up a dialog that can be used to interac vely edit the object’s
proper es. If the dialog doesn’t show up when you enter this command, please see Running mlab scripts.
Some mes it is convenient to write an mlab script but s ll use the full envisage applica on so you can click on the menus and use other modules etc. To
do this you may do the following before you create an mlab figure:
This will give you the full-fledged UI instead of the default simple window.
Figures, legends, camera and decorations
Figure decorations
Axes can be added around a visualiza on object with the axes() func on, and the labels can be set using the xlabel() , ylabel() and zlabel() func ons.
Similarly, outline() creates an outline around an object. title() adds a tle to the figure.
Color bars can be used to reflect the color maps used to display values (LUT, or lookup tables, in VTK parlance). colorbar() creates a color bar for the last
object created, trying to guess whether to use the vector data or the scalar data color maps. The scalarbar() and vectorbar() func on scan be used to
create color bars specifically for scalar or vector data.
Warning: The orientation_axes() was named orienta onaxes before release 3.2.
The view() and roll() func ons return the current values of the different angles and distances they take as arguments. As a result, the view point obtained
interac vely can be stored and reset using:
You can also rotate the camera around itself using the roll, yaw and pitch methods of the camera object. This moves the focal point:
f = mlab.gcf()
camera = f.scene.camera
camera.yaw(45)
Unlike the view() and roll() func on, the angles are incremental, and not absolute.
The camera is en rely defined by its posi on, its focal point, and its view angle (a ributes ‘posi on’, ‘focal_point’, ‘view_angle’). The camera method
‘zoom’ changes the view angle incrementally by the specify ra o, where as the method ‘dolly’ translates the camera along its axis while keeping the focal
point constant. The move() func on can also be useful in these regards.
In addi on to the informa on returned and set by mlab.view and mlab.roll, a last parameter is needed to fully define the view point: the parallel scale of
the camera, that control its view angle. It can be read (or set) with the following code:
f = mlab.gcf()
camera = f.scene.camera
cam.parallel_scale = 9
You need to start IPython with the –gui=qt op on. In this environment, the plo ng commands are interac ve: they have an immediate effect on the
figure, allevia ng the need to use the show() func on.
Mlab can also be used interac vely in the Python shell of the mayavi2 applica on, or in any interac ve Python shell of wxPython-based applica on (such
as other Envisage-based applica ons, or SPE, Stani’s Python Editor).
$ ipython --matplotlib=qt
$ ipython --gui=qt
and before impor ng any matplotlib modules, enter the following Python commands:
$ ipython --pylab=qt
If you want matplotlib and mlab to work together by default in IPython, you can change you default matplotlib backend, by edi ng the
~/.matplotlib/matplotlibrc to add the following line:
backend : Qt4Agg
If for some reason, the Qt backend does not work, you can use the wx backend. To do this you may do:
$ ETS_TOOLKIT=wx
$ ipython --gui=wx
Note that as far as Mayavi is concerned, it chooses the appropriate toolkit using the ETS_TOOLKIT environment variable. If this is not set, the supported
toolkits are tried in a version-dependent order un l one succeeds. With recent releases of traitsui, the default is Qt. The possible op ons for ETS_TOOLKIT
are:
Star ng from Mayavi version 3.4.0, the mlab screenshot() can be used to take a screenshot of the current figure, to integrate in a matplotlib plot.
In scripts
Mlab commands can be wri en to a file, to form a script. This script can be loaded in the Mayavi applica on using the File->Open file menu entry, and
executed using the File->Refresh code menu entry or by pressing Control-r . It can also be executed during the start of the Mayavi applica on using the -x
command line switch.
As men oned above, when running outside of an interac ve environment, for instance with python myscript.py, you need to call the show() func on (as
shown in the demo above) to pause your script and have the user interact with the figure.
You can also use show() to decorate a func on, and have it run in the event-loop, which gives you more flexibility:
@mlab.show
def image():
mlab.imshow(random.random((10, 10)))
With this decorator, each me the image func on is called, mlab makes sure an interac ve environment is running before execu ng the image func on. If
an interac ve environment is not running, mlab will start one and the image func on will not return un l it is closed.
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 a ribute 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.
If mul ple 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:
# View it.
l = plot3d(x, y, z, np.sin(mu), tube_radius=0.025, colormap='Spectral')
No ce the use of the set method above. With this method, the visualiza on 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 anima ng data are provided with mlab. Try the examples with the name mlab.test_<name>_anim, i.e. where the name ends
with an _anim to see how these work and run.
Note: It is important to remember dis nc on between set and reset. Use set or directly set the a ributes (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 se ng the traits.
Warning: When crea ng a Mayavi pipeline, as explained in the following subsec on, instead of using ready-made plo ng func on, the mlab_source
a ribute is created only on sources created via mlab. Pipeline created en rely using mlab will present this a ribute.
Note: If you are anima ng several plot objects, each me you modify the data with there mlab_source a ribute, Mayavi will trigger a refresh of the
scene. This opera on might take me, and thus slow your anima on. In this case, the p Accelera ng a Mayavi script may come in handy.
Mlab provides a sub-module pipeline which contains func ons to populate the pipeline easily from scripts. This module is accessible in mlab:
mlab.pipeline, or can be imported from mayavi.tools.pipeline.
When using an mlab plo ng func on, a pipeline is created: first a source is created from numpy arrays, then modules, and possibly filters, are added. The
resul ng pipeline can be seen for instance with the mlab.show_pipeline command. This informa on can be used to create the very same pipeline directly
using the pipeline scrip ng module, as the names of the func ons required to create each step of the pipeline are directly linked to the default names of
the objects created by mlab on the pipeline. As an example, let us create a visualiza on using surf() :
import numpy as np
a = np.random.random((4, 4))
from mayavi import mlab
mlab.surf(a)
mlab.show_pipeline()
Array2DSource
\__ WarpScalar
\__ PolyDataNormals
\__ Colors and legends
\__ Surface
src = mlab.pipeline.array2d_source(a)
warp = mlab.pipeline.warp_scalar(src)
normals = mlab.pipeline.poly_data_normals(warp)
surf = mlab.pipeline.surface(normals)
Data sources
The mlab.pipeline module contains func ons for crea ng various data sources from arrays. They are fully documented in details in the Mlab pipeline-
control reference. We give a small summary of the possibili es here.
Mayavi dis nguishes sources with scalar data, and sources with vector data, but more important, it has different func ons to create sets of unconnected
points, with data a ached to them, or connected data points describing con nuously varying quan es that can be interpolated between data points,
o en called fields in physics or engineering.
Unconnected sources:
vector_scatter() (creates an
scalar_scatter() (creates a
PolyData)
PolyData)
implicitly-connected sources:
scalar_field() (creates an
ImageData)
array2d_source() (creates an
ImageData)
vector_field() (creates an
ImageData)
Explicitly-connected sources:
line_source() (creates an triangular_mesh_source() (creates an
PolyData) PolyData)
All the mlab.pipline source factories are func ons that take numpy arrays and return the Mayavi source object that was added to the pipeline. However,
the implicitly-connected sources require well-shaped arrays as arguments: the data is supposed to lie on a regular, orthogonal, grid of the same shape as
the shape of the input array, in other words, the array describes an image, possibly 3 dimensional.
Note: More complicated data structures can be created, such as irregular grids or non-orthogonal grid. See the sec on on data structures.
In general, the mlab.pipeline module and filter factory func ons simply create and connect the corresponding object. However they can also contain
addi on logic, exposed as keyword arguments. For instance they allow to set up easily a colormap, or to specify the color of the module, when relevant. In
accordance with the goal of the mlab interface to make frequent opera ons simple, they use the keyword arguments to choose the proper es of the
created object to suit the requirements. It can be thus easier to use the keyword arguments, when available, than to set the a ributes of the objects
created. For more informa on, please check out the docstrings. Full, detailed, usage examples are given in the next subsec on.
import numpy as np
x, y, z = np.ogrid[-10:10:20j, -10:10:20j, -10:10:20j]
s = np.sin(x*y*z)/(x*y*z)
Iso- To display iso surfaces of the field, the simplest solu on is simply to use the mlab contour3d() func on:
Surfaces:
mlab.contour3d(s)
The problem with this method is that the outer iso-surfaces tend to hide inner ones. As a result, quite o en only one iso-surface can be
visible.
Volume rendering:
Volume rendering is an advanced technique in which each voxel is given a partly transparent color. This can be achieved with mlab.pipeline
using the scalar_field() source, and the volume module:
mlab.pipeline.volume(mlab.pipeline.scalar_field(s))
For such a visualiza on, tweaking the opacity transfer func on is cri cal to achieve a good effect. Typically, it can be useful to limit the lower
and upper values to the 20 and 80 percen les of the data, in order to have a reasonable frac on of the volume transparent:
It is useful to open the module’s dialog (eg through the pipeline interface, or using it’s edit_traits() method) and tweak the color transfer
func on to render the transparent low-intensity regions of the image. For this module, the LUT as defined in the `Colors and legends` node
are not used
The limita ons of volume rendering is that, while it is o en very pre y, it can be difficult to analyze the details of the field with it.
Cut While less impressive, cut planes are a very informa ve way of visualizing the details of a scalar field:
planes:
mlab.pipeline.image_plane_widget(mlab.pipeline.scalar_field(s),
plane_orientation='x_axes',
slice_index=10,
)
mlab.pipeline.image_plane_widget(mlab.pipeline.scalar_field(s),
plane_orientation='y_axes',
slice_index=10,
)
mlab.outline()
The image plane widget can only be used on regular-spaced data, as created by mlab.pipeline.scalar_field, but it is very fast. It should thus be
prefered to the scalar cut plane, when possible.
Clicking and dragging the cut plane is an excellent way of exploring the field.
A combina on of techniques:
Finally, it can be interes ng to combine cut planes with iso-surfaces and thresholding to give a view of the peak areas using the iso-surfaces,
visualize the details of the field with the cut plane, and the global mass with a large iso-surface:
src = mlab.pipeline.scalar_field(s)
mlab.pipeline.iso_surface(src, contours=[s.min()+0.1*s.ptp(), ], opacity=0.1)
mlab.pipeline.iso_surface(src, contours=[s.max()-0.1*s.ptp(), ],)
mlab.pipeline.image_plane_widget(src,
plane_orientation='z_axes',
slice_index=10,
)
In some cases, though not in our example, it might be usable to insert a threshold filter before the cut plane, eg:to remove area with values
below ‘s.min()+0.1*s.ptp()’. In this case, the cut plane needs to be implemented with mlab.pipeline.scalar_cut_plane as the data looses its
structure a er thresholding.
import numpy as np
x, y, z = np.mgrid[0:1:20j, 0:1:20j, 0:1:20j]
u = np.sin(np.pi*x) * np.cos(np.pi*z)
v = -2*np.sin(np.pi*y) * np.cos(2*np.pi*z)
w = np.cos(np.pi*x)*np.sin(np.pi*z) + np.cos(np.pi*y)*np.sin(2*np.pi*z)
Quiver: The simplest visualiza on of a set of vectors, is using the mlab func on quiver3d:
mlab.quiver3d(u, v, w)
mlab.outline()
The main limita on of this visualiza on is that it posi ons an arrow for each sampling point on the grid. As a result the visualiza on is very
busy.
Masking vectors:
We can use the fact that we are visualizing a vector field, and not just a bunch of vectors, to reduce the amount of arrows displayed. For this we
need to build a vector_field source, and apply to it the vectors module, with some masking parameters (here we keep only one point out of 20):
src = mlab.pipeline.vector_field(u, v, w)
mlab.pipeline.vectors(src, mask_points=20, scale_factor=3.)
A cut If we are interested in displaying the vectors along a cut, we can use a cut plane. In par cular, we can inspect interac vely the vector field by
plane: moving the cut plane along: clicking on it and dragging it can give a very clear understanding of the vector field:
magnitude = mlab.pipeline.extract_vector_norm(src)
mlab.pipeline.iso_surface(magnitude, contours=[1.9, 0.5])
The Flow, or the field lines:
For certain vector fields, the line of flow along the field can have an interes ng meaning. For instance this can be interpreted as a trajectory in
hydrodynamics, or field lines in electro-magne sm. We can display the flow lines origina ng for a certain seed surface using the streamline
module, or the mlab flow() func on, which relies on streamline internally:
A combina on of techniques:
Giving a meaningful visualiza on of a vector field is a hard task, and one must use all the tools at hand to illustrate his purposes. It is important
to choose the message conveyed. No one visualiza on will tell all about a vector field. Here is an example of a visualiza on made by combining
the different tools above:
Moreover, the mlab func ons expose only a small frac on of the possibili es of the visualiza on objects. The dialogs expose more of these
func onali es, that are en rely controlled by the a ributes of the objects returned by the mlab func ons. These objects are very rich, as they are built
from VTK objects. It can be hard to find the right a ribute to modify when exploring them, or in the VTK documenta on, thus the easiest way is to
modify them interac vely using the pipeline view dialog and use the record feature to find out the corresponding lines of code. See Organisa on of
Mayavi visualiza ons: the pipeline to understand be er the link between the lines of code generated by the record feature and mlab. .
[1] Toussaint, V.; Carriere, P. & Raynal, F. A numerical Eulerian approach to mixing by chao c advec on Phys. Fluids, 1995, 7, 2587