
不知什么原因,某天启动电脑后,桌面上的图标、文件和背景图片都不见了。一直没有时间去折腾,今天终于回复原状了。
打开“开始菜单-设置-xfce4设置中心-桌面“对话框,选中“允许xfce管理桌面”,并记得关机时选中“保存设置”,这样才能在下次启动时也有效。
笔记,见闻,感想,评论 @ 社会、*nix、体育、python、旅游、AI、摄影、SF……
在此例中,我们从标量场的梯度(gradient)中产生向量场,然后交互地查看。此例介绍怎样交互地进行类似前面例子的操作,例如使用过滤器 (filter)和模块(module)。前面的例子使用 `numpy`进行大多数操作,这一步则需要对 Mayavi 和 VTK 过滤器有更多的了解。与之对应的益处是可以交互地进行可视化。
首先,我们生成与前面例子相同的标量场。打开 Mayavi,在 Python 命令行内输入下面的代码:
from enthought.mayavi import mlab
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]
mlab.contour3d(X, Y, Z, V)
像前面的例子一样,可以改变调色板(color map)和在等值面中选定的数值。
为了使用标量场梯度生成向量场,我们将使用`CellDerivative`滤波器。此滤波器可获得单元(也就是点之间,请参考data- structures-used-by-mayavi)内数据的微分。首先使用`PointToCellData`滤波器对单元内各点进行插值,然后使用 `CellDerivatives`滤波器,接着使用`CellToPointData`滤波器重新获得点数据。
使用`VectorCutPlane`模块可以可视化向量场。生成的标量数据太大,我们可以在`Glyph`标签(以及在此标签内的`Glyph` 标签)将缩放比例(scale factor)减少为0.2。向量场还是太密集,可以在`Masking`标签打开遮蔽(masking)功能,将`on ratio`设为6 (one arrow out of 6 is masked)并关闭随机模式(random mode)。
为了获得更漂亮的颜色,可以改变向量场的调色板:在`VectorCutPlane`上面的`Colors and legend`节点,找到**in the VectorLUT**标签,选择查找表,那里有向量和标量数据的不同调色板。
不像之前的例子,我们可以在对话框中试试各种参数,例如遮蔽,或在`Glyph`标签选择`color_by_scalar`来显示势值(the value of the potential)。我们也可以拖动显示向量的剖面。
既然有了3D向量场,可以使用Mayavi集成(integrate)其中一个粒子的轨迹。为此,我们可以使用streamline模块。此模块显 示起始于种子(seed)表面顶点的轨迹。选择`Point Widget`作为种子(在`Seed`标签),可以在3D场景中拖动种子点。这使我们可以在产生于初始标量场的势位中探索轨迹。这里,所有的轨迹终止于 局部极小势位。可以移动种子点,使我们可以看到每个点将陷入的极小值之处,换句话说,每个局部极小的吸引盆(basin of attraction)。
此教程的例子讲解当使用 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',因为它可以很好的分开层次。
为了得到更好的电势视图,我们想显示更多的轮廓,但是其问题是封闭的轮廓隐藏了内部情况。一个解决方案是使用剖面。右击 IsoSurface 节点,通过 "Add module" 子菜单添加 ScalarCutPlane。单击并拖动它可以移动此剖面。
为了实现 numpy 数组和可视化之间的联系,我们可以使用相同的菜单添加 Axes 和 Outline。最后,让我们添加一个颜色条。输入下面的命令:
mlab.colorbar(title='Potential', orientation='vertical')
或者使用先前使用的 LUT 中的选项。
我们想研究此电势中粒子的运动。为此我们需要推导电势陡度(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))
现在我们可以使用 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')
类似 heart.vtk
,例子数据集 fire_ug.vtu
也可以在目录 examples/data
中找到。此数据集是一个非结构化的网格(unstructured grid),存在一个 VTK XML 文件中,表示一个角落中有火的房间。通过模拟此火焰的流体,将一个特定时刻的结果保存在此文件中。此数据集由 Philip Rubini 博士提供 (当时 Rubini 博士在 Cranfield 大学)。同时提供了一个 VRML 文件,显示火焰被取走的房间情况。
启动 mayavi2,选择 File->Load data->Open file 来载入数据。再次在左边的树形显示中看到一个节点,但在 TVTK 场景中没有任何显示。此数据集在一个文件中包含了不同的标量和向量数据。如果选择左边的 VTK XML file... 节点,在对象编辑器中将配置读入器(reader)。在其中,可以看到此数据文件中所有标量和向量的下拉列表。任意选择其中一个。
按照前面所述,使用 Outline 模块建立数据的轮廓。建立 IsoSurface 模块以查看数据的 iso-曲面。也请试试 ScalarCutPlane 模块。
单击 Colors and legends 节点,选中 Show scalar bar,显示映射颜色的标尺(通过查找表(Look up table)将标量映射为颜色)。试试不同的默认颜色映射。
现在单击 VTK XML file ... 并选择不同的标量来查看数据如何变化。当标量改变时,图例将自动更新。
此数据也包括向量。标量数据有 u,v和 w,但没有速度的大小。假设我们希望查看速度大小的 iso-曲面,可以使用 ExtractVectorNorm 过滤器。选择 Visualize->Filters->Extract Vector Norm 菜单可以使用此过滤器。
如果现在建立 ScalarCutPlane,可以在 ExtractVectorNorm 节点下看到 Colors and legends 节点。这个标量剖面用颜色显示此过滤器生成的速度大小。可以将 iso-曲面模块从另一个 Colors and legends 节点下拖到此 Colors and legends 节点下,使得生成的 Iso-曲面 是关于速度大小的,而不是关于所选的标量。
注意:左边的显示树表示如下的数据流动管道, source -> filter -> modules。本质上是数据从父节点流到其下的子节点。
现在如果你想在管道的不同分支进行可视化,例如你想查看温度数据的 iso 曲面,必须单击模块或源对象(VTK XML File ... 节点)本身,然后选择菜单项。当选择了显示树中的一项,此项目成为当前对象,其后选择的菜单项将在当前对象下建立新模块/滤波器。
可以过滤"已经过滤的数据"。选择 ExtractVectorNorm 节点使其成为当前对象。现在通过 Visualize->Filters->Threshold 建立 Threshold 滤波器。然后在对象编辑器中设置上限和下限,例如 0.5 和 3.0。如果在这里建立 VectorCutPlane 模块,并且移动此剖面,应该能看到箭头,但是只有位于上下限之间的箭头。因此可以使用这样的步骤建立很复杂的可视化管道。
有几个向量模块:VectorCutPlane,Vectors,WarpVectorCutPlane和Streamlines。如果查看流线(streamline),mayavi 将产生数据集中向量的流线。为了查看初始数据集的流线,可以单击原先的 Outline 模块(或数据源),然后选择 Streamline 菜单项。可以使用3D小部件移动屏幕上不同类型的种子(seed)。这些位置的种子点(seed point)用来跟踪流线。球(Sphere)、线和平面源可以用来初始化流线种子。
选择 File->Open->VRML2 file 菜单项打开 VRML 文件``room_vis.wrl``,可以查看着火的房间。
建立起复杂的可视化管道后,想将其保存下来以便以后再查看,可以通过 File->Save Visualization 菜单项保存整个可视化。可以使用 File->Load Visualization 菜单项载入保存后的文件。此选项并不是100%鲁棒,仍在实验阶段。后续版本将改善此功能。毕竟,此功能暂时可以使用。
再次说明,此例中的可视化是使用用户界面生成的,但可以完全使用 Python 脚本完成。一个简单的脚本 examples/streamline.py
演示了几个上面的模块。用户可以研究一下此文件。可按照如下方式运行此脚本:
$ cd examples
$ python streamline.py
或者:
$ mayavi2 -x streamline.py
从此例可以看到,编写脚本使用 mayavi 进行可视化是很简单的。下面是此脚本生成的图形。