1
.. _advanced-scripting-with-mayavi:
3
Advanced Scripting with Mayavi
4
===============================
6
As elaborated in the :ref:`an-overview-of-mayavi` section, mayavi can be
7
scripted from Python in order to visualize data. Mayavi2 was designed
8
from the ground up to be highly scriptable. Everything that can be done
9
from the user interface can be achieved using Python scripts.
11
If you are not looking to script mayavi itself but looking for quick
12
ways to get your visualization done with simple code you may want to
13
check out mayavi's mlab module. This is described in more detail in
14
the :ref:`simple-scripting-with-mlab` section.
16
To best understand how to script mayavi, a reasonable understanding of
17
the mayavi internals is necessary. The following sections provides an
18
overview of the basic design and objects in the mayavi pipeline.
19
Subsequent sections consider specific example scripts that are
20
included with the mayavi sources that illustrate the ideas.
22
Mayavi2 uses Traits_ and TVTK_ internally. Traits_ in many ways
23
changes the way we program. So it is important to have a good idea of
24
Traits in order to understand mayavi's internals. If you are unsure
25
of traits it is a good idea to get a general idea about traits now.
26
Trust me, your efforts learning Traits will not be wasted!
28
.. _Traits: https://svn.enthought.com/enthought/wiki/Traits
29
.. _TVTK: https://svn.enthought.com/enthought/wiki/TVTK
34
This section provides a brief introduction to mayavi's internal
37
The "big picture" of a visualization in mayavi is that an ``Engine``
38
(``enthought.mayavi.engine.Engine``) object manages the entire
39
visualization. The ``Engine`` manages a collection of ``Scene``
40
(``enthought.mayavi.core.scene.Scene``) objects. In each ``Scene``, a
41
user may have created any number of ``Source``
42
(``enthought.mayavi.core.source.Source``) objects. A ``Source``
43
object can further contain any number of ``Filters``
44
(``enthought.mayavi.core.filter.Filter``) or ``ModuleManager``
45
(``enthought.mayavi.core.module_manager.ModuleManager``) objects. A
46
``Filter`` may contain either other filters or ``ModuleManagers``. A
47
``ModuleManager`` manages any number of ``Modules``. The figure below
48
shows this hierarchy in a graphical form.
50
.. image:: images/m2_big_picture.png
51
:alt: Illustration of the various objects in the mayavi pipeline.
53
*Illustration of the various objects in the mayavi pipeline.*
55
This hierarchy is precisely what is seen in the Mayavi tree view on
56
the UI. The UI is therefore merely a graphical representation of this
57
internal world-view. A little more detail on these objects is given
58
below. For even more details please refer to the sources.
60
All objects in the mayavi pipeline feature ``start`` and ``stop``
61
methods. The reasoning for this is that any object in mayavi is not
62
usable (i.e. it may not provide any outputs) unless it has been
63
started. Similarly the ``stop`` method "deactivates" the object.
64
This is done because mayavi is essentially driving VTK objects
65
underneath. These objects require inputs in order to do anything
66
useful. Thus, an object that is not connected to the pipeline cannot
67
be used. For example, consider an ``IsoSurface`` module. It requires
68
some data in order to contour anything. Thus, the module in isolation
69
is completely useless. It is usable only when it is added to the
70
mayavi pipeline. When an object is added to the pipeline, its inputs
71
are setup and its ``start`` method is called automatically. When the
72
object is removed from the pipeline its ``stop`` method is called
75
Apart from the ``Engine`` object, all other objects in the mayavi
76
pipeline feature a ``scene`` trait which refers to the current
77
``enthought.pyface.tvtk.tvtk_scene.TVTKScene`` instance that the
78
object is associated with. The objects also feature an ``add_child``
79
method that lets one build up the pipeline by adding "children"
80
objects. The ``add_child`` method is "intelligent" and will try to
81
appropriately add the child in the right place.
83
Here is a brief description of the key objects in the mayavi pipeline.
86
The Mayavi engine is defined in the ``enthought.mayavi.engine``
89
* It possesses a ``scenes`` trait which is a Trait ``List`` of
92
* Features several methods that let one add a
93
``Filter/Source/Module`` instance to it. It allows one to
94
create new scenes and delete them. Also has methods to load
95
and save the entire visualization.
97
* The ``EnvisageEngine`` defined in the
98
``enthought.mayavi.envisage_engine`` module is a subclass of
99
``Engine`` and is the one used in the ``mayavi2`` application.
100
The ``Engine`` object is not abstract and itself perfectly
101
usable. It is useful when users do not want to use Envisage_
102
but still desire to use mayavi for visualization.
105
Defined in the ``enthought.mayavi.core.scene`` module.
107
* ``scene`` attribute: manages a ``TVTKScene``
108
(``enthought.pyface.tvtk.tvtk_scene``) object which is where
109
all the rendering occurs.
111
* The ``children`` attribute is a ``List`` trait that manages a
112
list of ``Source`` objects.
115
Defined in the ``enthought.mayavi.core.pipeline_base`` module.
116
Derives from ``Base`` which merely abstracts out common
117
functionality. The ``PipelineBase`` is the base class for all
118
objects in the mayavi pipeline except the ``Scene`` and ``Engine``
119
(which really isn't *in* the pipeline but contains the pipeline).
121
* This class is characterized by two events, ``pipeline_changed``
122
and ``data_changed``. These are ``Event`` traits. They
123
determine when the pipeline has been changed and when the data
124
has changed. Therefore, if one does::
126
object.pipeline_changed = True
128
then the ``pipeline_changed`` event is fired. Objects
129
downstream of ``object`` in the pipeline are automatically
130
setup to listen to events from an upstream object and will call
131
their ``update_pipeline`` method. Similarly, if the
132
``data_changed`` event is fired then downstream objects will
133
automatically call their ``update_data`` methods.
135
* The ``outputs`` attribute is a trait ``List`` of outputs
136
produced by the object.
140
Defined in the ``enthought.mayavi.core.source`` module. All the
141
file readers, Parametric surface etc. are subclasses of the
144
* Contains the rest of the pipeline via its ``children`` trait.
145
This is a ``List`` of either ``Modules`` or other ``Filters``.
147
* The ``outputs`` attribute is a trait ``List`` of outputs
148
produced by the source.
151
Defined in the ``enthought.mayavi.core.filter`` module. All the
152
``Filters`` described in the :ref:`filters` section are subclasses of
155
* Contains the rest of the pipeline via its ``children`` trait.
156
This is a ``List`` of either ``Modules`` or other ``Filters``.
158
* The ``inputs`` attribute is a trait ``List`` of input data
159
objects that feed into the filter.
161
* The ``outputs`` attribute is a trait ``List`` of outputs
162
produced by the filter.
164
* Also features the three methods:
166
- ``setup_pipeline``: used to create the underlying
167
TVTK pipeline objects if needed.
169
- ``update_pipeline``: a method that is called when the
170
upstream pipeline has been changed, i.e. an upstream object
171
fires a ``pipeline_changed`` event.
173
- ``update_data``: a method that is called when the upstream
174
pipeline has **not** been changed but the data in the
175
pipeline has been changed. This happens when the upstream
176
object fires a ``data_changed`` event.
179
Defined in the ``enthought.mayavi.core.module_manager`` module.
180
This object is the one called *Modules* in the tree view on the
181
UI. The main purpose of this object is to manage ``Modules`` and
182
share common data between them. All modules typically will use
183
the same lookup table (LUT) in order to produce a meaningful
184
visualization. This lookup table is managed by the module
187
* The ``source`` attribute is the ``Source`` or ``Filter`` object
188
that is the input of this object.
190
* Contains a list of ``Modules`` in its ``children`` trait.
192
* The ``scalar_lut_manager`` attribute is an instance of a
193
``LUTManager`` which basically manages the color mapping from
194
scalar values to colors on the visualizations. This is
195
basically a mapping from scalars to colors.
197
* The ``vector_lut_manager`` attribute is an instance of a
198
``LUTManager`` which basically manages the color mapping from
199
vector values to colors on the visualizations.
201
* The class also features a ``lut_data_mode`` attribute that
202
specifies the data type to use for the LUTs. This can be
203
changed between 'auto', 'point data' and 'cell data'. Changing
204
this setting will change the data range and name of the lookup
205
table/legend bar. If set to 'auto' (the default), it
206
automatically looks for cell and point data with point data
207
being preferred over cell data and chooses the one available.
208
If set to 'point data' it uses the input point data for the LUT
209
and if set to 'cell data' it uses the input cell data.
212
Defined in the ``enthought.mayavi.core.module`` module.
213
These objects are the ones that typically produce a visualization
214
on the TVTK scene. All the modules defined in the :ref:`modules`
215
section are subclasses of this.
217
* The ``components`` attribute is a trait ``List`` of various
218
reusable components that are used by the module. These usually
219
are never used directly by the user. However, they are
220
extremely useful when creating new modules. A ``Component`` is
221
basically a reusable piece of code that is used by various
222
other objects. For example, almost every ``Module`` uses a
223
TVTK actor, mapper and property. These are all "componentized"
224
into a reusable `Actor` component that the modules use. Thus,
225
components are a means to promote reuse between mayavi pipeline
228
* The ``module_manager`` attribute specifies the
229
``ModuleManager`` instance that it is attached to.
231
* Like the ``Filter`` modules also feature the three methods:
233
- ``setup_pipeline``: used to create the underlying
234
TVTK pipeline objects if needed.
236
- ``update_pipeline``: a method that is called when the
237
upstream pipeline has been changed, i.e. an upstream object
238
fires a ``pipeline_changed`` event.
240
- ``update_data``: a method that is called when the upstream
241
pipeline has **not** been changed but the data in the
242
pipeline has been changed. This happens when the upstream
243
object fires a ``data_changed`` event.
245
The following figures show the class hierarchy of the various objects
249
.. image:: images/design2c.png
250
:alt: The ``Engine`` object.
252
*The ``Engine`` object and its important attributes and methods.*
254
.. image:: images/design2a.png
255
:alt: Basic object hierarchy
257
*This hierarchy depicts the ``Base`` object, the ``Scene``,
258
``PipelineBase`` and the ``ModuleManager``.*
260
.. image:: images/design2b.png
261
:alt: More object hierarchy
263
*This hierarchy depicts the ``PipelineBase`` object, the ``Source``,
264
``Filter``, ``Module`` and the ``Component``.*
267
Scripting the ``mayavi2`` application
268
-------------------------------------
270
The ``mayavi2`` application is implemented in the
271
``enthought.mayavi.scripts.mayavi2`` module (look at the
272
``mayavi2.py`` file and not the ``mayavi2`` script). This code
273
handles the command line argument parsing and runs the application.
275
``mayavi2`` is an Envisage_ application. It starts the Envisage
276
application in its ``main`` method. The code for this is in the
277
``enthought.mayavi.app`` module. Mayavi uses several envisage plugins
278
to build up its functionality. These plugins are defined in the
279
``enthought.mayavi.plugin_definitions`` module. In this module there
280
are two lists of plugins defined, ``PLUGIN_DEFINITIONS`` and the
281
``NONGUI_PLUGIN_DEFINITIONS``. The default application uses the
282
former which produces a GUI that the user can use. If one uses the
283
latter (``NONGUI_PLUGIN_DEFINITIONS``) then the mayavi tree view,
284
object editor and menu items will not be available when the
285
application is run. This allows a developer to create an application
286
that uses mayavi but does not show its user interface. An example of
287
how this may be done is provided in ``examples/nongui.py``.
289
.. _envisage: https://svn.enthought.com/enthought/wiki/Envisage
292
Scripting from the UI
293
~~~~~~~~~~~~~~~~~~~~~
295
When using the ``mayavi2`` application, it is possible to script from
296
the embedded Python interpreter on the UI. On the interpreter the
297
name ``mayavi`` is automatically bound to an
298
``enthought.mayavi.script.Script`` instance that may be used to easily
299
script mayavi. This instance is a simple wrapper object that merely
300
provides some nice conveniences while scripting from the UI. It has
301
an ``engine`` trait that is a reference to the running mayavi engine.
303
As described in :ref:`the-embedded-python-interpreter` section, one can
304
always drag a mayavi object from the tree and drop it on the
305
interpreter to script it directly.
307
One may select the `File->Open File...` menu to open an existing
308
Python file in the text editor, or choose the `File->New File` menu to
309
create a new file. The text editor is Python-aware and one may write
310
a script assuming that the ``mayavi`` name is bound to the ``Script``
311
instance as it is on the shell. To execute this script one can press
312
``Control-r`` as described earlier. ``Control-s`` will save the
315
The nice thing about this kind of scripting is that if one scripts
316
something on the interpreter or on the editor, one may save the
317
contents to a file, say ``script.py`` and then the next time mayavi
320
$ mayavi2 -x script.py
322
This will execute the script for automatically. The name ``mayavi``
323
is available to the script and is bound to the ``Script`` instance.
324
This is very convenient. It is possible to have mayavi execute
325
multiple scripts. For example::
327
$ mayavi2 -d foo.vtk -m IsoSurface -x setup_iso.py -x script2.py
329
will load the ``foo.vtk`` file, create an ``IsoSurface`` module, then
330
run ``setup_iso.py`` and then run ``script2.py``.
332
There are several scripts in the mayavi ``examples`` directory that
333
should show how this can be done. The ``examples/README.txt``
334
contains some information on the recommended ways to script.
337
Scripting from IPython
338
~~~~~~~~~~~~~~~~~~~~~~
340
It is possible to script Mayavi using IPython_. IPython will have to
341
be invoked with the ``-wthread`` command line option in order to allow
342
one to interactively script the mayavi application::
346
To start a visualization do the following::
348
from enthought.mayavi.app import main
349
# Note, this does not process any command line arguments.
351
# 'mayavi' is the mayavi Script instance.
353
It is also possible to use mlab (see :ref:`simple-scripting-with-mlab`) for
356
from enthought.mayavi.tools import mlab
357
f = mlab.figure() # Returns the current scene.
358
mayavi = mlab.get_mayavi() # Returns the Script instance.
360
With this it should be possible to script mayavi just the way it is
361
done on the embedded interpreter or on the text editor.
363
.. _IPython: http://ipython.scipy.org
368
Here is an example script that illustrates various features of
371
# Create a new mayavi scene.
374
# Get the current active scene.
375
s = mayavi.engine.current_scene
378
from enthought.mayavi.sources.api import VTKXMLFileReader
379
d = VTKXMLFileReader()
380
# You must specify the full path to the data here.
381
d.initialize('fire_ug.vtu')
384
# Import a few modules.
385
from enthought.mayavi.modules.api import Outline, IsoSurface, Streamline
390
o.actor.property.color = 1, 0, 0 # red color.
392
# Make a few contours.
394
mayavi.add_module(iso)
395
iso.contour.contours = [450, 570]
396
# Make them translucent.
397
iso.actor.property.opacity = 0.4
398
# Show the colormapping.
399
iso.module_manager.scalar_lut_manager.show_scalar_bar = True
403
mayavi.add_module(st)
404
# Position the seed center.
405
st.seed.widget.center = 3.5, 0.625, 1.25
406
st.streamline_type = 'tube'
408
# Save the resulting image.
409
s.scene.save('test.png')
413
# Rotate the camera by 10 degrees.
414
s.scene.camera.azimuth(10)
416
# Resets the camera clipping plane so everything fits and then
421
s.scene.save_png('anim%d.png'%i)
423
Sometimes, given a mayavi ``Script`` instance or ``Engine``, it is
424
handy to be able to navigate to a particular module/object. In the
425
above this could be achieved as follows::
427
x = mayavi.engine.scenes[0].children[0].children[0].children[-1]
430
In this case ``x`` will be set to the ``Streamline`` instance that we
433
There are plenty of examples illustrating various things in the
434
``examples`` directory. These are all fairly well documented.
436
In particular, the ``standalone.py`` example illustrates how one can
437
script mayavi without using the envisage application at all. The
438
``offscreen.py`` example illustrates how this may be done using off
439
screen rendering (if supported by your particular build of VTK).
441
``examples/README.txt`` contains some information on the recommended
442
ways to script and some additional information.
446
Using the mayavi envisage plugins
447
---------------------------------
449
The mayavi related plugin definitions to use are:
451
* ``mayavi_plugin_definition.py``
452
* ``mayavi_ui_plugin_definition.py``
454
These are in the ``enthought.mayavi`` package. To see an example of
455
how to use this see the ``enthought.mayavi.plugin_definitions``
456
module and the ``enthought.mayavi.app`` module.
458
If you are writing Envisage plugins for an application and desire to
459
use the mayavi plugins from your plugins/applications then it is
460
important to note that mayavi creates three application objects for
461
your convenience. These are:
463
* ``enthought.mayavi.services.IMAYAVI``: This is an
464
``enthought.mayavi.script.Script`` instance that may be used to
465
easily script mayavi. It is a simple wrapper object that merely
466
provides some nice conveniences while scripting from the UI. It
467
has an ``engine`` trait that is a reference to the running mayavi
470
* ``enthought.mayavi.services.IMAYAVI_ENGINE``: This is the running
471
mayavi engine instance.
473
* ``enthought.mayavi.services.IMAYAVI_ENGINE_VIEW``: This is the
474
view of the engine and is only exposed if the
475
``mayavi_ui_plugin_definition.py`` is used.
477
A simple example that demonstrates the use of the mayavi plugin in an
478
envisage application is included in the ``examples/explorer``
479
directory. This may be studied to understand how you may do the same
480
in your envisage applications.
487
indent-tabs-mode: nil
488
sentence-end-double-space: t