簡體   English   中英

用python讀取和繪制VTK文件數據結構

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

我有一個帶有pointscells格的 VTK 文件(非結構化網格)。

我可以導入文件並使用meshio python 包將其讀入。

如果我輸入命令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]])}

我想在 matplotlib 中繪制它(我知道 ParaView 是一種替代方法,我一直在使用它,但目前我也想為此使用 matplotlib)。 無論如何,我無法將頭環繞在結構上。

每個列表中有 8 個數據點。

如果我運行命令mesh.points我會得到一個包含x, y, z坐標列表的數組,這是有道理的。 但是,對於六面體,列表中是否也有x, y, z坐標? 如果有x, y, z坐標列表會更有意義,因為這將構成多邊形。

我看過這個帖子,但我仍然堅持理解這一點。

附件是 VTK 文件,以及它在 ParaView 中的樣子。 謝謝! Paraview 的屏幕截圖,帶有三個不同顏色的條帶

tl;dr:我認為您不應該為此嘗試使用 matplotlib,這會很困難並且效果不佳。 我建議使用專用的 vtk 庫,可以是裸vtk 、更高級別的mayavi.mlab或我最近獲得的最喜歡的pyvista 我將詳細說明這一切。

數據

首先,這是您輸入數據的一個小的、自包含的版本(因為您在問題中鏈接的數據既太大又可能遲早會成為斷開的鏈接)。 我已將您的數據減少到三個不同大小的矩形長方體以近似您的數字。

# 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
 

讓我們討論一下這個文件代表什么。 標題指定它是一個非結構化網格。 這意味着它可以包含以任意任意方式排列的點。 基本上是一袋積分。 您可以在此處找到有關文件格式的一些說明。

第一個塊POINTS包含16 float行,每行對應 3d 中一個點的坐標,共 16 個點。

第二個塊CELLS定義了 3 行,每行對應於根據點的基於 0 的索引定義的單元格(較小的單位,在本例中為體積)。 第一個數字 ( 8 ) 表示給定單元格中的頂點數,以下數字是相應頂點的點索引。 上面示例數據文件中的所有三個單元格都包含 8 個頂點,因為我們要繪制的每個長方體都有 8 個頂點。 CELLS行的第二個數字是這個區塊的數字總數,即3 * (8+1) ,即 27。

第三個塊CELL_TYPES定義了3單元格中的每個單元格的類型。 在這種情況下,它們都是類型12 ,對應於“六面體”。 從已經鏈接的示例的圖 2 和 3 中借用的信息圖: 線性細胞類型圖,12對應六面體 非線性細胞類型圖 這些列出了細胞類型的主要種類及其各自的索引。

最后一個塊SCALARS包含每個單元格的標量(數字),稍后將根據該標量着色。 標量13將被映射到顏色圖上,為您提供圖中看到的紅色到藍色的過渡。

為什么不使用 matplotlib?

我不熟悉meshio但我懷疑它可以讓您訪問 VTK 文件中的上述塊。 您顯示的mesh.cells屬性表明它識別每個單元格都是“六面體”,並列出每個單元格及其各自的 8 個頂點索引。 mesh.points屬性可能是一個形狀為(n,3)的數組,在這種情況下, mesh.points[cell_inds, :]為您提供由其 8 長度數組定義的給定單元格的(8,3)形坐標cell_inds

您將如何使用 matplotlib 將其可視化? 首先,您的實際數據很大,它包含 84480 個單元格,盡管從遠處看它們看起來很像我上面的示例數據。 所以你必須

  1. 想出一種方法將所有這些單元格坐標轉換為要使用 matplotlib 繪制的曲面,這並不容易,
  2. 然后意識到 80k 個表面將導致 matplotlib 中巨大的內存和 CPU 開銷,最后
  3. 請注意,matplotlib 具有 2d 渲染器,因此復雜(讀取:不相交、互鎖)表面的 3d 可視化經常出錯

