2
Building applications using Mayavi
3
===================================
5
.. topic:: Section summary
7
This section describes how Mayavi can be used as a scientific data
8
visualization and 3D plotting tool in interactive application.
10
Mayavi can be used as a fully integrated and interactive 3D plotting tool
11
in a GUI application. Using the event model behind Traits and TVTK, all
12
the different properties of a visualization can be changed dynamically,
13
including the data visualized itself.
15
In this section, we first show how an interactive dialog embedding a
16
Mayavi scene can be built, using `Traits`. Then we show how to integrate
17
this dialog in a WxPython or a PyQt application.
19
Custom interactive dialogs
20
--------------------------
22
Mayavi and TVTK are entirely built using the Traits library which provide
23
easy callbacks and visualization for objects attribute. All the different
24
properties of the pipeline and pipeline objects are expressed as Traits,
25
ie special attributes that can be visualized in dialogs, and that fire
26
callbacks when they are modified. In particuler this means that when a
27
visualization object is modified, the scene can update automatically.
29
We strongly suggest that you refer to the `Traits`
30
`documentation <http://code.enthought.com/projects/traits.documentation.php>`_
31
for more details, and to the
32
`tutorial <http://code.enthought.com/projects/traits/docs/html/tutorials/traits_ui_scientific_app.html>`_
33
for a quick introduction.
35
Embedding a Mayavi scene in a Traits dialog
36
............................................
38
To build a custom dialog with a Mayavi scene, the best option is to
39
create a class deriving from the base `Traits` class. A special
40
attribute, called SceneModel can be used as an attribute to represent a
41
Mayavi scene that can accept objects. This defines the `model`, ie the
42
main `HasTraits` object in which the application logics is contained.
44
A view of this object, as a dialog, can be created using the
45
`.configure_traits` method of this object. If a view is explicitely
46
specified the embedded Mayavi scene can be represented with the usual
47
widget for scene by specifying for it the `SceneEditor`::
49
from enthought.traits.api import HasTraits, Instance
50
from enthought.traits.ui.api import View, Item
51
from enthought.tvtk.pyface.scene_model import SceneModel
52
from enthought.tvtk.pyface.scene_editor import SceneEditor
54
class MyModel(HasTraits):
55
scene = Instance(SceneModel, ())
57
view = View(Item('scene', height=400, show_label=False,
58
editor=SceneEditor()))
60
MyModel().configure_traits()
62
A `Mayavi` button to pop up the pipeline dialog can be added on the
63
toolbar by specifying a different scene view to the `SceneEditor`::
65
from enthought.mayavi.core.ui.mayavi_scene import MayaviScene
68
editor=SceneEditor(scene_class=MayaviScene)
71
The ``mayavi_traits_ui.py`` example is a fairly comprehensive example that
72
demonstrates how you can embed almost the entire mayavi UI into your traits
73
based UI. mlab based visualization.
75
A scene, with `mlab` embedded
76
..............................
78
An object representing a scene is interesting only if you can visualize
79
data with the scene. For this we can instanciate an `Engine` and assign
80
it to the scene. Having an `Engine` only for one scene allows us to
81
confine action and visualization objects only to this scene.
83
We can also use an `MlabSceneModel` instance, rather than a `SceneModel`,
84
imported from `enthought.mayavi.tools.mlab_scene_model`. This scene model
85
has an embedded `mlab` attribute, that exposes all the mlab commands (see
86
:ref:`mlab_plotting_functions`) as attributes, applying on the scene. For
87
instance plotting 3D points can be achieved with
88
`self.scene.mlab.points3d(x, y, z, s)`.
90
Making the visualization live
91
..............................
93
Having an interactive application is interesting only if you can do
94
custom, domain-specific, interaction with the visualization.
96
An important use case is modifying the data visualized as a parameter is
97
changed interactively. For this we can use the inplace modification of
98
the data of an mlab object, as for animation of an mlab plot (see
99
:ref:`mlab-animating-data`). Suppose we are plotting a line curve defined
100
by a function of two parameters::
102
from numpy import linspace, pi, cos, sin
104
def curve(n_mer, n_long):
105
phi = linspace(0, 2*pi, 2000)
106
return [ cos(phi*n_mer) * (1 + 0.5*cos(n_long*phi)),
107
sin(phi*n_mer) * (1 + 0.5*cos(n_long*phi)),
111
Using `mlab`, we could plot the curve with `plot3d`::
113
x, y, z, s = curve(4, 6)
114
from enthought.mayavi import mlab
115
plot = mlab.plot3d(x, y, z, s)
117
Modifying the plot for new parameters could be written::
119
x, y, z, t = curve(4, 8)
120
plot.mlab_source.set(x=x, y=y, z=z, scalars=t)
122
In a dialog, this would be::
124
from enthought.traits.api import HasTraits, Range, Instance, \
126
from enthought.traits.ui.api import View, Item, HGroup
127
from enthought.tvtk.pyface.scene_editor import SceneEditor
128
from enthought.mayavi.tools.mlab_scene_model import \
130
from enthought.mayavi.core.ui.mayavi_scene import MayaviScene
133
class Visualization(HasTraits):
134
meridional = Range(1, 30, 6)
135
transverse = Range(0, 30, 11)
136
scene = Instance(MlabSceneModel, ())
139
# Do not forget to call the parent's __init__
140
HasTraits.__init__(self)
141
x, y, z, t = curve(self.meridional, self.transverse)
142
self.plot = self.scene.mlab.plot3d(x, y, z, t,
145
@on_trait_change('meridional,transverse')
146
def update_plot(self):
147
x, y, z, t = curve(self.meridional, self.transverse)
148
self.plot.mlab_source.set(x=x, y=y, z=z, scalars=t)
150
view = View(Item('scene', height=400, show_label=False,
151
editor=SceneEditor(scene_class=MayaviScene)),
152
HGroup('meridional', 'transverse'))
154
visualization = Visualization()
155
visualization.configure_traits()
157
A complete, runnable, code based on the above comments is given by the
158
``mlab_traits_ui.py`` example.
161
Integrating in a WxPython application
162
--------------------------------------
164
Using the `Visualization` class defined above::
168
class MainWindow(wx.Frame):
169
def __init__(self, parent, id):
170
wx.Frame.__init__(self, parent, id, 'Mayavi in Wx')
171
self.visualization = Visualization()
172
self.control = self.visualization.edit_traits(parent=self,
173
kind='subpanel').control
176
app = wx.PySimpleApp()
177
frame = MainWindow(None, wx.ID_ANY)
181
Integrating in a PyQt application
182
----------------------------------
184
Before defining the `Visualization` class::
187
os.environ['ETS_TOOLKIT'] = 'qt4'
189
And using this class::
191
from PyQt4 import QtGui
193
class MainWindow(QtGui.QMainWindow):
194
def __init__(self, parent=None):
195
QtGui.QWidget.__init__(self, parent)
196
self.visualization = Visualization()
197
self.ui = self.visualization.edit_traits().control
198
self.setCentralWidget(self.ui)
200
window = MainWindow()