三流Mayavi操作-Mayav-2.1.4-surf、contour_surf、contour3d绘制

秉着边学边写边折腾的原则,开始粗糙的工作。真正掌握还是得讲解给别人听。 先给出网课
https://www.icourse163.org/course/BIT-1001871001
Mayavi官方
http://docs.enthought.com/mayavi/mayavi/genindex.html
(有时候这网站会装死,一般过几个小时就会活过来)
我发现了,光是三流操作还不够,还得加上四流翻译。

这一章主要讲surfcontour_surfcontour3d绘制
先说surf,因为经常要用,而且前面提到过,说起来方便。然后contour_surf,最后是contour3d

1.surf和contour_surf

官方实例,官方也是很友善,把代码合并在一起了。

import numpy as np
from mayavi.mlab import *
def f(x, y):
    sin, cos = np.sin, np.cos
    return sin(x + y) + sin(2 * x - y) + cos(3 * x + 4 * y)
x, y = np.mgrid[-7.:7.05:0.1, -5.:5.05:0.05]
surf(x, y, f)
contour_surf(x, y, f)
show()

以下是效果图

在这里插入图片描述
官方还是很良心的制作了一个,第一个图是surf第二个是contour_surf最后那个是两个合并的可视化,这么做不好,因为是我干的,为了省事。
其实我只是想说,两者可以叠加,管线会出现两个层级,还可以继续叠加outline

前面说了meshsurf的区别,在于绘制的网格的不同,这里再说一次,mesh的绘制方式是三角形网格,surf是规整的网格

在这里插入图片描述

surf实际是正交,我在这里增设了一个面,这个面是整个绘制范围,并设置了opacity,是不是秒懂。(我这里的面设置的高度是1,角度看起来就有点奇怪,设0会好点)

在这里插入图片描述

对于surfcontour_surf的简单介绍如下:

surf:Plots a surface using regularly-spaced elevation data supplied as a 2D array.
contour_surf:Plots a the contours of a surface using grid-spaced data for elevation supplied as a 2D array.

利用形如2Darray的高程数据绘制具有规整网格的平面
语法如下(两者语法相同)

surf(s, ...)
surf(x, y, s, ...)
surf(x, y, f, ...)

详细说明(也是相同的,措辞微微调整了一下,这里给出surf(s, ...)的全文翻译(误))

s is the elevation matrix, a 2D array, where indices along the first array axis represent x locations, and indices along the second array axis represent y locations.
.
x and y can be 1D or 2D arrays such as returned by numpy.ogrid or numpy.mgrid. Arrays returned by numpy.meshgrid require a transpose first to obtain correct indexing order. The points should be located on an orthogonal grid (possibly non-uniform). In other words, all the points sharing a same index in the s array need to have the same x or y value. For arbitrary-shaped position arrays (non-orthogonal grids), see the mesh function.
.
If only 1 array s is passed, the x and y arrays are assumed to be made from the indices of arrays, and an uniformly-spaced data set is created.
If 3 positional arguments are passed the last one must be an array s, or a callable, f, that returns an array. x and y give the coordinates of positions corresponding to the s values.

s是一个高程矩阵,2维array的形式,其中第一个位置代表x轴,第二个位置是y轴。
.
x,y可以是由numpy.ogrid或者numpy.mgrid初始的1维或者2维array.为了得到正确的索引顺序,被numpy.meshgrid返回的array的第一个array会发生转置.这些点会被放置在正交网格上(可能不均匀).s中的每一个值所匹配x,y的坐标应该具备相同的索引.对于不规则的array而言(非正交网格),可以参考mesh.
.
可以只传递1个参数s,x,y的索引已经预设好,这时就创建了一个等间距的数据集。
也可以传递3个参数,最后一个参数必须是一个array,或者是一个可返回的f表达式,且返回的类型也是array,s值的坐标由前两个参数x,y给出。
.
contour_surf

s is the elevation matrix, a 2D array. The contour lines plotted are lines of equal s value.
.
x and y can be 1D or 2D arrays (such as returned by numpy.ogrid or numpy.mgrid), but the points should be located on an orthogonal grid (possibly non-uniform). In other words, all the points sharing a same index in the s array need to have the same x or y value. For arbitrary-shaped position arrays (non-orthogonal grids), see the mesh function.
.
If only 1 array s is passed, the x and y arrays are assumed to be made from the indices of arrays, and an uniformly-spaced data set is created.
.
If 3 positional arguments are passed the last one must be an array s, or a callable, f, that returns an array. x and y give the coordinates of positions corresponding to the s values.

官方实例用的就是三个参数的形式.先离散再用绘制,surfcontour_surf传参方式相同。
x, y = np.mgrid[-7.:7.05:0.1, -5.:5.05:0.05]
surf(x, y, f)

然后呢,我想提一下管线

在这里插入图片描述
surfcontour_surf的配置很相似,上面是surf下面是contour_surf
surf多了一层PolyDataNormals,这里先把问题抛出来,然后讲一点管线。

为什么在这里要讲一下管线配置,因为官方用的就是surf做的例子,满满的幸福感,全程翻译。

The plotting functions reviewed above explore only a small fraction of the visualization possibilities of Mayavi. The full power of Mayavi can only be unleashed through the control of the pipeline itself. As described in the An overview of Mayavi section, a visualization in Mayavi is created by loading the data in Mayavi with data source object, optionally transforming the data through Filters, and visualizing it with Modules. The mlab functions build complex pipelines for you in one function, making the right choice of sources, filters, and modules, but they cannot explore all the possible combinations.

前面涉及到的绘图函数只探索了Mayavi可视化的一小部分.只有通过管线配置才能充分发挥Mayavi的全部效果。在 An overview of Mayavi章节的叙述中,Mayavi 可以通过配置数据源来创建可视化实例,在这个过程中,可以使用Filters任意变换数据,并通过 Modules进行可视化。mlab函数可以用一条命令生成复杂的管线,并配置正确的数据源sources, filters, 和 modules,但是他们无法同时探索所有的可能正确的组合形式。
.
Mlab provides a sub-module pipeline which contains functions to populate the pipeline easily from scripts. This module is accessible in mlab: mlab.pipeline, or can be import from mayavi.tools.pipeline.
Mlab提供一个子模块管线,它包含很多用于配置管线的函数,通过脚本可以轻易实现。这个模块可以在mlab中引用,通过mlab.pipeline或者mayavi.tools.pipeline
.
When using a mlab plotting function, a pipeline is created: first a source is created from numpy arrays, then modules, and possibly filters, are added. The resulting pipeline can be seen for instance with the mlab.show_pipeline command. This information can be used to create the very same pipeline directly using the pipeline scripting module, as the names of the functions required to create each step of the pipeline are directly linked to the default names of the objects created by mlab on the pipeline. As an example, let us create a visualization using surf():
当调用mlab函数的时候,一条pipeline管线已经创建好了:首先是由numpy arrays初始的source,然后是modules,可能中间还会有filters。最后生成的pipeline管线可以被mlab.show_pipeline命令显示出来。通过pipeline管线的脚本模块,这些信息可以用来创建相同的管线,根据名称,可以直接通过object对象的默认名,直接创建管线的每一步配置。作为例子,我们可以用surf()做可视化:

.

import numpy as np
a = np.random.random((4, 4))
from mayavi import mlab
mlab.surf(a)
mlab.show_pipeline()

The same pipeline can be created using the following code:
相同的管线,也可以用以下代码进行创建

import numpy as np
a = np.random.random((4, 4))
from mayavi import mlab
src = mlab.pipeline.array2d_source(a)
warp = mlab.pipeline.warp_scalar(src)
normals = mlab.pipeline.poly_data_normals(warp)
surf = mlab.pipeline.surface(normals)

The following pipeline is created:
Array2DSource
—— WarpScalar
————PolyDataNormals
——————Colors and legends
———————— Surface
在这里插入图片描述

这里不敢展开太细,简单说一下
numpy创建的4X4,2Darray经过Array2DSource构建了数据源Sources,到达Filters层级WarpScalarFilters用于数据变换,PolyDataNormals也是Filters的一种,也试数据变换,用于计算法线数据。到最后Modules可视化层级,Colors and legends LUT配色方案,Surface用于绘制平面

这个并没有展开说各个层级的具体内容,怎样构建,后面来填坑。

多提醒一句,就是同属于Filter层级的WarpScalarPolyDataNormals仍然可以连续建立,还可以多次变换。
.

