Unable to Set Transfer2DYAxisArray to "Curvature"

Dear vtk Community :sunny:,

during my project to construct a volume renderer using vtk i am facing the challenge to define the curvature data of the volume as the y-axis of the 2D transfer function.

According to vtk documentation the input must be of type char.

SetTransfer2DYAxisArray()
virtual void vtkGPUVolumeRayCastMapper::SetTransfer2DYAxisArray	(const char *)
// Set/Get the transfer 2D Y axis array.

My approach was to use numpy to calculate the curvature on the entire volume and then create a vtkImageData object with its “Name” set to “Curvature”.

        from vtkmodules.util import numpy_support
        curvature_np_array = compute_curvature(array_from_image(self.itk_img))  # Curvature as np.array

        vtkarr = numpy_support.numpy_to_vtk(curvature_np_array.ravel(), deep=True, array_type=vtk.VTK_FLOAT)
        vtkarr.SetNumberOfComponents(1)
        vtkarr.SetNumberOfTuples(curvature_np_array.ravel().shape[0])
        vtkarr.SetName("Curvature")

        self.volume_mapper.SetTransfer2DYAxisArray(vtkarr.GetName())

The compute_curvature function calculates the mean curvature using the “itk.EigenFilter”.

Unfortunately the VolumeMapper ignores this and the Y-axis remains “gradient”.

Can someone help me with this?

David

Could you please post a complete script that you use?

Are you setting the transfer function mode via vtkVolumeProperty::SetTransferFunctionMode to TF_2D?

Hi @sankhesh,
thank you very much for your answer. So soon we hear each other again. :smiley:

Unfortunately I can’t send the complete script. But I will extract pieces from my pipeline in appropriate order.

I initialize my class with the following field variables:

    def __init__(self):
        self.two_dimensional_tf = vtk.vtkImageData()
        self.volume = vtk.vtkVolume()
        self.volume_property = vtk.vtkVolumeProperty()
        self.volume_mapper = vtk.vtkOpenGLGPUVolumeRayCastMapper()
        self.renderer = vtk.vtkOpenGLRenderer()
        self.render_window = vtk.vtkRenderWindow()
        self.interactor = vtk.vtkRenderWindowInteractor()

After reading the dataset
I calculate its curvature with

curvature_np_array = compute_curvature(array_from_image(self.itk_img)) 

This has the same size as the itk_volume:

>>> print(curvature_np_array.shape)
(423, 548, 548)
>>> print(self.itk_img.shape)
(423, 548, 548)

I then convert this to a vtkFloatArray:

Curvature = numpy_support.numpy_to_vtk(curvature_np_array.ravel(), deep=True, array_type=vtk.VTK_FLOAT)
Curvature.SetNumberOfComponents(1)
Curvature.SetNumberOfTuples(curvature_np_array.ravel().shape[0])
Curvature.SetName("Curvature")
Curvature.Modified()

I have tried to set SetTransferFunctionModeTo2D() already here.

Then:

self.volume_mapper.SetTransfer2DYAxisArray(Curvature.GetName())
# Or with same result
self.volume_mapper.SetTransfer2DYAxisArray("Curvature")

Afterwards I put the input into the VolumeMapper.

#  Before that I converted the itk to the vtk_image
self.volume_mapper.SetInputData(self.vtk_image)

Then I set the VolumeProperty:

self.volume_property.SetTransferFunctionModeTo2D()
self.volume_property.SetTransferFunction2D(0, self.two_dimensional_tf)

… The volume Actor:

self.volume_mapper.Update()
self.volume_property.Modified()
self.volume.SetMapper(self.volume_mapper)
self.volume.SetProperty(self.volume_property)

And finally add the volume to the renderer.