~ubuntu-branches/debian/sid/mayavi2/sid

« back to all changes in this revision

Viewing changes to docs/source/mayavi/data.rst

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath
  • Date: 2009-03-27 04:34:55 UTC
  • mfrom: (1.2.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20090327043455-vs6ox32daj6ndw33
Tags: 3.2.0-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
.. _creating-data-for-mayavi:
 
1
.. _data-structures-used-by-mayavi:
2
2
 
3
 
Creating data for Mayavi
4
 
========================
 
3
Data structures used by Mayavi
 
4
==============================
5
5
 
6
6
Describing data in three dimension in the general case is a complex
7
7
problem. Mayavi helps you focus on your visualization work and not worry
8
8
too much about the underlying data structures, for instance using mlab
9
 
(see :ref:`simple-scripting-with-mlab`). However, if you want to create
10
 
data for a more efficient visualization, it helps to understand the VTK
11
 
data structures that Mayavi uses.
 
9
(see :ref:`simple-scripting-with-mlab`). We suggest you create sources
 
10
for Mayavi using `mlab` or Mayavi sources when possible. However, if you
 
11
want to create data with a very specific structure for a more efficient
 
12
visualization, it helps to understand the VTK data structures that Mayavi
 
13
uses.
12
14
 
13
15
VTK data structures
14
16
--------------------
15
17
 
 
18
Mayavi uses the VTK library for all its visualization needs. The data is
 
19
exposed internally, by the sources, or at the output of the filters, as
 
20
VTK datasets, described below. Understanding these structures is useful
 
21
not only to manipulate them, but also to understand what happens when
 
22
using filters to transform the data in the pipeline.
 
23
 
 
24
Caracteristics of a dataset
 
25
.............................
 
26
 
 
27
A dataset is defined by many different characteristics:
 
28
 
 
29
.. image:: images/dataset_diagram/dataset_diagram.jpg
 
30
 
 
31
:Connectivity:
 
32
 
 
33
    Connectivity is not only necessary to draw lines between the
 
34
    different points, it is also needed to define a volume.
 
35
 
 
36
    **Implicit connectivity**: connectivity or positioning is implicit. In
 
37
    this case the data is considered as arranged on a lattice-like structure,
 
38
    with equal number of layers in each direction, x increasing first along
 
39
    the array, then y and finally z.
 
40
 
 
41
:Data:
 
42
 
 
43
    Dataset are made of points positioned in 3D, with the corresponding
 
44
    data. Each dataset can carry several data components.
 
45
 
 
46
    **Scalar or Vectors data**: The data can be scalar, in which case VTK
 
47
    can perform operations such as taking the gradient and display the
 
48
    data with a colormap, or vector, in which case VTK can perform an
 
49
    integration to display streamlines, display the vectors, or extract the 
 
50
    norm of the vectors, to create a scalar dataset.
 
51
 
 
52
    **Cell data and point data**: Each VTK dataset is defined by vertices and
 
53
    cells, explicitly or implicitly. The data, scalar or vector, can be
 
54
    positioned either on the vertices, in which case it is called point data,
 
55
    or associated with a cell, in which case it is called cell data.
 
56
    Point data is stored in the `.point_data` attribute of the dataset,
 
57
    and the cell data is stored in the `.cell_data` attribute.
 
58
 
 
59
    In addition the data arrays have an associated name, which is used in
 
60
    Mayavi to specify on which data component module or filter apply (eg
 
61
    using the`SetActiveAttribute` filter.
 
62
 
 
63
All VTK arrays, whether it be for data or position, are exposed as (n, 3)
 
64
numpy arrays for 3D components, and flat (n, ) array for 1D components.
 
65
The index vary in the opposite order as numpy: z first, y and then x.
 
66
Thus to go from a 3D numpy array to the corresponding flatten VTK array,
 
67
the operation is::
 
68
 
 
69
    vtk_array = numpy_array.T.ravel()
 
70
 
 
71
Description of the different datasets
 
72
......................................
 
73
 
16
74
The 5 VTK structures used are the following (ordered by the cost of
17
75
visualizing them).:
18
76
 
26
84
UnstructuredGrid    Explicit      Volumes and surfaces        x, y, z positions of vertices and arrays of volume Cells
27
85
================== ============= =========================== ============================================================
28
86
 
29
 
**Implicit connectivity**: connectivity or positioning is implicit. In
30
 
this case the data is considered as arranged on a lattice-like structure,
31
 
with equal number of layers in each direction, x increasing first along
32
 
the array, then y and finally z.
33
 
 
34
 
**Cell data and point data**: Each VTK dataset is defined by vertices and
35
 
cells, explicitly or implicitly. The data, scalar or vector, can be
36
 
positioned either on the vertices, in which case it is called point data,
37
 
or associated with a cell, in which case it is called cell data.
38
 
 
39
 
 
40
 
**Description of the datasets**:
41
87
 
42
88
:ImageData:
43
89
  This dataset is made of data points positioned on an orthogonal grid,
44
90
  with constant spacing along each axis. The position of the data points
45
91
  are inferred from their position on the data array (implicit
46
92
  positioning), an origin and a spacing between 2 slices along each axis.
47
 
  In 2D, this can be understood as a raster image. 
 
93
  In 2D, this can be understood as a raster image. This is the data
 
94
  structure created by the `ArraySource` mayavi source, from a 3D numpy
 
95
  array, as well as the `mlab.pipeline.scalar_field` and 
 
96
  `mlab.pipeline.vector_field` factory functions, if the `x`, `y` and 
 
97
  `z` arrays are not explicitely specified.
48
98
 
49
99
  .. image:: image_data.png
50
100
 
 
101
  Creating a `tvtk.ImageData` object from numpy arrays::
 
102
  
 
103
    from enthought.tvtk.api import tvtk
 
104
    from numpy import random
 
105
    data = random.random((3, 3, 3))
 
106
    i = tvtk.ImageData(spacing=(1, 1, 1), origin=(0, 0, 0))
 
107
    i.point_data.scalars = data.ravel()
 
108
    i.point_data.scalars.name = 'scalars'
 
109
    i.dimensions = data.shape
 
110
 
 
111
 
51
112
:RectilinearGrid:
52
113
  This dataset is made of data points positioned on an orthogonal grid, 
53
114
  with arbitrary spacing along the various axis. The position of the data
56
117
 
57
118
  .. image:: rectilinear_grid.png
58
119
 
 
120
  Creating a `tvtk.RectilinearGrid` object from numpy arrays::
 
121
 
 
122
    from enthought.tvtk.api import tvtk
 
123
    from numpy import random, array
 
124
    data = random.random((3, 3, 3))
 
125
    r = tvtk.RectilinearGrid()
 
126
    r.point_data.scalars = data.ravel()
 
127
    r.point_data.scalars.name = 'scalars'
 
128
    r.dimensions = data.shape
 
129
    r.x_coordinates = array((0, 0.7, 1.4))
 
130
    r.y_coordinates = array((0, 1, 3))
 
131
    r.z_coordinates = array((0, .5, 2))
 
132
 
 
133
 
59
134
:StructuredGrid:
60
135
  This dataset is made of data points positioned on arbitrary grid: each
61
136
  point is connected to its nearest neighbors on the data array. The
62
137
  position of the data points are fully described by 1 coordinate
63
 
  arrays, specifying x, y and z for each point.
 
138
  arrays, specifying x, y and z for each point. This is the dataset
 
139
  created by the `mlab.pipeline.scalar_field` and 
 
140
  `mlab.pipeline.vector_field` factory functions, if the `x`, `y` and 
 
141
  `z` arrays are explicitely specified.
 
142
 
64
143
 
65
144
  .. image:: structured_grid.png
66
145
 
 
146
  Creating a `tvtk.StructuredGrid` object from numpy arrays::
 
147
 
 
148
    from numpy import pi, cos, sin, empty, linspace, random
 
149
    from enthought.tvtk.api import tvtk
 
150
 
 
151
    def generate_annulus(r, theta, z):
 
152
        """ Generate points for structured grid for a cylindrical annular
 
153
            volume.  This method is useful for generating a unstructured
 
154
            cylindrical mesh for VTK.
 
155
        """
 
156
        # Find the x values and y values for each plane.
 
157
        x_plane = (cos(theta)*r[:,None]).ravel()
 
158
        y_plane = (sin(theta)*r[:,None]).ravel()
 
159
        
 
160
        # Allocate an array for all the points.  We'll have len(x_plane)
 
161
        # points on each plane, and we have a plane for each z value, so
 
162
        # we need len(x_plane)*len(z) points.
 
163
        points = empty([len(x_plane)*len(z),3])
 
164
        
 
165
        # Loop through the points for each plane and fill them with the
 
166
        # correct x,y,z values.
 
167
        start = 0
 
168
        for z_plane in z:
 
169
            end = start+len(x_plane)
 
170
            # slice out a plane of the output points and fill it
 
171
            # with the x,y, and z values for this plane.  The x,y
 
172
            # values are the same for every plane.  The z value
 
173
            # is set to the current z 
 
174
            plane_points = points[start:end]    
 
175
            plane_points[:,0] = x_plane
 
176
            plane_points[:,1] = y_plane 
 
177
            plane_points[:,2] = z_plane
 
178
            start = end
 
179
            
 
180
        return points
 
181
 
 
182
    dims = (3, 4, 3)
 
183
    r = linspace(5, 15, dims[0])
 
184
    theta = linspace(0, 0.5*pi, dims[1])
 
185
    z = linspace(0, 10, dims[2])
 
186
    pts = generate_annulus(r, theta, z)
 
187
    sgrid = tvtk.StructuredGrid(dimensions=(dims[1], dims[0], dims[2]))
 
188
    sgrid.points = pts
 
189
    s = random.random((dims[0]*dims[1]*dims[2]))
 
190
    sgrid.point_data.scalars = ravel(s.copy())
 
191
    sgrid.point_data.scalars.name = 'scalars'
 
192
 
 
193
 
 
194
 
 
195
 
67
196
:PolyData:
68
197
  This dataset is made of arbitrarily positioned data points that can
69
198
  be connected to form lines, or grouped in polygons to from surfaces
70
199
  (the polygons are broken up in triangles). Unlike the other datasets, 
71
 
  this one cannot be used to describe volumetric data.
 
200
  this one cannot be used to describe volumetric data. The is the dataset
 
201
  created by the `mlab.pipeline.scalar_scatter` and
 
202
  `mlab.pipeline.vector_scatter` functions.
72
203
 
73
204
  .. image:: poly_data.png
74
205
 
 
206
  Creating a `tvtk.PolyData` object from numpy arrays::
 
207
 
 
208
    from numpy import array, random
 
209
    from enthought.tvtk.api import tvtk
 
210
 
 
211
    # The numpy array data.
 
212
    points = array([[0,-0.5,0], [1.5,0,0], [0,1,0], [0,0,0.5],
 
213
                    [-1,-1.5,0.1], [0,-1, 0.5], [-1, -0.5, 0],
 
214
                    [1,0.8,0]], 'f')
 
215
    triangles = array([[0,1,3], [1,2,3], [1,0,5], 
 
216
                       [2,3,4], [3,0,4], [0,5,4], [2, 4, 6],
 
217
                        [2, 1, 7]])
 
218
    scalars = random.random(points.shape) 
 
219
 
 
220
    # The TVTK dataset.
 
221
    mesh = tvtk.PolyData(points=points, polys=triangles)
 
222
    mesh.point_data.scalars = scalars
 
223
    mesh.point_data.scalars.name = 'scalars'
 
224
 
 
225
 
75
226
:UnstructuredGrid:
76
227
  This dataset is the most general dataset of all. It is made of data 
77
228
  points positioned arbitrarily. The connectivity between data points 
81
232
 
82
233
  .. image:: unstructured_grid.png
83
234
 
 
235
  Creating a `tvtk.UnstructuredGrid` object from numpy arrays::
 
236
 
 
237
    from numpy import array, random
 
238
    from enthought.tvtk.api import tvtk
 
239
 
 
240
    points = array([[0,1.2,0.6], [1,0,0], [0,1,0], [1,1,1], # tetra
 
241
                    [1,0,-0.5], [2,0,0], [2,1.5,0], [0,1,0],
 
242
                    [1,0,0], [1.5,-0.2,1], [1.6,1,1.5], [1,1,1], # Hex
 
243
                    ], 'f')
 
244
    # The cells
 
245
    cells = array([4, 0, 1, 2, 3, # tetra
 
246
                   8, 4, 5, 6, 7, 8, 9, 10, 11 # hex
 
247
                   ])
 
248
    # The offsets for the cells, i.e. the indices where the cells
 
249
    # start.
 
250
    offset = array([0, 5])
 
251
    tetra_type = tvtk.Tetra().cell_type # VTK_TETRA == 10
 
252
    hex_type = tvtk.Hexahedron().cell_type # VTK_HEXAHEDRON == 12
 
253
    cell_types = array([tetra_type, hex_type])
 
254
    # Create the array of cells unambiguously.
 
255
    cell_array = tvtk.CellArray()
 
256
    cell_array.set_cells(2, cells)
 
257
    # Now create the UG.
 
258
    ug = tvtk.UnstructuredGrid(points=points)
 
259
    # Now just set the cell types and reuse the ug locations and cells.
 
260
    ug.set_cells(cell_types, offset, cell_array)
 
261
    scalars = random.random(points.shape[0]) 
 
262
    ug.point_data.scalars = scalars
 
263
    ug.point_data.scalars.name = 'scalars'
 
264
 
 
265
 
 
266
 
84
267
External references
85
268
--------------------
86
269
 
142
325
  > -x structured_points3d.py -x structured_grid.py -x unstructured_grid.py
143
326
 
144
327
 
 
328
 
145
329
.. Creating datasets from numpy arrays
146
330
   -----------------------------------
147
331
   
152
336
 
153
337
   Add content here from the presentations.
154
338
 
 
339
Inserting TVTK datasets in the Mayavi pipeline.
 
340
-----------------------------------------------
 
341
 
 
342
TVTK datasets can be created using directly TVTK, as illustrated in the
 
343
examples above. A VTK data source can be inserted in the Mayavi pipeline
 
344
using the VTKDataSource. For instance we can create an `ImageData`
 
345
dataset::
 
346
 
 
347
    from enthought.tvtk.api import tvtk
 
348
    import numpy as np
 
349
    a = np.random.random((10, 10, 10))
 
350
    i = tvtk.ImageData(spacing=(1, 1, 1), origin=(0, 0, 0))
 
351
    i.point_data.scalars = a.ravel()
 
352
    i.point_data.scalars.name = 'scalars'
 
353
    i.dimensions = a.shape
 
354
 
 
355
Inserting this dataset on the pipeline with `VTKDataSource` is done as
 
356
such::
 
357
 
 
358
    from enthought.mayavi.sources.api import VTKDataSource
 
359
    src = VTKDataSource(data=i)
 
360
    from enthought.mayavi.api import Engine
 
361
    e = Engine()
 
362
    e.start()
 
363
    s = e.new_scene()
 
364
    e.add_source(src)
 
365
 
 
366
In addition, if you are scripting using `mlab`, the `mlab.pipeline`
 
367
factory functions creating filters and modules accept VTK datasets, in
 
368
which case they are automatically inserted on the pipeline. A surface
 
369
module could have been used to visualize the `ImageData` dataset as
 
370
such::
 
371
 
 
372
    from enthgouth.mayavi import mlab
 
373
    mlab.pipeline.surface(i)
 
374
 
 
375
Of course, unless you want specific control on the attributes of the VTK
 
376
dataset, or you are using Mayavi in the context of existing code
 
377
manipulating TVTK objects, creating an `ImageData` TVTK object is not
 
378
advised. The `ArraySource` Mayavi will actually create an `ImageData`,
 
379
but make sure you don't get the shape wrong, which can lead to a
 
380
segmentation fault. An even easier way to create a data source for an
 
381
`ImageData` is to use the `mlab.pipeline.scalar_field` function.
 
382
 
 
383
 
155
384
..
156
385
   Local Variables:
157
386
   mode: rst