I have created a class that encapsulates the creation of:
vtkImageDatareferred to here as “
- a lookup table,
- a poly data set (from
- a mapper (using
vtkPolyDataMapper), that associates the lookup table to it, with appropriate ranges,
- an actor,
- a renderer,
- a render window, referred to here as “
- and a render window interactor, referred to as “
The constructer finishes with a call to
All of these objects are instance attributes of the class. I’ve skipped a few method calls to try to keep the question succint.
When instantiated, the user must input the initial scalar values of the cells using a numpy array referred to as “
values”. An instance attribute called (
values is generated. A shallow copy of this numpy array is then taken using
vtk.utils.numpy_support) yielding a corresponding vtk array referred to as “
values_vtk”, which is also an instance attribute of the class. The scalars of the cell data of the vtkImageData object (
mesh is set to this vtk array.
The real issue I am having is when updating the
vtkImageData of the object when new cell data scalar
values are passed.
I created a method as
def update(self, values) that:
self.values = values
self.values_vtkto be equal to the vtk equivalent value of this new
self.renderWindow.Render()to refresh the window.
Firstly, I would like to know if steps 1 to 3 are okay, performance-wise, in order to update the cell scalar values of an ImageData. I had initially thought that just by changing
self.values_vtk (i.e. only step 2 without step 3), the ImageData would automatically change (maybe after a call to
.Modified()), but that was not the case in my tests.
Lastly, and most importantly, step 4 is not working - the window does not refresh with the changed ImageData cell scalar values. Or rather, it does so only a couple of times and then stops. When using PyCharm, if I begin the process in debug mode and set a breakpoint anywhere in the code after calling
.update(), then the window consistently updates the visualization as desired, when the execution reaches the breakpoint. I tried using
time.pause(0.001), but this did not work. I also tried calling
self.renderWindowInteractor.ReInitialize() after step 5 but this just crashes the program.
Edit: the written class can be found attached below.
vtkVisualizationPackage.py (11.9 KB)
Edit 2: fixed something in the attached code related to the
I am starting to believe the issue has something to do with Windows. In the following MWE, the first call, of quickly changing renders works fine. But the second one stops. I am in Windows 10.
import numpy as np from vtkVisualizationPackage import VTKImageData2DTopology import time def main(n_iter=100, sleep_time=0.01): nels = [20, 10] design_domain = [1., 0.5] types_of_els = 3 n_tot_els = nels*nels values = np.zeros(n_tot_els, dtype=np.int64) values[1::3] = 1 values[2::3] = 2 imageObject = VTKImageData2DTopology(nels=nels, number_of_vals=types_of_els, values=values, domain_size=design_domain) imageObject.zoom_camera(1.66) for i in range(n_iter): if (i % 3) == 0: values = np.ones(n_tot_els, dtype=np.int64)*2 values[1::3] = 0 values[2::3] = 1 elif (i % 3) == 1: values = np.ones(n_tot_els, dtype=np.int64) values[1::3] = 2 values[2::3] = 0 else: values = np.zeros(n_tot_els, dtype=np.int64) values[1::3] = 1 values[2::3] = 2 imageObject.update(values) time.sleep(sleep_time) if __name__ == "__main__": main(sleep_time=0.01) print(f"Finished first animation") main(n_iter=30, sleep_time=0.3) print(f"Finished second animation")
Edit 3: It seems that a quick and dirty fix would be to make the window interactor
.Start() or after updating and then somehow trigger a
Q click event automatically. Which is not ideal… Or maybe a method that makes the window interactive for a milisecond, after calling the
Edit 4: Edit 3 has been accomplished using
renderWindowInteractor.ProcessEvents(). But I hope that there is a better way to accomplish this.