基于ParaView的Python脚本如何显示vtkUnstructuredGrid?

5

我在Ubuntu 18.04上安装了Paraview 5.6,并且我希望编写一个Python脚本来显示vtkUnstructuredGrid。

import numpy as np
from paraview.simple import *
import paraview.vtk as vtk
from paraview.vtk.numpy_interface import dataset_adapter as dsa
import paraview.vtk.util.numpy_support as vnp

node = np.array(
        [[0.0, 0.0, 0.0],
         [1.0, 0.0, 0.0],
         [1.0, 1.0, 0.0],
         [0.0, 1.0, 0.0]], dtype=np.float)
cell = np.array([[3, 1, 2, 0], [3, 3, 0, 2]], dtype=np.int)
NC = cell.shape[0]

points = vtk.vtkPoints()
points.SetData(vnp.numpy_to_vtk(node))
cells = vtk.vtkCellArray()
cells.SetCells(NC, vnp.numpy_to_vtkIdTypeArray(cell))

uGrid =vtk.vtkUnstructuredGrid() 
uGrid.SetPoints(points)
uGrid.SetCells(vtk.VTK_TRIANGLE, cells)
# how to put uGrid into the following codes
view = GetActiveViewOrCreate('RenderView') 
dispaly = Show()
render = Render()
Interact()

我找不到在Python脚本中实现此功能的任何示例。所以,我需要您的帮助,非常感谢。
更新:
我尝试编写以下源代码类:
import numpy as np
from paraview.simple import *
import vtk 
import vtk.util.numpy_support as vnp
from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase
from vtkmodules.numpy_interface import dataset_adapter as dsa
from paraview.util.vtkAlgorithm import smproxy, smproperty, smdomain

@smproxy.source(name="MeshSource", label="triangle mesh!")
class MeshSource(VTKPythonAlgorithmBase):
    def __init__(self):
        print("Initialize the source!")
        VTKPythonAlgorithmBase.__init__(self,
                nInputPorts=0,
                nOutputPorts=1,
                outputType='vtkUnstructuredGrid')
        node = np.array(
                [[0.0, 0.0, 0.0],
                 [1.0, 0.0, 0.0],
                 [1.0, 1.0, 0.0],
                 [0.0, 1.0, 0.0]], dtype=np.float)
        cell = np.array([[3, 1, 2, 0], [3, 3, 0, 2]], dtype=np.int)
        NN = node.shape[0]
        NC = cell.shape[0]

        points = vtk.vtkPoints()
        points.SetData(vnp.numpy_to_vtk(node))
        cells = vtk.vtkCellArray()
        cells.SetCells(NC, vnp.numpy_to_vtkIdTypeArray(cell))

        self.mesh = vtk.vtkUnstructuredGrid() 
        self.mesh.SetPoints(points)
        self.mesh.SetCells(vtk.VTK_TRIANGLE, cells)
        rho = vnp.numpy_to_vtk(np.zeros(NN))
        rho.SetName('rho_A')
        self.mesh.GetPointData().AddArray(rho)
        self.Port = 0

    def RequestData(self, request, inInfo, outInfo):
        print("Request the data!")
        output = vtk.vtkUnstructuredGrid.GetData(outInfo)
        optput.ShallowCopy(self.mesh)
        return 1

    def UpdatePointData(self, rho):
        print("Update the point data!")
        rho = vnp.numpy_to_vtk(rho)
        rho.SetName('rho_A')
        self.mesh.GetPointData().AddArray(rho)
        self.Modified()

source = MeshSource()
view = GetActiveViewOrCreate('RenderView') 
display = Show(source, view)
Interact()

但是我遇到了一些错误:

Traceback (most recent call last):
  File "test_triangle.py", line 55, in <module>
    dispaly = Show(source, view)
  File "/home/why/local/lib/python3.6/site-packages/paraview/simple.py", line 482, in Show
    rep = controller.Show(proxy, proxy.Port, view)
  File "/home/why/local/lib/python3.6/site-packages/paraview/servermanager.py", line 158, in __ConvertArgumentsAndCall
    retVal = func(*newArgs)
TypeError: Show argument 1: method requires a vtkSMSourceProxy, a vtkPythonAlgorithm was provided.

我一定错过了什么。

1个回答

6
重要的是要理解,在ParaView中有两个级别的Python脚本可用。较低级别是您可以使用VTK创建或过滤数据的地方。较高级别允许您控制ParaView的操作,例如显示数据、设置显示属性等。您缺少的是在脚本中两个级别之间的桥梁。
在您的原始示例中,您很好地创建了一个非结构化网格。为了使ParaView可以使用它,请添加以下内容:
# how to put uGrid into the following codes
view = GetActiveViewOrCreate('RenderView')

# create a trivial producer to bridge between the VTK object and ParaView
tp = TrivialProducer()
tp.GetClientSideObject().SetOutput(uGrid)

dispaly = Show(tp)

这将创建一个ParaView代理(TrivialProducer),它是一个简单的VTK数据源vtkTrivialProducer的代理。它所做的就是获取数据集并将其传递给任何请求它的下游过滤器。(注意:这仅在内置服务器模式下运行时才有效,因为涉及到GetClientSideObject(),这是相当常见的)。
此外,您定义单元格的方式也存在问题。单元格定义中的第一个条目需要是定义单元格的点数。因此,请将该行更改为:
cell = np.array([[3, 1, 2, 0], [3, 3, 0, 2]], dtype=np.int)

非常感谢,Cory。我认为这些知识应该被放入Paraview的教程中。 - Huayi Wei
1
这是一种笨拙的方法,所以不应该添加到教程中。最好的方法是通过可编程源或通过扩展VTKPythonAlgorithmBase(你已经接近了,只需要将类与脚本分开,保存在单独的文件中,然后作为插件加载)。这两种方法都记录在ParaView指南的第12章中(https://www.paraview.org/paraview-guide/)。 - Cory Quammen
感谢您的详细解释。我会再试一次。 - Huayi Wei
@CoryQuammen 你好,请问您能详细说明一下这个问题吗:“(注意:这仅适用于在内置服务器模式下运行的情况,因为GetClientSideObject()函数是相当常见的)”。这是否意味着它不能通过例如Connect("localhost")连接到外部Python会话来工作?也就是说,只能通过本地ParaView会话的Python shell来使用? - M.K
GetClientSideObject() 返回客户端上的 VTK 数据对象。当您调用 Connect 时,您正在连接到另一个服务器进程,因此 GetClientSideObject() 将不会返回任何有用的信息。您可以使用 paraview.servermanager.Fetch(GetActiveSource()) 将管道浏览器中当前选定对象的 VTK 对象传输到客户端。返回的对象是完整的 VTK 数据对象。 - Cory Quammen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接