2009年6月28日星期日

Mayavi2 用户手册3.4——与 scipy 一起使用 Mayavi

内容来自Mayavi2的中文文档项目。本篇文档的源文件在这里。欢迎感兴趣的朋友加入

此教程的例子讲解当使用 scipy 进行数值计算时如何利用 Mayavi 交互地可视化 numpy 数组。此教程假设你熟悉 Python 的数值工具,然后讲解如何使用 Mayavi 与这些工具协同工作。

让我们来研究电势(potential)中例子的轨迹。这在物理和工程中是很常见的问题,电势和轨迹可视化的关键是理解此问题。

我们所关心的电势是一个周期性栅格(periodic lattice), 沉浸在抛物线约束(parabolic confinement)中。我们振动此电势然后查看粒子从一个栅格的洞(hole)跳到另一个的情况。抛物线约束在那里限制粒子的偏移 (excursion)。:

 import numpy as np

def V(x, y, z):
""" A 3D sinusoidal lattice with a parabolic confinement. """
return np.cos(10*x) + np.cos(10*y) + np.cos(10*z) + 2*(x**2 + y**2 + z**2)

既然我们定义好了电势,我们看看在三维中看起来是什么样子。我们可以创建一个点组成的三维网格,然后在这些点处进行采样:

 X, Y, Z = np.mgrid[-2:2:100j, -2:2:100j, -2:2:100j]
V(X, Y, Z)

我们将使用 mlab 模块(请参考simple-scripting-with-mlab)交互地可视化此容量数据(volumetric data)。为此,最好在 Python 的交互命令行输入命令,使用 Mayavi2 内建的命令行或 ipython -wthread。下面我们可视化电势的三维 iso 曲面:

 from enthought.mayavi import mlab
mlab.contour3d(X, Y, Z, V)

我们可以与上面的命令产生的可视化结果进行交互,例如旋转视图。但是为了更好的理解电势的结构,变化 iso 曲面是很有用的。我们可以在 Mayavi 管道树(如果你从 ipython 中运行,需要单击场景中的 Mayavi 图标以弹出管道树) 中双击`IsoSurface`。这将打开一个对话框,允许我们选择轮廓的数值。好的电势视图可以这样获得:关闭 auto contour 并选择 -0.5 作为第一个轮廓数值 (例如,在左边的文本输入框输入数值并按 tab 键)。单击蓝色箭头并选择"Add after"可以加入第二个轮廓值。使用数值15可以得到较好的结果。

我们现在可以管道线中单击 Colors and legends 然后选择不同的 LUT (查找表)以改变使用的颜色。让我们选择 'Paired',因为它可以很好的分开层次。

example_potential_ipython.jpg

为了得到更好的电势视图,我们想显示更多的轮廓,但是其问题是封闭的轮廓隐藏了内部情况。一个解决方案是使用剖面。右击 IsoSurface 节点,通过 "Add module" 子菜单添加 ScalarCutPlane。单击并拖动它可以移动此剖面。

为了实现 numpy 数组和可视化之间的联系,我们可以使用相同的菜单添加 Axes 和 Outline。最后,让我们添加一个颜色条。输入下面的命令:

 mlab.colorbar(title='Potential', orientation='vertical')

或者使用先前使用的 LUT 中的选项。

example_potential.jpg

我们想研究此电势中粒子的运动。为此我们需要推导电势陡度(gradient)相应的力。我们建立陡度函数:

 def gradient(f, x, y, z, d=0.01):
""" Return the gradient of f in (x, y, z). """
fx = f(x+d, y, z)
fx_ = f(x-d, y, z)
fy = f(x, y+d, z)
fy_ = f(x, y-d, z)
fz = f(x, y, z+d)
fz_ = f(x, y, z-d)
return (fx-fx_)/(2*d), (fy-fy_)/(2*d), (fz-fz_)/(2*d)

为了检查陡度函数是否工作正常,让我们可视化它产生的向量场。为了避免显示太多的向量,我们将仅仅评定 X=50 处剖面的陡度,并且只在网格中每三个点评定一个:

 Vx, Vy, Vz = gradient(V, X[50, ::3, ::3], Y[50, ::3, ::3], Z[50, ::3, ::3])
mlab.quiver3d(X[50, ::3, ::3], Y[50, ::3, ::3], Z[50, ::3, ::3],
Vx, Vy, Vz, scale_factor=-0.2, color=(1, 1, 1))

example_gradient.jpg

现在我们可以使用 scipy 积分轨迹。首先必须定义动态流体,这是一个这些参数和时间的函数,返回不同参数的导数。此流体被每个 ODE (常微分方程) 解算器(solver)所使用。它给出系统动态(dynamic)。我们关心的动态由电势推导出的力造成,而我们在三个方向上随时间振动此电势,作为阻尼力。调节阻尼系数及振动的数量和频率可以给出有趣的动态。 :

 def flow(r, t):
""" The dynamical flow of the system """
x, y, z, vx, vy, vz = r
fx, fy, fz = gradient(V, x-.2*np.sin(6*t), y-.2*np.sin(6*t+1), z-.2*np.sin(6*t+2))
return np.array((vx, vy, vz, -fx - 0.3*vx, -fy - 0.3*vy, -fz - 0.3*vz))

现在我们可以积分轨迹:

 from scipy.integrate import odeint

# Initial conditions
R0 = (0, 0, 0, 0, 0, 0)
# Times at which we want the integrator to return the positions:
t = np.linspace(0, 50, 500)
R = odeint(flow, R0, t)