然后再回到管线讲解之前的内容。
surfcontour_surf多了一层Filters,多做了一次PolyDataNormals数据变换。
这里还得留一个坑,我并没有发现这一层的具体细节,我删除掉contour_surf,在PolyDataNormals之前创建Surface也能达到同样的效果,这是显然的。

在这里插入图片描述

隐藏掉PolyDataNormals层下的Surface,直接可视化WarpScalarSurface,也就是少一层PolyDataNormals数据变换,图像进行对比,还是有细微差别的。

在这里插入图片描述
左图是经过PolyDataNormals数据变换之后的图像细腻一些。
再仔细一点可以想到,左图出现马赛克的地方全是网格绘制走过的地方,这些点的标量值是离散的!是可以确定的值,而这些光滑的地方的数据都是不存在的!可能做了插值,看下图。
在这里插入图片描述

我对比过两个Surface里面的设置只有Actor中有设置,而且还全是一样的,Colors and legends的设置也是一毛一样的。经过一层一层向上对比,找到了PolyDataNormals里面。

在这里插入图片描述

最后在Compute point normals上发现了,去掉之后就变成了马赛克。。上面两个选项,Auto orient normalsCompute cell normals对马赛克都有一定的削弱作用,可能采用不同的算法。
Mayavi文档中也没有对它过多说明,一笔带过,可能要去VTK看看。

Computes normals from input data. This gives meshes a smoother appearance. This should work for any input dataset.

简单来说就是用一层Filter把网格处理得平滑一点。

根本问题还是,我不知道PolyDataNormals到底干了什么。

到此为止surfcontour_surf是基本说完了。
不知道有没有这样的感觉,surfcontour_surf的配置是很简单的,所有的中间管线都被mlab做好了。
我们至少三种绘图写法:

第一种是直接用mlab绘图函数进行,这样做的好处是中间的管线不需要一步一步进行配置,而是直接由mlab选择默认配置一步到位,很是节约代码。需要一些特殊效果的时候,再手动去设置它的pipeline管线。但这样做是缺陷的,有一些设置并不能完成,比如刚才出现了一个PolyDataNormals,它的设置并没有在图形界面中,只能从代码对层面进行配置。另外如果规模大了,手动是一件很费力的事情。
.
所以就有了第二种,用mlab直接建立完整的管线,用代码微整它的pipeline管线配置,但是同样有缺陷,有一些更底层的细节无法实现。
.
进而就有了第三种,从pipeline管线一层一层配置,能发挥它的全部威力,好处不用说了,不好处就是比较麻烦。
.
最后就是,要回到VTK了,更麻烦,但也更强大。毕竟是Mayavi它老爹。

2.contour3d

官方实例,老规矩,+np+show…

import numpy as np
from mayavi.mlab import *
x, y, z = np.ogrid[-5:5:64j, -5:5:64j, -5:5:64j]
scalars = x * x * 0.5 + y * y + z * z * 2.0
contour3d(scalars, contours=4, transparent=True)
show()

然后是这个东西

在这里插入图片描述

这次的代码已经有一些变化了,用到了ogrid,正愁没地方说ogrid。刚好,一锅端了,上次说过了mgrid,入口2.1.2

这次说一下ogrid在文末。

Mayavi绘图常用的技巧

中间的这个小细节说完了,然后又回到contour3d本身是干嘛的讨论来。
估计也看出来了,绘制的是等值面。分别设置contours为4、6、8、10、40、100之后的图。

在这里插入图片描述

.官方文档的解释

Plots iso-surfaces for a 3D volume of data suplied as arguments.
为三维数据绘制等值面。

语法

contour3d(scalars, ...)
contour3d(x, y, z, scalars, ...)

详细解释

scalars is a 3D numpy arrays giving the data on a grid.
.
If 4 arrays, (x, y, z, scalars) are passed, the 3 first arrays give the position, and the last the scalar value. The x, y and z arrays are then supposed to have been generated by numpy.mgrid, in other words, they are 3D arrays, with positions lying on a 3D orthogonal and regularly spaced grid with nearest neighbor in space matching nearest neighbor in the array. The function builds a scalar field assuming the points are regularly spaced.
.
空间网格的数据scalars可由numpy初始化的三维array给定。
.
如果传递的参数是4个array(包括x,y,z,scalars),前三个array给定空间位置,最有一个指定scalars标量值,x,y,z的array应由numpy.mgrid初始化,换言之,他们应当是一个3D的array,并且规整而且正交的空间网格上就近匹配。给定的空间点是规整的前提之下,这个函数可以建立一个标量场。

