[英]Reading and plotting VTK file data structure with python
I have a VTK file (unstructured grid) with points
and cells
.我有一个带有
points
和cells
格的 VTK 文件(非结构化网格)。
I can import the file and read it into using the meshio python package.我可以导入文件并使用meshio python 包将其读入。
If I type the command mesh.cells
I see a dictionary called 'hexahedron'
with an array made up of lists inside like this:如果我输入命令
mesh.cells
我会看到一个名为'hexahedron'
的字典,里面有一个由列表组成的数组,如下所示:
{'hexahedron': array([[ 0, 162, 185, ..., 163, 186, 23],
[162, 329, 351, ..., 330, 352, 186],
[329, 491, 514, ..., 492, 515, 352],
...,
[483, 583, 600, ..., 584, 601, 490],
[583, 650, 656, ..., 651, 657, 601],
[650, 746, 762, ..., 747, 763, 657]])}
I would like to plot this in matplotlib (I know ParaView is an alternative, which I've been using, but I would also like to use matplotlib for this at the moment).我想在 matplotlib 中绘制它(我知道 ParaView 是一种替代方法,我一直在使用它,但目前我也想为此使用 matplotlib)。 Anyways, I'm having trouble wrapping my head around the structure.
无论如何,我无法将头环绕在结构上。
There are 8 data points in each list.每个列表中有 8 个数据点。
If I run the command mesh.points
I get an array of lists of x, y, z
coordinates, which makes sense.如果我运行命令
mesh.points
我会得到一个包含x, y, z
坐标列表的数组,这是有道理的。 However, with the hexahedron, are there also x, y, z
coordinates in the list?但是,对于六面体,列表中是否也有
x, y, z
坐标? It would make more sense if there were lists of x, y, z
coordinates, as that would make up polygons.如果有
x, y, z
坐标列表会更有意义,因为这将构成多边形。
I've seen this thread , but I'm still stuck on understanding this. 我看过这个帖子,但我仍然坚持理解这一点。
Attached is the VTK file , as well as what it looks like in ParaView. 附件是 VTK 文件,以及它在 ParaView 中的样子。 Thanks!
谢谢!
tl;dr: I don't think you should try to use matplotlib for this, and it would be difficult and not work very well. tl;dr:我认为您不应该为此尝试使用 matplotlib,这会很困难并且效果不佳。 I suggest using a dedicated vtk library, either bare
vtk
, the higher-level mayavi.mlab
or my recently acquired favourite, pyvista
.我建议使用专用的 vtk 库,可以是裸
vtk
、更高级别的mayavi.mlab
或我最近获得的最喜欢的pyvista
。 I'll elaborate on all this in detail.我将详细说明这一切。
First, here is a small, self-contained version of your input data (since the data you linked in the question is both too large and likely to become a broken link sooner or later).首先,这是您输入数据的一个小的、自包含的版本(因为您在问题中链接的数据既太大又可能迟早会成为断开的链接)。 I've reduced your data to three rectangular cuboids of varying sizes to approximate your figure.
我已将您的数据减少到三个不同大小的矩形长方体以近似您的数字。
# vtk DataFile Version 3.1
MCVE VTK file
ASCII
DATASET UNSTRUCTURED_GRID
POINTS 16 float
0. 0. 0.
0. 0. 3.
0. 2. 0.
0. 2. 3.
4. 0. 0.
4. 0. 3.
4. 2. 0.
4. 2. 3.
5. 0. 0.
5. 0. 3.
5. 2. 0.
5. 2. 3.
13. 0. 0.
13. 0. 3.
13. 2. 0.
13. 2. 3.
CELLS 3 27
8 0 1 3 2 4 5 7 6
8 4 5 7 6 8 9 11 10
8 8 9 11 10 12 13 15 14
CELL_TYPES 3
12 12 12
CELL_DATA 3
SCALARS elem_val float
LOOKUP_TABLE default
1
2
3
Let's discuss what this file represents.让我们讨论一下这个文件代表什么。 The header specifies that it's an unstructured grid.
标题指定它是一个非结构化网格。 This means it can contain points arranged in any kind of arbitrary manner.
这意味着它可以包含以任意任意方式排列的点。 Basically a bag of points.
基本上是一袋积分。 You can find some explanation about the file format here .
您可以在此处找到有关文件格式的一些说明。
The first block, POINTS
, contains the 16 float
rows, each row corresponds to coordinates of a point in 3d, 16 points in total.第一个块
POINTS
包含16 float
行,每行对应 3d 中一个点的坐标,共 16 个点。
The second block, CELLS
, defines 3 rows, each row corresponding to a cell (smaller unit, in this case volume) defined in terms of the 0-based indices of the points.第二个块
CELLS
定义了 3 行,每行对应于根据点的基于 0 的索引定义的单元格(较小的单位,在本例中为体积)。 The first number ( 8
) indicates the number of vertices in the given cell, the following numbers are the point indices for the corresponding vertices.第一个数字 (
8
) 表示给定单元格中的顶点数,以下数字是相应顶点的点索引。 All three cells in the above example data file consist of 8 vertices, since each cuboid we'll want to draw has 8 vertices.上面示例数据文件中的所有三个单元格都包含 8 个顶点,因为我们要绘制的每个长方体都有 8 个顶点。 The second number on the
CELLS
line is the total number of numbers in this block, ie 3 * (8+1)
, ie 27. CELLS
行的第二个数字是这个区块的数字总数,即3 * (8+1)
,即 27。
The third block, CELL_TYPES
, defines the kind of cell for each of the 3
cells.第三个块
CELL_TYPES
定义了3
单元格中的每个单元格的类型。 In this case all of them are type 12
, which corresponds to "hexahedrons".在这种情况下,它们都是类型
12
,对应于“六面体”。 An informative figure borrowed from Fig. 2 and 3 of the already linked examples : 从已经链接的示例的图 2 和 3 中借用的信息图:
These list the main kinds of cell types and their respective indices.
这些列出了细胞类型的主要种类及其各自的索引。
The last block, SCALARS
, contains a scalar (number) for each cell according to which it will get coloured later.最后一个块
SCALARS
包含每个单元格的标量(数字),稍后将根据该标量着色。 The scalars 1
through 3
will be mapped onto a colormap to give you the red-to-blue transition seen in your figure.标量
1
到3
将被映射到颜色图上,为您提供图中看到的红色到蓝色的过渡。
I'm not familiar with meshio
but I suspect it gives you access the the aforementioned blocks in the VTK file.我不熟悉
meshio
但我怀疑它可以让您访问 VTK 文件中的上述块。 The mesh.cells
attribute you showed suggests that it recognizes that every cell is a "hexahedron", and lists every cell and their respective 8 vertex indices.您显示的
mesh.cells
属性表明它识别每个单元格都是“六面体”,并列出每个单元格及其各自的 8 个顶点索引。 The mesh.points
attribute is probably an array of shape (n,3)
, in which case mesh.points[cell_inds, :]
gives you the (8,3)
-shaped coordinates of a given cell defined by its 8-length array cell_inds
. mesh.points
属性可能是一个形状为(n,3)
的数组,在这种情况下, mesh.points[cell_inds, :]
为您提供由其 8 长度数组定义的给定单元格的(8,3)
形坐标cell_inds
。
How would you visualize this with matplotlib?您将如何使用 matplotlib 将其可视化? Firstly, your actual data is huge, it contains 84480 cells, even though from afar they look quite like my example data above.
首先,您的实际数据很大,它包含 84480 个单元格,尽管从远处看它们看起来很像我上面的示例数据。 So you'd have to
所以你必须
All these things considered, I would definitely not try to use matplotlib for this.考虑到所有这些事情,我绝对不会尝试为此使用 matplotlib。
Use what ParaView uses under the hood: VTK!使用 ParaView 在幕后使用的东西:VTK! You can still use the machinery programmatically either via the low-level
vtk
module or the high(er)-level mayavi.mlab
module.您仍然可以通过低级
vtk
模块或高级 (er) 级mayavi.mlab
模块以编程方式使用机器。 There's also the mayavi
-related tvtk
module which is sort of a middle-ground (it's still low-level VTK for these purposes, but with a more python-friendly API), but I'll leave that as an exercise to the reader.还有与
mayavi
相关的tvtk
模块,它是一种中间地带(对于这些目的,它仍然是低级 VTK,但具有更对 Python 友好的 API),但我将把它作为练习留给读者。
vtk
vtk
Reading and plotting an unstructured grid with vtk is a bit complicated (as it always is with bare vtk, since you have to assemble the pipeline yourself), but manageable using this ancient wiki page plus these corrections that have changed since :使用 vtk 读取和绘制非结构化网格有点复杂(因为使用裸 vtk 总是如此,因为您必须自己组装管道),但可以使用这个古老的 wiki 页面以及自以下以来发生变化的这些更正来进行管理:
from vtk import (vtkUnstructuredGridReader, vtkDataSetMapper, vtkActor,
vtkRenderer, vtkRenderWindow, vtkRenderWindowInteractor)
file_name = "mesh_mcve.vtk" # minimal example vtk file
# Read the source file.
reader = vtkUnstructuredGridReader()
reader.SetFileName(file_name)
reader.Update() # Needed because of GetScalarRange
output = reader.GetOutput()
output_port = reader.GetOutputPort()
scalar_range = output.GetScalarRange()
# Create the mapper that corresponds the objects of the vtk file
# into graphics elements
mapper = vtkDataSetMapper()
mapper.SetInputConnection(output_port)
mapper.SetScalarRange(scalar_range)
# Create the Actor
actor = vtkActor()
actor.SetMapper(mapper)
# Create the Renderer
renderer = vtkRenderer()
renderer.AddActor(actor)
renderer.SetBackground(1, 1, 1) # Set background to white
# Create the RendererWindow
renderer_window = vtkRenderWindow()
renderer_window.AddRenderer(renderer)
# Create the RendererWindowInteractor and display the vtk_file
interactor = vtkRenderWindowInteractor()
interactor.SetRenderWindow(renderer_window)
interactor.Initialize()
interactor.Start()
Note that I've only minimally changed the original wiki version.请注意,我只对原始 wiki 版本进行了最低限度的更改。 Here's the output after some rotation of the viewport:
这是视口旋转后的输出:
The actual colour depends on the default colormap and the scaling of the scalars.实际颜色取决于默认颜色图和标量的缩放。 The above default of the
vtk
module seems to use the jet
colormap by default, and it normalizes the scalars so that the values are mapped to the complete colour range. vtk
模块的上述默认值似乎默认使用jet
颜色图,并且它对标量进行了标准化,以便将值映射到完整的颜色范围。
mayavi.mlab
mayavi.mlab
Personally, I find vtk
to be a huge pain to use.就个人而言,我发现
vtk
使用起来非常痛苦。 It involves a lot of searching, and more often than not digging in the labyrinth of submodules and classes defined in the library.它涉及大量的搜索,而且通常是在库中定义的子模块和类的迷宫中挖掘。 This is why I always try to use
vtk
via the higher-level functionality of mayavi.mlab
instead.这就是为什么我总是尝试通过
mayavi.mlab
的更高级别功能来使用vtk
。 This module is especially useful when you're not working with VTK files (like when trying to visualize data that is defined in numpy arrays), but it happens to spare us a lot of work in this case as well, while providing additional functionality.当您不使用 VTK 文件时(例如尝试可视化在 numpy 数组中定义的数据时),此模块特别有用,但在这种情况下,它恰好也为我们节省了大量工作,同时提供了附加功能。 Here's the same visualization using
mlab
:这是使用
mlab
的相同可视化:
from mayavi import mlab
from mayavi.modules.surface import Surface
file_name = "mesh_mcve.vtk" # minimal example vtk file
# create a new figure, grab the engine that's created with it
fig = mlab.figure()
engine = mlab.get_engine()
# open the vtk file, let mayavi figure it all out
vtk_file_reader = engine.open(file_name)
# plot surface corresponding to the data
surface = Surface()
engine.add_filter(surface, vtk_file_reader)
# block until figure is closed
mlab.show()
Much less work!工作量少得多! We pushed the entire VTK parsing monstrosity onto
mayavi
, along with the mess of mappers and actors and renderers and ...我们将整个 VTK 解析怪物推到了
mayavi
,以及映射器、演员和渲染器的混乱以及......
The above is a minimal, least-effort visualization, but from here of course you can start changing whatever you like to make it fit your needs.以上是一个最小的、最省力的可视化,但从这里当然你可以开始改变你喜欢的任何东西,使其适合你的需求。 You can change the background, change the colormap, manipulate the data in weird ways, you name it.
您可以更改背景,更改颜色图,以奇怪的方式操作数据,您可以命名。 Note that the colours here are reversed compared to the
vtk
case, since either the default colormap or the mapping of scalars to the colormap (the lookup table) is different.请注意,与
vtk
情况相比,此处的颜色是相反的,因为默认颜色图或标量到颜色图(查找表)的映射是不同的。 The more you stray from the high-level API of mlab the dirtier it gets (since you're getting closer and closer to the bare VTK under the hood), but you can usually still spare a lot of work and obfuscated code with mayavi
.您越远离 mlab 的高级 API,它就会变得越脏(因为您离引擎盖下的裸 VTK 越来越近),但您通常仍然可以使用
mayavi
大量工作和混淆代码。
Finally, mayavi
's figure window supports all sorts of gems: interactive modification of the pipeline and scene, annotations such as coordinate axes, toggling orthogonal projections, and even being able to record anything you change interactively in auto-generated python scripts.最后,
mayavi
的图形窗口支持所有类型的宝石:管道和场景的交互式修改、坐标轴等注释、切换正交投影,甚至能够在自动生成的 Python 脚本中记录您交互式更改的任何内容。 I would definitely suggest trying to implement what you want to do using mayavi.我肯定会建议尝试使用 mayavi 来实现您想做的事情。 If you know what you'd do with ParaView, it's fairly easy to port that over to
mayavi
by making use of its interactive session recording feature.如果你知道你会用 ParaView 做什么,那么通过使用它的交互式会话记录功能将它移植到
mayavi
是相当容易的。
pyvista
pyvista
I've recently been pointed to pyvista
which is a delightfully versatile and powerful library built on top of vtk
.我最近被指出
pyvista
是一个构建在vtk
之上的令人愉快的多功能和强大的库。 Although its API needs some getting used to, there are plenty of examples and an exhaustive API reference in the documentation .尽管它的 API 需要一些习惯,但文档中有大量示例和详尽的 API 参考。 There's a bit of a learning curve to get started with the library, but you might find that you're way more productive using its high-level interface and "do what I mean" mechanics.
开始使用该库需要一些学习曲线,但您可能会发现使用其高级界面和“按我的意思做”机制会更有效率。 I especially appreciate its open-source nature complete with public issue tracker and responsive core developers.
我特别欣赏它的开源性质,包括公共问题跟踪器和响应式核心开发人员。
So how can we read and plot the grid with pyvista
?那么我们如何使用
pyvista
读取和绘制网格呢? Here goes:开始:
import pyvista as pv
# read the data
grid = pv.read('mesh_mcve.vtk')
# plot the data with an automatically created Plotter
grid.plot(show_scalar_bar=False, show_axes=False)
As you can see the colours are very different: this is because pyvista
uses matplotlib's perceptually uniform viridis colormap , which is great for data visualization!如您所见,颜色非常不同:这是因为
pyvista
使用了 matplotlib 的感知统一的viridis 颜色图,这对于数据可视化非常pyvista
! If you insist on the weirder colours you can pass cmap='jet'
to the call to grid.plot
.如果您坚持使用更奇怪的颜色,您可以将
cmap='jet'
传递给对grid.plot
的调用。 There's a lot to be said how the default lighting and shading is different here, but I suggest perusing the documentation about all the options and ways to filter and plot datasets.这里有很多要说的默认照明和阴影的不同之处,但我建议仔细阅读有关过滤和绘制数据集的所有选项和方法的文档。
Let me also draw your attention to让我也提请你注意
vtkplotter
vtkplotter
which has a different approach, also built on top of vtk
:它有一种不同的方法,也建立在
vtk
之上:
from vtkplotter import *
# read the data
ugrid = loadUnStructuredGrid("mesh_mcve.vtk")
# create the outline of the data as polygonal mesh and show it
Mesh(ugrid).c('viridis').alpha(1.0).show()
Plenty of examples can be found here along with API documentation .可以在此处找到大量示例以及 API文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.