右击对应的管道线节点,选择 delete 可除去剖面和向量场。然后我们开始绘制此轨迹。同时关闭相应的 Colors and legends 节点的第一个颜色条。我们用与它相关的标量信息绘制轨迹,通过调色板(colormap)显示时间:

 x, y, z, vx, vy, vz = R.T
trajectory = mlab.plot3d(x, y, z, t, colormap='hot',
tube_radius=None)
mlab.colorbar(trajectory, title='Time', orientation='vertical')

example_trajectories.jpg
[......]

2009年6月27日星期六

Mayavi2 用户手册3.3——可视化富数据集(rich dataset): 例子数据 fire_ug.vtu

内容来自Mayavi2的中文文档项目。本篇文档的源文件在这里。欢迎感兴趣的朋友加入

类似 heart.vtk,例子数据集 fire_ug.vtu 也可以在目录 examples/data 中找到。此数据集是一个非结构化的网格(unstructured grid),存在一个 VTK XML 文件中,表示一个角落中有火的房间。通过模拟此火焰的流体,将一个特定时刻的结果保存在此文件中。此数据集由 Philip Rubini 博士提供 (当时 Rubini 博士在 Cranfield 大学)。同时提供了一个 VRML 文件,显示火焰被取走的房间情况。

  1. 启动 mayavi2,选择 File->Load data->Open file 来载入数据。再次在左边的树形显示中看到一个节点,但在 TVTK 场景中没有任何显示。此数据集在一个文件中包含了不同的标量和向量数据。如果选择左边的 VTK XML file... 节点,在对象编辑器中将配置读入器(reader)。在其中,可以看到此数据文件中所有标量和向量的下拉列表。任意选择其中一个。

  2. 按照前面所述,使用 Outline 模块建立数据的轮廓。建立 IsoSurface 模块以查看数据的 iso-曲面。也请试试 ScalarCutPlane 模块。

  3. 单击 Colors and legends 节点,选中 Show scalar bar,显示映射颜色的标尺(通过查找表(Look up table)将标量映射为颜色)。试试不同的默认颜色映射。

  4. 现在单击 VTK XML file ... 并选择不同的标量来查看数据如何变化。当标量改变时,图例将自动更新。

  5. 此数据也包括向量。标量数据有 uvw,但没有速度的大小。假设我们希望查看速度大小的 iso-曲面,可以使用 ExtractVectorNorm 过滤器。选择 Visualize->Filters->Extract Vector Norm 菜单可以使用此过滤器。

  6. 如果现在建立 ScalarCutPlane,可以在 ExtractVectorNorm 节点下看到 Colors and legends 节点。这个标量剖面用颜色显示此过滤器生成的速度大小。可以将 iso-曲面模块从另一个 Colors and legends 节点下拖到此 Colors and legends 节点下,使得生成的 Iso-曲面 是关于速度大小的,而不是关于所选的标量。

    注意:左边的显示树表示如下的数据流动管道, source -> filter -> modules。本质上是数据从父节点流到其下的子节点。

    现在如果你想在管道的不同分支进行可视化,例如你想查看温度数据的 iso 曲面,必须单击模块或源对象(VTK XML File ... 节点)本身,然后选择菜单项。当选择了显示树中的一项,此项目成为当前对象,其后选择的菜单项将在当前对象下建立新模块/滤波器。

  7. 可以过滤"已经过滤的数据"。选择 ExtractVectorNorm 节点使其成为当前对象。现在通过 Visualize->Filters->Threshold 建立 Threshold 滤波器。然后在对象编辑器中设置上限和下限,例如 0.5 和 3.0。如果在这里建立 VectorCutPlane 模块,并且移动此剖面,应该能看到箭头,但是只有位于上下限之间的箭头。因此可以使用这样的步骤建立很复杂的可视化管道。

  8. 有几个向量模块:VectorCutPlaneVectorsWarpVectorCutPlaneStreamlines。如果查看流线(streamline),mayavi 将产生数据集中向量的流线。为了查看初始数据集的流线,可以单击原先的 Outline 模块(或数据源),然后选择 Streamline 菜单项。可以使用3D小部件移动屏幕上不同类型的种子(seed)。这些位置的种子点(seed point)用来跟踪流线。球(Sphere)、线和平面源可以用来初始化流线种子。

  9. 选择 File->Open->VRML2 file 菜单项打开 VRML 文件``room_vis.wrl``,可以查看着火的房间。

  10. 建立起复杂的可视化管道后,想将其保存下来以便以后再查看,可以通过 File->Save Visualization 菜单项保存整个可视化。可以使用 File->Load Visualization 菜单项载入保存后的文件。此选项并不是100%鲁棒,仍在实验阶段。后续版本将改善此功能。毕竟,此功能暂时可以使用。

再次说明,此例中的可视化是使用用户界面生成的,但可以完全使用 Python 脚本完成。一个简单的脚本 examples/streamline.py 演示了几个上面的模块。用户可以研究一下此文件。可按照如下方式运行此脚本:

 $ cd examples
$ python streamline.py

或者:

 $ mayavi2 -x streamline.py

从此例可以看到,编写脚本使用 mayavi 进行可视化是很简单的。下面是此脚本生成的图形。


[......]

2009年6月10日星期三

收到Google寄来的礼物


今年2月份时,由于 feedburner出错(Google's poor planning on Feedburner),曾收到Google的道歉信,许诺给我寄一份礼物。就在我几乎忘记此事时,昨天收到了Google寄来的包裹:一个无线光电鼠标(包括一个PS2转usb转换器),一支签字笔,一个无源USB集中器。

免费服务出了错还赔礼道歉送礼物,而很多公司收了钱却不好好干活,真是天壤之别。

我这个用户的忠诚度又飙升了两米。


[......]