通过设置representation=points到这里可以很清晰地看到空间点了。

在这里插入图片描述

以下是我的理解(可能有误)

可能你也看出来了,surfcontour_surfcontour3d是完全不同的,surfcontour_surf的数据主要还是面,设置方式还是在xoy平面上确定坐标值并展示另一个数据,也就是离散了两个值,分别对x、y坐标取了步长,而contour3d就不同了,它的数据,要取三个步长,离散了xyz三个坐标值,最后是有另外一个用来显示颜色的是标量值。
.
而如果要将空间点连接起来,并不是一件容易的事情,连接方式并不是任意的,而是一需要指定一些方式。和以往的面绘制不太一样,面绘制的时候,空间上的点连接有些是隐性有些是显性,但是说到底,他们还是连接了,区别于根据绘制的不同来确定是否指定绘制方式。但是空间中的点,连接是否有必要,这个我也一直在想。首先要回答的是为什么要连接?其次才能回答,怎样连接。像这个图,绘制的图像是是等值面,那么连接方式是可以确定的。如果你要规定不同的连接方式也是可以的,那么就需要构建新的算法,这是我个人想法。
.
就目前来看,对于空间中的一个点的描述,除了3个坐标位置,这个位置的标量值之外,还有这个位置的矢量信息,从而有需要新的函数和数据进行矢量可视化。后面会专门来说

从管线再说一下。

这个管线和上面还是不太一样的.对于上面的surfcontour_surf它们的层级末端Module对应的是Surfacecontour3d的层级末端对应的是IsoSurface
IsoSurface
这里有一个例子

A module that allows the user to make contours of input volumetric data.
该模块使用户可以使用空间数据绘制等值面。

到这里为止,对比两个Module的具体设置也不尽相同。

在这里插入图片描述
对于IsoSurface针对的对象是三维数据,是体绘制对象
而对于Surface的对象是面绘制

3.surf、contour_surf、contour3d的参数

这三个绘制函数的9个共同参数不在这里说了。
在这里插入图片描述
需要说明一下的是,
surf其实是有contours但是这样做不如直接用contour_surf,如果仔细看了上面的说明,就会知道surf多了一个Filter层级计算,如果只绘制contours,这个层级就是多余的。因此可以忽略掉surfcontours
在上面的例子中已经给出了contour3dcontour_surf的例子,这里进行翻译,给出说明。

contours

Integer/list specifying number/list of contours. Specifying a list of values will only give the requested contours asked for.
接受的变量类型为int或者list.如果指定的参数值是list,则会按照list所要求的值进行绘制。

上面已经说过了contours的例子,用的是int,按照条数等距绘制,这里给出接受的值是list的例子,按照值分别绘制。
管线内部的变化
这里设置的contours=[-0.2,0,0.5],这就不是等距的等值线设置。
在这里插入图片描述
然后继续放大等值线,看看图
上面的图是contour3d,下面的图是contour_surf

在这里插入图片描述
.

mask

boolean mask array to suppress some data points. Note: this works based on colormapping of scalars and will not work if you specify a solid color using the color keyword.
这个至今是个历史悬疑。

representation

the representation type used for the surface. Must be ‘surface’ or ‘wireframe’ or ‘points’. Default: surface
representation类型用于绘制平面的类型。接受的参数为 ‘surface’ or ‘wireframe’ or ‘points’,且默认值为surface

这个不过多说明了,效果如下,从左到右 pointswireframesurface
在这里插入图片描述

warp_scale