考慮到所有這些事情,我絕對不會嘗試為此使用 matplotlib。

然后怎樣呢?

使用 ParaView 在幕后使用的東西:VTK! 您仍然可以通過低級vtk模塊或高級 (er) 級mayavi.mlab模塊以編程方式使用機器。 還有與mayavi相關的tvtk模塊,它是一種中間地帶(對於這些目的,它仍然是低級 VTK,但具有更對 Python 友好的 API),但我將把它作為練習留給讀者。

1. vtk

使用 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()

請注意,我只對原始 wiki 版本進行了最低限度的更改。 這是視口旋轉后的輸出:

使用 vtk 模塊輸出,帶有紅色、綠色和藍色條紋的條形圖

實際顏色取決於默認顏色圖和標量的縮放。 vtk模塊的上述默認值似乎默認使用jet顏色圖,並且它對標量進行了標准化,以便將值映射到完整的顏色范圍。

2. mayavi.mlab

就個人而言,我發現vtk使用起來非常痛苦。 它涉及大量的搜索,而且通常是在庫中定義的子模塊和類的迷宮中挖掘。 這就是為什么我總是嘗試通過mayavi.mlab的更高級別功能來使用vtk 當您使用 VTK 文件時(例如嘗試可視化在 numpy 數組中定義的數據時),此模塊特別有用,但在這種情況下,它恰好也為我們節省了大量工作,同時提供了附加功能。 這是使用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()

工作量少得多! 我們將整個 VTK 解析怪物推到了mayavi ,以及映射器、演員和渲染器的混亂以及......

這是它的外觀: 用 mlab 輸出,類似的三色條,但顏色順序相反

以上是一個最小的、最省力的可視化,但從這里當然你可以開始改變你喜歡的任何東西,使其適合你的需求。 您可以更改背景,更改顏色圖,以奇怪的方式操作數據,您可以命名。 請注意,與vtk情況相比,此處的顏色是相反的,因為默認顏色圖或標量到顏色圖(查找表)的映射是不同的。 您越遠離 mlab 的高級 API,它就會變得越臟(因為您離引擎蓋下的裸 VTK 越來越近),但您通常仍然可以使用mayavi大量工作和混淆代碼。

最后, mayavi的圖形窗口支持所有類型的寶石:管道和場景的交互式修改、坐標軸等注釋、切換正交投影,甚至能夠在自動生成的 Python 腳本中記錄您交互式更改的任何內容。 我肯定會建議嘗試使用 mayavi 來實現您想做的事情。 如果你知道你會用 ParaView 做什么,那么通過使用它的交互式會話記錄功能將它移植到mayavi是相當容易的。

3. pyvista

我最近被指出pyvista是一個構建在vtk之上的令人愉快的多功能和強大的庫。 盡管它的 API 需要一些習慣,但文檔中有大量示例和詳盡的 API 參考。 開始使用該庫需要一些學習曲線,但您可能會發現使用其高級界面和“按我的意思做”機制會更有效率。 我特別欣賞它的開源性質,包括公共問題跟蹤器和響應式核心開發人員。

那么我們如何使用pyvista讀取和繪制網格呢? 開始:

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)

這產生用 pyvista 輸出,同樣是一個帶有三條紋的條形,但現在它們是紫綠色黃色

如您所見,顏色非常不同:這是因為pyvista使用了 matplotlib 的感知統一的viridis 顏色圖,這對於數據可視化非常pyvista 如果您堅持使用更奇怪的顏色,您可以將cmap='jet'傳遞給對grid.plot的調用。 這里有很多要說的默認照明和陰影的不同之處,但我建議仔細閱讀有關過濾和繪制數據集的所有選項和方法的文檔。

讓我也提請你注意

4. vtkplotter

它有一種不同的方法,也建立在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()

在此處輸入圖片說明

可以在此處找到大量示例以及 API文檔

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM