Mayavi 2 脚本:主模块¶
日期 | 2017-07-13(最后修改),2007-08-10(创建) |
---|
简介¶
这是真正的东西 ;-)
您将在这里学习如何使用 !MayaVi2 中的各种模块。
注意:某些模块无法添加到任何类型的数据集中。例如,某些模块仅适用于 !StructuredGrid 或 !StructuredPoints(有关 VTK 数据类型的更多信息,请参阅 http://www.vtk.org/pdf/file-formats.pdf)。需要时将每次指定。
注意 2:在 !MayaVi2 树视图中,“主模块”(称为“模块”)已与加载 !ModuleManager 的“基本模块”分开。当然,您可以加载所有模块和过滤器,而无需使用 !ModuleManager。
ImagePlaneWidget/ScalarCutPlane/SliceUnstructuredGrid 模块¶
毫无疑问,显示 3D 数据最简单(也是最容易,但不是最令人印象深刻 ;-))的方法是在一些垂直于 Ox、Oy 或 Oz 轴或倾斜的平面上切片它。
您可以用来执行此操作的模块之一称为 !ScalarCutPlane。它适用于任何数据。
注意:由于 !ImagePlaneWidget 模块也在平面上显示标量数据(但它不会“切割”数据),请参阅 [:Cookbook/MayaVi/Examples: Example with a 3D array as numerical source (numeric_source.py)] 或 [:Cookbook/MayaVi/Examples: Example using ImagePlaneWidget Module (test.py)] 以获取有关如何使用此模块的更多信息。
您必须设置几个参数
* 平面 法线;
\ * 它的 原点;
\ * 小部件 启用 或 不启用: 如果 启用, 您可以 使用 鼠标 修改 法线 方向, 位置 等;
\ * 一些 颜色 属性.
因此,您必须键入
from enthought.mayavi.modules.scalar_cut_plane import ScalarCutPlane
和
scp = ScalarCutPlane() # set scp as ScalarCutPlane() module
script.add_module(scp) # add module to the scene
scp.implicit_plane.normal = (1, 0, 0) # set normal to Ox axis
# set origin to (i=10, j=25, k=25) i.e. integers for a structured grid
scp.implicit_plane.origin = (10, 25, 25)
# set origin to (x=1.0, y=2.5, z=2.5) i.e. reals for unstructured grids
# scp.implicit_plane.origin = (1.0, 2.5, 2.5)
scp.implicit_plane.widget.enabled = False
scp.actor.property.diffuse = 0.0 # set some color properties
scp.actor.property.ambient = 1.0 #
scp.actor.property.opacity = 1.0 #
scp.module_manager.scalar_lut_manager.data_range = [0, 1]
请注意,如果您启用小部件,您将能够实时地平移(将鼠标移到红色框上)、更改切面的法线(将鼠标移到灰色箭头上)。
您也可以将切面显示为“扭曲曲面”,只需添加几行代码,设置比例因子和法线是否需要计算(更平滑的曲面)。
scp.enable_warp_scalar = True
scp.compute_normals = True
scp.warp_scalar.filter.scale_factor = 20
当然,您可以添加任意数量的切面,无论是否倾斜。
现在让我们来看一个更复杂的例子:我们希望将每个切面的不透明度设置为 0.2,并为相同的切面添加轮廓(#10)。上面的代码行已更改如下
注意:我同意,这不是编写此类代码的最佳方式。您显然可以编写一个方法来完成相同的事情。但这并不是这里的目的。
### cutplane #1, normal to Ox, opacity = 0.2, representation = surface
scp = ScalarCutPlane()
script.add_module(scp)
scp.implicit_plane.normal = (1, 0, 0)
scp.implicit_plane.origin = (25, 25, 25)
scp.implicit_plane.widget.enabled = False
scp.actor.property.diffuse = 0.0
scp.actor.property.ambient = 1.0
scp.actor.property.opacity = 0.2
scp.module_manager.scalar_lut_manager.data_range = [0, 1]
### cutplane #2, normal to Oy, opacity = 0.2, representation = surface
scp = ScalarCutPlane()
script.add_module(scp)
scp.implicit_plane.normal = (0, 1, 0)
scp.implicit_plane.origin = (25, 25, 25)
scp.implicit_plane.widget.enabled = False
scp.actor.property.diffuse = 0.0
scp.actor.property.ambient = 1.0
scp.actor.property.opacity = 0.2
scp.module_manager.scalar_lut_manager.data_range = [0, 1]
### cutplane #3, normal to Oz, opacity = 0.2, representation = surface
scp = ScalarCutPlane()
script.add_module(scp)
scp.implicit_plane.normal = (0, 0, 1)
scp.implicit_plane.origin = (25, 25, 25)
scp.implicit_plane.widget.enabled = False
scp.actor.property.diffuse = 0.0
scp.actor.property.ambient = 1.0
scp.actor.property.opacity = 0.2
scp.module_manager.scalar_lut_manager.data_range = [0, 1]
### cutplane #4, normal to Ox, representation = contour
scp = ScalarCutPlane()
script.add_module(scp)
scp.implicit_plane.normal = (1, 0, 0)
scp.implicit_plane.origin = (25, 25, 25)
scp.implicit_plane.widget.enabled = False
scp.actor.property.diffuse = 0.0
scp.actor.property.ambient = 1.0
scp.enable_contours = True
scp.contour.number_of_contours = 10
scp.contour.minimum_contour, scp.contour.maximum_contour = [0, 1]
scp.module_manager.scalar_lut_manager.data_range = [0, 1]
### cutplane #5, normal to Oy, representation = contour
scp = ScalarCutPlane()
script.add_module(scp)
scp.implicit_plane.normal = (0, 1, 0)
scp.implicit_plane.origin = (25, 25, 25)
scp.implicit_plane.widget.enabled = False
scp.actor.property.diffuse = 0.0
scp.actor.property.ambient = 1.0
scp.enable_contours = True
scp.contour.number_of_contours = 10
scp.contour.minimum_contour, scp.contour.maximum_contour = [0, 1]
scp.module_manager.scalar_lut_manager.data_range = [0, 1]
### cutplane #6, normal to Oz, representation = contour
scp = ScalarCutPlane()
script.add_module(scp)
scp.implicit_plane.normal = (0, 0, 1)
scp.implicit_plane.origin = (25, 25, 25)
scp.implicit_plane.widget.enabled = False
scp.actor.property.diffuse = 0.0
scp.actor.property.ambient = 1.0
scp.enable_contours = True
scp.contour.number_of_contours = 10
scp.contour.minimum_contour, scp.contour.maximum_contour = [0, 1]
scp.module_manager.scalar_lut_manager.data_range = [0, 1]
看起来像这样
另一个切片网格的模块称为 !SliceUnstructuredGrid。顾名思义,它应该只适用于非结构化网格。但是,由于它已经在结构化网格上进行了测试,即使 !MayaVi2 会发出警告消息,它仍然“适用于”结构化网格(对我们的例子来说很高兴 ;-))。
事实上,它的兴趣点并不仅仅是切片网格,更重要的是显示网格的结构,即网格单元。因此,您可以查看是否存在任何问题(孔等)。
from enthought.mayavi.modules.slice_unstructured_grid import SliceUnstructuredGrid
和
sug = SliceUnstructuredGrid()
script.add_module(sug)
# unstructured grid so origin coordinates are reals
sug.implicit_plane.origin = (25., 25., 25.)
sug.implicit_plane.normal = (1, 1, 1)
sug.implicit_plane.widget.enabled = False
sug.extract_geometry.extract_boundary_cells = False
sug.extract_geometry.extract_inside = True
sug.extract_geometry.extract_only_boundary_cells = False
sug.geom_filter.cell_clipping = False
sug.geom_filter.extent_clipping = False
sug.geom_filter.merging = True
sug.geom_filter.point_clipping = False
sug.actor.property.representation = 'wireframe'
sug.actor.property.diffuse = 0.0
sug.actor.property.ambient = 1.0
sug.actor.property.opacity = 1.0
sug.module_manager.scalar_lut_manager.data_range = [0, 1]
场景应该看起来像这样
GridPlane/StructuredGridOutline 模块¶
使用 !GridPlane 模块也可以切片网格,但与 !ScalarCutPlane 模块截然不同。您只能获得沿 Ox、Oy 和 Oz 轴的法线平面,并且它只适用于结构化网格。但与 !ScalarCutPlane 模块不同,后者始终在平面上切片网格,!GridPlane 会穿过网格:如果它是共形网格,切片将不是平面,而是遵循网格曲率的东西。
!StructuredGridOutline 模块与 Outline 模块的作用相同,但适用于共形网格。
为了说明如何使用这些模块,让我们考虑 VTKData 目录中提供的示例,combxyz.bin & combq.bin 文件(Plot3D 格式),来自您可以在 此处 下载的 tarball vtkdata-5.0.3.tar.gz。
所以,输入
from enthought.mayavi.modules.strucured_grid_outline import StructuredGridOutline
from enthought.mayavi.modules.grid_plane import GridPlane
# to load Plot3D files format
from enthought.mayavi.sources.plot3d_reader import PLOT3DReader
和
src = PLOT3DReader()
src.initialize('combxyz.bin', 'combq.bin')
script.add_source(src)
sgo = StructuredGridOutline()
script.add_module(sgo)
gp = GridPlane()
script.add_module(gp)
gp.grid_plane.axis = 'x'
gp.grid_plane.position = 2
gp.actor.mapper.scalar_visibility = True
gp.actor.property.representation = 'surface'
gp.actor.property.diffuse = 0.0
gp.actor.property.ambient = 1.0
gp.actor.property.opacity = 1
gp = GridPlane()
script.add_module(gp)
gp.grid_plane.axis = 'x'
gp.grid_plane.position = 25
gp.actor.mapper.scalar_visibility = True
gp.actor.property.representation = 'surface'
gp.actor.property.diffuse = 0.0
gp.actor.property.ambient = 1.0
gp.actor.property.opacity = 1
gp = GridPlane()
script.add_module(gp)
gp.grid_plane.axis = 'x'
gp.grid_plane.position = 55
gp.actor.mapper.scalar_visibility = True
gp.actor.property.representation = 'surface'
gp.actor.property.diffuse = 0.0
gp.actor.property.ambient = 1.0
gp.actor.property.opacity = 1
场景渲染如下
表面/等值面模块¶
其他模块是表面和!等值面。这些模块适用于任何数据。
表面模块与!等值面模块的功能相同,但会自动显示给定范围内多个值的多个等值面。
事实上,您可以使用!等值面模块获得相同的结果,但您需要设置每个等值。
当使用表面或!等值面模块显示多个等值面时,您应该将不透明度设置为低于 1 的值,以便看到所有等值面。
使用表面模块很简单
from enthought.mayavi.modules.surface import Surface
然后
s = Surface()
s.enable_contours = True # we want contours enabled
s.contour.auto_contours = True # we want isovalues automatically well-defined
s.contour.number_of_contours = 10 # self-explanatory ;-)
s.actor.property.opacity = 0.2
script.add_module(s)
s.contour.minimum_contour = 0
s.contour.maximum_contour = 1
s.module_manager.scalar_lut_manager.data_range = [0, 1]
场景应该看起来像这样
使用!等值面模块并不困难。例如,假设我们想要与表面模块显示的结果相同。
from enthought.mayavi.modules.iso_surface import IsoSurface
和
isosurf = IsoSurface()
script.add_module(isosurf)
isosurf.contour.contours = [0.1111, 0.2222, 0.3333, 0.4444, 0.5555, 0.6666, 0.7777, 0.8888]
isosurf.compute_normals = True
isosurf.actor.property.opacity = 0.2
isosurf.module_manager.scalar_lut_manager.data_range = [0, 1]
这当然会生成与之前相同的场景,但现在,您可以分别控制每个等值。
有趣的是,您可以通过移动滑块实时设置表面或等值线的最小/最大轮廓或!等值线的轮廓。这是一个非常有用的功能。并且可以渲染非常漂亮的“动态”场景!:-)
体积模块¶
对我来说,它仍然处于实验阶段(您可以设置很多参数),所以本节将非常简短 ;-)
数据不是以表面的形式显示,而是在整个体积中显示。
开始导入所需的模块
from enthought.mayavi.modules.volume import Volume
然后,像往常一样将其添加到源代码中
v = Volume()
script.add_module(v)
v.lut_manager.show_scalar_bar = True
v.lut_manager.scalar_bar.orientation = 'vertical'
v.lut_manager.scalar_bar.width = 0.1
v.lut_manager.scalar_bar.height = 0.8
v.lut_manager.scalar_bar.position = (0.01, 0.15)
v.lut_manager.scalar_bar.label_text_property.color = fg_color
v.lut_manager.scalar_bar.title_text_property.color = fg_color
v.lut_manager.number_of_labels = 10
v.lut_manager.data_name = ""
请注意,体积模块有一个“颜色传递函数”,它与其他模块使用的!查找表完全不同。
渲染后的场景应该看起来像这样(感谢 Prabhu 使 CTF 与 LUT 相似)
向量/符号/向量切平面/扭曲向量切平面模块¶
到目前为止,我们只处理了标量值。您还可以将值显示为向量。您可以使用以下三个模块之一
* 向量 模块: 比例 和 颜色 由 向量 数据 设置, 即 一个 3D 数组 向量 场;
* 符号 模块: 比例 和 颜色 由 标量 数据 设置;
* !VectorCutPlane 模块;在这种情况下,向量不会在整个体积中显示,而只会在切平面上显示,就像 !ScalarCutPlane 模块对标量值所做的那样。
您可以为这些模块设置几个参数,涉及箭头形状等。
首先,这取决于您体积中的点数,但建议您对数据进行降采样。如果不这样做,您将看不到任何东西,除了到处都是大量的箭头,从而丢失了相关信息。您可以选择随机或不随机降采样。
其次,您可以从以下列表中选择向量的形状:2D 图形或箭头、圆锥、圆柱、球体和立方体 3D 向量形状。
第三,您可以为所选形状设置一些参数。例如,使用箭头形状,您可以为轴和尖端设置以下属性
* 轴半径;
* 轴分辨率(多边形数量);
* 尖端长度;
* 尖端半径;
* 尖端分辨率;
您还可以设置向量位置,在“尾部”、“居中”和“头部”之间,设置比例模式、颜色模式、比例因子(向量显示的大小)等。
现在让我们看看如何做到这一点。
首先,导入所需的模块。
对于 Vectors 模块,
from enthought.mayavi.modules.vectors import Vectors
对于 Glyph 模块,
from enthought.mayavi.modules.glyph import Glyph
对于 !VectorCutPlane 模块,
from enthought.mayavi.modules.vector_cut_plane import VectorCutPlane
事实上,您会发现这三个模块使用相同的对象和方法。只有默认值不同。
例如,对于 Vectors 模块,您可以键入
v = Vectors()
script.add_module(v)
v.glyph.mask_input_points = True # we want to decimate our data...
v.glyph.mask_points.on_ratio = 100 # ...by a ratio of 100
v.glyph.mask_points.random_mode = True # I want a randomly decimation
v.glyph.glyph_source = v.glyph.glyph_list[1] # I like ArrowSource ;-)
# following values are the default values: tweak your own !
v.glyph.glyph_source.shaft_radius = 0.03
v.glyph.glyph_source.shaft_resolution = 6
v.glyph.glyph_source.tip_length = 0.35
v.glyph.glyph_source.tip_radius = 0.1
v.glyph.glyph_source.tip_resolution = 6
v.glyph.glyph.scale_factor = 10
v.glyph.glyph_position = 'tail'
v.glyph.scale_mode = 'scale_by_vector'
v.glyph.color_mode = 'color_by_vector'
### if you use Glyph module, here are the default values
# v.glyph.glyph_position = 'center'
# v.glyph.scale_mode = 'scale_by_scalar'
# v.glyph.color_mode = 'color_by_scalar'
如果我们再次考虑 ;-), 之前显示的相同 3D 数据,但这次使用向量而不是标量数据,场景应该看起来像这样
对于 !VectorCutPlane 模块,您可以设置与上面相同的属性,以及 !ScalarCutPlane 模块的属性,例如 implicit_plane.normal、implicit_plane.origin、implicit_plane.widget.enabled 等
vcp = VectorCutPlane()
script.add_module(vcp)
vcp.glyph.mask_input_points = True
vcp.glyph.mask_points.on_ratio = 5
vcp.glyph.mask_points.random_mode = False
vcp.glyph.glyph_source = vcp.glyph.glyph_list[1]
vcp.glyph.glyph_source.shaft_radius = 0.03
vcp.glyph.glyph_source.shaft_resolution = 6
vcp.glyph.glyph_source.tip_length = 0.35
vcp.glyph.glyph_source.tip_radius = 0.1
vcp.glyph.glyph_source.tip_resolution = 6
vcp.glyph.glyph.scale_factor = 20
vcp.glyph.glyph_position = 'tail'
vcp.glyph.scale_mode = 'scale_by_vector'
vcp.glyph.color_mode = 'color_by_vector'
vcp.implicit_plane.normal = (1, 0, 0) # set normal to Ox axis
vcp.implicit_plane.origin = (10, 25, 25) # set origin to (i=10, j=25, k=25) for a structured grid
vcp.implicit_plane.widget.enabled = True
vcp.actor.property.diffuse = 0.0 # set some color properties
vcp.actor.property.ambient = 1.0 #
vcp.actor.property.opacity = 1.0 #
vcp.module_manager.vector_lut_manager.data_range = [0, 1]
这应该渲染这个场景
您还可以根据向量场扭曲切平面。为此,您需要加载另一个模块,而不是 !VectorCutPlane,名为 !WarpVectorCutPlane。
键入
from enthought.mayavi.modules.warp_vector_cut_plane import WarpVectorCutPlane
然后
wvcp = WarpVectorCutPlane()
script.add_module(wvcp)
wvcp.implicit_plane.normal = (1, 0, 0) # set normal to Ox axis
wvcp.implicit_plane.origin = (10, 25, 25) # set origin to (i=10, j=25, k=25) for a structured grid
wvcp.implicit_plane.widget.enabled = True
wvcp.compute_normals = True
wvcp.warp_vector.filter.scale_factor = 10
您应该得到这个(与使用 !ScalarCutPlane 模块的扭曲表面进行比较)
![](files/../_static/items/attachments/MayaVi_ScriptingMayavi2_MainModules/module_warpvcp.png)
流线模块¶
另一种显示矢量场的方法是使用流线模块。
这里我们考虑其他 Plot3D 文件:postxyz.bin & postq.bin,您可以从 这里 下载。您可以在 VTK 主页 这里 找到使用这些文件的截图。
您可以为该模块设置多个参数:例如,流线的类型(管、带或线)及其属性,以及“种子”。
在本例中,我们还使用了 !GridPlane 模块。
开始导入所需的模块
from enthought.mayavi.sources.plot3d_reader import PLOT3DReader
from enthought.mayavi.modules.streamline import Streamline
from enthought.mayavi.modules.grid_plane import GridPlane
在本例中,我们希望流线以管状显示,有 10 个边,种子设置为线种子。我们还选择显示 Plot3D 文件的“动能”部分。
src = PLOT3DReader()
src.initialize('postxyz.bin', 'postq.bin')
src.scalars_name = "kinetic energy"
script.add_source(src)
gp = GridPlane()
script.add_module(gp)
gp.grid_plane.axis = 'x'
gp.actor.mapper.scalar_visibility = True
gp.actor.property.representation = 'surface'
gp.actor.property.diffuse = 0.0
gp.actor.property.ambient = 1.0
gp.actor.property.opacity = 1
gp = GridPlane()
script.add_module(gp)
gp.grid_plane.axis = 'z'
gp.actor.mapper.scalar_visibility = False
gp.actor.property.representation = 'wireframe'
gp.actor.property.diffuse = 0.0
gp.actor.property.ambient = 1.0
gp.actor.property.opacity = 1
strl = Streamline()
script.add_module(strl)
strl.streamline_type = "tube" # tube, ribbon or line
strl.tube_filter.number_of_sides = 10
strl.tube_filter.radius = 0.1
strl.seed.widget = strl.seed.widget_list[1] # [Sphere, Line, Plane, Point]
strl.seed.widget.align = "z_axis" # or "x_axis", "y_axis"
strl.seed.widget.point1 = (-0.7, 0, 0)
strl.seed.widget.point2 = (-0.7, 0, 4.82)
strl.seed.widget.resolution = 10
strl.seed.widget.enabled = False
这应该看起来像
注意:您也可以在 [:Cookbook/MayaVi/Examples: Cookbook/MayaVi/Examples] 中看到使用流线模块的示例。
章节作者:FredericPetit、Christian Gagnon
附件