scale of the z axis (warped from the value of the scalar). By default this scale is a float value. If you specify ‘auto’, the scale is calculated to give a pleasant aspect ratio to the plot, whatever the bounds of the data. If you specify a value for warp_scale in addition to an extent, the warp scale will be determined by the warp_scale, and the plot be positioned along the z axis with the zero of the data centered on the center of the extent. If you are using explicit extents, this is the best way to control the vertical scale of your plots. If you want to control the extent (or range) of the surface object, rather than its scale, see the extent keyword argument.
z轴的放缩系数。默认情况下scale是一个浮点数,如果指定为‘auto’,会得到一个自动适应图像的放缩率,它会根据边界范围给定一个合适的观测比例。如果为warp_scalar指定一个值,那么图像将会按照指定的值进行放缩,图像将沿着z轴定位,并且将数据的零点放置在中心。如果数据由明确的范围设定,这将是最好的方式来控制图像的纵向比例尺。如果你想控制的是数据的范围(Surface object),而不是它的比例尺,参考extent参数。

就目前为止这个参数还是第一次遇到,以前都没有提到过,所以这里说一下。
这个参数是contour3d不具备的,下面这个就是直接调整了标量值。
追加三行代码辅助来观察outline方便观察值域,xlabel观察量的变化

contour_surf(x, y,f,contours=15,warp_scale=0.1)
outline(color=(1,0,0),opacity=0.8,line_width=1.5)
xlabel('x')
在这里插入图片描述

一句话,warp_scale就是纵向压缩率。
说得虽然简单,但是细节还是麻烦看一下上方的文档。里面也是有细节的。

extent

[xmin, xmax, ymin, ymax, zmin, zmax] Default is the x, y, z arrays extent. Use this to change the extent of the object created.
[xmin, xmax, ymin, ymax, zmin, zmax] 默认值是x,y,z的范围,使用这个参数来改变object的范围。
.
当时我用的时候也疏忽了这一点,这个参数在使用的时候容易出错。
contour3d这个函数的两种语法contour3d(scalars, ...),contour3d(x, y, z, scalars, ...),我建议用后者,如果使用前者,得小心,因为contour3d(scalars, ...)只传入了一个scalars,并没有告知坐标位置,所以会默认从1开始每一个点取一个单位1,比如每个方向离散了64个点,就会取64的长度来画,得到64X64X64的空间。然后把每一个scalars指定到每一个点上

我举个栗子,正常情况下,这个图形应该是正方体的。

x, y, z = np.ogrid[-5:5:32j, -5:5:64j, -5:5:64j]
scalars = x * x * 0.5 + y * y + z * z * 2.0
mlab.contour3d(scalars,opacity=0.7,contours=6)

在这里插入图片描述

由于ogrid在各个方向离散的程度不同,而每一个间距都是确定的,所以绘制出来是一个长方体。而后期因为要追加xlabeloutline等一些辅助观测函数,看图,把所有的数据都带乱了。所以,这个时候要把xyz的坐标位置一起传进去。
注意这个时候,因为用ogrid会有维度错误,要用mgrid代码修改如下:
np.mgrid[-5:5:32j, -5:5:64j, -5:5:64j]
scalars = x * x * 0.5 + y * y + z * z * 2.0
mlab.contour3d(x,y,z,scalars,opacity=0.7,contours=6)

此后得到的图像就和坐标位置绑定了,虽然x方向的离散程度只有y和z的一半,但是因为坐标绑定了,他们个方向的点密度是不同的。然后添加outlinexlabel就没问题了。
所以真正的问题是出来数据源本身没有接收到xyz的位置。
在这里插入图片描述

再看看各个方向的点密度,可以选择更大的间距。

在这里插入图片描述

4.结尾

补充:

关于mgridogrid戳这里

文章给得挺详细的。
在这里插入图片描述

需要说的是,s[0],s[1],s[2]都是可进行运算的,例子中给得是自乘,其实s[0]也是可加减s[1]的

当进行加减运算的时候,会被铺设成空间矩阵。
当各边长都分成3份,想象一个边长为3的矩阵,3X3X3
x,y,z = np.ogrid[-5:5:3j,-5:5:3j,-5:5:3j]

x,y,z本身的维度是对不上的,但一旦相加,各项维度就出来了。

在这里插入图片描述

问题汇总:

1.各个层级的具体内容,怎样构建

这个内容很多,打算留链接,单独开一章。

2.PolyDataNormals这个怎么做到的,相关的资料。

更新时间

2018.10-10.——surfcontour_surf更完,contour3d开更,参数未更。
2018.10.11.——目录扩充、contour3d实例及配图
2018.10.12.——参数补充(更完)
2018.12.13.——补讲一个extent参数

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值