Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fasten VTK addPoint Loop (Python)

As i am starting to build some basic plotting methods for 3D visualization with VTK for some Data-Visualization, i ran over the following issue:

My Dataset is usually about the Size ob 200e6-1000e6 Datapoints (Sensor Values) with its corresponding coordinates, points, (X,Y,Z). My Visualization method works fine, but there is at least one Bottleneck. Beside the rest of the code, the schown example with the 2 for loops, is the most time consuming part of the whole method.

I am not happy with adding the Coordinates (points, numpy(n,3) ) and Sensor Values (intensity, numpy(n,1) ) via foor loops to the VTK Objects

The spicific code example:

    vtkpoints = vtk.vtkPoints()                                                     # https://vtk.org/doc/nightly/html/classvtkPoints.html
    vtkpoints.SetNumberOfPoints(self.points.shape[0])


    # Bottleneck - Faster way?
    self.start = time.time()
    for i in range(self.points.shape[0]):
        vtkpoints.SetPoint(i, self.points[i])
    self.vtkpoly = vtk.vtkPolyData()                                                # https://vtk.org/doc/nightly/html/classvtkPolyData.html
    self.vtkpoly.SetPoints(vtkpoints)

    self.elapsed_time_normal = (time.time() - self.start) 
    print(f" AddPoints took : {self.elapsed_time_normal}")


    # Bottleneck - Faster way?
    vtkcells = vtk.vtkCellArray()                                                   # https://vtk.org/doc/nightly/html/classvtkCellArray.html
    self.start = time.time()
    for i in range(self.points.shape[0]):
        vtkcells.InsertNextCell(1)
        vtkcells.InsertCellPoint(i)
    map(vtkcells.InsertNextCell(1),self.points)
    
    self.elapsed_time_normal = (time.time() - self.start) 
    print(f" AddCells took : {self.elapsed_time_normal}")
    
    # Inserts Cells to vtkpoly 
    self.vtkpoly.SetVerts(vtkcells)

Times:

  • Convert DataFrame took: 6.499739646911621
  • AddPoints took : 58.41245102882385b
  • AddCells took : 48.29743027687073
  • LookUpTable took : 0.7522616386413574

All Input Data is of type int, its basicly a Dataframe converted to vtknumpy objects by numpy_to_vtk method.

I am very happy, if someone has an idea of speeding this up.

BR Bastian

like image 352
AM_Guy Avatar asked Mar 03 '26 16:03

AM_Guy


1 Answers

For the first Loop @Mathieu Westphal gave me a nice solution:

vtkpoints = vtk.vtkPoints()                                                  
vtkpoints.SetData(numpy_to_vtk(self.points))
self.vtkpoly = vtk.vtkPolyData()                                             
self.vtkpoly.SetPoints(vtkpoints)

New Time to Add Points:

  • AddPoints took : 0.03202845573425293

For the second Loop it took me a bit longer to find that solution, bit with some hints of the vtk community, i got it running too. Heres the Code i used to set the Verts of the vtkpoly:

vtkcells = vtk.vtkCellArray()

cells_array_init = np.arange(len(self.points)).reshape(len(self.points),1)

cells_array_set = np.repeat(cells_array_init, repeats=3, axis=1)

cells_npy = np.column_stack([np.full(len(self.points), 3, dtype=np.int64), cells_array_set.astype(np.int64)]).ravel()

vtkcells.SetCells(len(self.points), numpy_to_vtkIdTypeArray(cells_npy) 

# Inserts Cells to vtkpoly 
self.vtkpoly.SetVerts(vtkcells)

New Time to Add Cells/Verts:

  • AddCells took : 2.73202845573425293

(17-18 x faster)

Needed to do some numpy stuff to get a "Cellarray" and get it in the right shape: (3,0,0,0, ..., 3, n-1, n-1, n-1) with n as len(points), and convert this to numpy_to_vtkIDTypeArray. Pretty sure this can be improved to, but i am pretty happy for now. If someone has a quick idea to even speed this up, i'd love to hear!

BR

like image 53
AM_Guy Avatar answered Mar 06 '26 07:03

AM_Guy