how to 3d volume render numpy array

I’m trying to volume render an 3d numpy array with vtk python.

I used to render it by getting the stack of images,
but I’m trying to volume render with an 3d numpy array instead of stack of images.

this picture below is my first try and it doesn’t look good.

data = box # box is 3d array

imdata = vtk.vtkImageData()

depthArray = numpy_support.numpy_to_vtk(data.ravel(), deep=True, array_type=vtk.VTK_DOUBLE)

imdata.GetPointData().SetScalars(depthArray)

volumeMapper.SetInputData(imdata)

I think these are something that needs to be fixed.

My input is not Image, It’s an 3d array.

What should I fix it?

I am not famiiar with numpy_support so someone else may help you better to fix the issue on your code.
However, to pass a numpy array as point data (in 0-copy), I use the following snippet in VTK python:

floatData = np.array([0, 1, 0.5], 'f') # my numpy array

floatArray = vtk.vtkFloatArray() # the VTK array
floatArray.SetName("My array")
floatArray.SetNumberOfComponents(1)
floatArray.SetArray(floatData, 3, False) # False because we do not take the ownership

mydata.GetPointData().SetScalars(floatArray); # give the array to the dataset

Hope that helps

You have forgot to set up appropriate transfer functions. Specifying scalar opacity transfer function is a minimum, for nicer rendering you probably also want color transfer function. Check out VTK examples (like this) and documentation for details. Determining transfer functions using Python scripting is tedious, so I would recommend Paraview’s transfer function editor for general engineering visualization and 3D Slicer’s volume rendering module for medical image visualization.

Yes I did set the color transfer function and opacity.

I haven’t show the whole code yet.

below is my whole code.

from vtk.util import numpy_support
import vtk
import numpy as np

box = []
for i in range(1536):
    loader = np.loadtxt("/Users/nyh/Documents/RP_lab/XRF/nparray/"+str(i+1)+".npy")
    box.append(loader)
box = np.stack(box)    

data = box

imdata = vtk.vtkImageData()
depthArray = numpy_support.numpy_to_vtk(data.ravel(), deep=True, array_type=vtk.VTK_DOUBLE)

imdata.SetDimensions(data.shape)
imdata.SetSpacing([1,1,1])
imdata.SetOrigin([0,0,0])
imdata.GetPointData().SetScalars(depthArray)

colorFunc = vtk.vtkColorTransferFunction()
# colorFunc.AddRGBPoint(1, 1, 0.0, 0.0) # Red
colorFunc.AddRGBPoint(2, 0.0, 1, 0.0) # Green

opacity = vtk.vtkPiecewiseFunction()

volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(colorFunc)
volumeProperty.SetScalarOpacity(opacity)
volumeProperty.SetInterpolationTypeToLinear()
volumeProperty.SetIndependentComponents(2)

volumeMapper = vtk.vtkOpenGLGPUVolumeRayCastMapper()
volumeMapper.SetInputData(imdata)
volumeMapper.SetBlendModeToMaximumIntensity()


volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty)

ren = vtk.vtkRenderer()
ren.AddVolume(volume)
ren.SetBackground(0,0,0)

renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
renWin.SetSize(900, 900)

interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(renWin)

interactor.Initialize()
renWin.Render()
interactor.Start()

When I visualize the array data with pyvista, it looks like this.

every slice of array has a circular data inside.
but I don’t see any circles with VTK.

It looks like your scalar opacity transfer function is incorrect. It is easier to learn how to create good transfer functions by using a GUI (Paraview, 3D Slicer, etc).

Did you take care about order c or fortran?
Try data.ravel(order=‘F’)