简体   繁体   English

用python读取和绘制VTK文件数据结构

[英]Reading and plotting VTK file data structure with python

I have a VTK file (unstructured grid) with points and cells .我有一个带有pointscells格的 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!谢谢! Paraview 的屏幕截图,带有三个不同颜色的条带

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.我将详细说明这一切。

The data数据

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 中借用的信息图: 线性细胞类型图,12对应六面体 非线性细胞类型图 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.标量13将被映射到颜色图上,为您提供图中看到的红色到蓝色的过渡。

Why not matplotlib?为什么不使用 matplotlib?

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所以你必须

  1. come up with a way to turn all these cell coordinates into surfaces to be plotted with matplotlib, which wouldn't be easy,想出一种方法将所有这些单元格坐标转换为要使用 matplotlib 绘制的曲面,这并不容易,
  2. then realize that 80k surfaces will lead to enormous memory and CPU overhead in matplotlib, finally然后意识到 80k 个表面将导致 matplotlib 中巨大的内存和 CPU 开销,最后
  3. notice that matplotlib has a 2d renderer, so 3d visualization of complex (read: disjoint, interlocking) surfaces often goes awry .请注意,matplotlib 具有 2d 渲染器,因此复杂(读取:不相交、互锁)表面的 3d 可视化经常出错

All these things considered, I would definitely not try to use matplotlib for this.考虑到所有这些事情,我绝对不会尝试为此使用 matplotlib。

What then?然后怎样呢?

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),但我将把它作为练习留给读者。

1. vtk 1. 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:这是视口旋转后的输出:

使用 vtk 模块输出,带有红色、绿色和蓝色条纹的条形图

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颜色图,并且它对标量进行了标准化,以便将值映射到完整的颜色范围。

2. mayavi.mlab 2. 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 ,以及映射器、演员和渲染器的混乱以及......

Here's how it looks:这是它的外观: 用 mlab 输出,类似的三色条,但颜色顺序相反

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是相当容易的。

3. pyvista 3. 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)

This produces这产生用 pyvista 输出,同样是一个带有三条纹的条形,但现在它们是紫绿色黄色

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让我也提请你注意

4. vtkplotter 4. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM