5

I install paraview 5.6 on my Ubuntu 18.04 system and I want to write a python script to show a 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()

I can not find any example from the internet to do such thing in python script. So I need your help, thanks very much.

Update:

I try to code a source class like following:

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

But I got some error :

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.

I must miss something.

Huayi Wei
  • 829
  • 1
  • 7
  • 16

1 Answers1

6

The key thing to understand is that there are two levels of Python scripting available in ParaView. The lower level is where you can create or filter data with VTK. The higher level lets you control the operation of ParaView, e.g., show data, set display properties, etc. What you are missing is a bridge between the two levels in your script.

In your original example, you are creating an unstructured grid in VTK just fine. To get it to a place where ParaView can use it add the following:

# 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)

This creates a ParaView proxy (TrivialProducer) that is a proxy for a simple VTK data source called a vtkTrivialProducer. All it does is take a dataset and pass that to any downstream filters that request it. (Caveat: this only works when you are running in built-in server mode because of GetClientSideObject(), which is fairly common).

There is also a problem with how you are defining cells. The first entry in a cell definition needs to be the number of points defining the cell. So change that line to

cell = np.array([[3, 1, 2, 0], [3, 3, 0, 2]], dtype=np.int)
Cory Quammen
  • 1,243
  • 7
  • 9
  • Thanks very much, Cory. I think this knowledge show be put into the tutorial of Paraview. – Huayi Wei Feb 12 '19 at 01:33
  • 1
    This is the kludgey way to do it, so it shouldn't really be added to a tutorial. The best way is either through a **Programmable Source** or by extending `VTKPythonAlgorithmBase` (which you got close to doing, you just needed to separate the class from the script, save it in a separate file, then load it as a plugin). Both approaches are documented in Chapter 12 of the ParaView Guide (https://www.paraview.org/paraview-guide/) – Cory Quammen Feb 18 '19 at 16:57
  • thanks for your detailed explanation. I will try it agian. – Huayi Wei Feb 19 '19 at 07:30
  • @CoryQuammen Hello, could you please elaborate on that "(Caveat: this only works when you are running in built-in server mode because of GetClientSideObject(), which is fairly common)". Does this mean that it won't work with an external python session connecting through Connect("localhost") for example. i.e only through the python shell of a local paraview session ? – M.K Jun 27 '20 at 11:40
  • `GetClientSideObject()` returns the VTK data object on the client. When you call `Connect`, you are connecting to a different server process, so `GetClientSideObject()` will not return anything useful. You can use `paraview.servermanager.Fetch(GetActiveSource())` to transfer the VTK object for the object currently selected in the Pipeline Browser to the client. The object returned is the full VTK data object. – Cory Quammen Jul 01 '20 at 20:53