Display vtkimage in 2D views

I have a vtkImage data and I would like to display this data in my slicer 2D views

After run this code, I could find node in my Slicer
However, I can not find image in my 2D views

And also, the in volume module the “Auto W/L” and “Threshold” section is deactivated.

This is my code,
Is there any problem?

## read vtk object convert to vtkimage
result_image = hlp.vtk_grid2image("/Users/home/Desktop/Simulation/Simulation/SMA_full_0.vtk")
result_volume = slicer.vtkMRMLScalarVolumeNode()
result_volume.SetAndObserveImageData(result_image)

## image to 2D scene
defaultVolumeDisplayNode = slicer.mrmlScene.CreateNodeByClass("vtkMRMLScalarVolumeDisplayNode")
defaultVolumeDisplayNode.AutoWindowLevelOn()
defaultVolumeDisplayNode.SetVisibility(True)
defaultVolumeDisplayNode.AddWindowLevelPresetFromString("ColdToHotRainbow")
slicer.mrmlScene.AddDefaultNode(defaultVolumeDisplayNode)
result_volume.SetAndObserveDisplayNodeID(defaultVolumeDisplayNode.GetID())
defaultVolumeDisplayNode.SetInputImageDataConnection(result_volume.GetImageDataConnection())

## volume node set name
slicer.mrmlScene.AddNode(result_volume).SetName("simulation_result")

You can use this to display any Scalar Volume Node in Slicer

def setSlicerViews(backgroundID, foregroundID):
    mainWindow = slicer.util.mainWindow()
    if mainWindow is not None:
        layoutManager = slicer.app.layoutManager()
        if layoutManager is not None:
            makeSlicerLinkedCompositeNodes()

            slicer.util.setSliceViewerLayers(background=backgroundID, foreground=foregroundID, foregroundOpacity=0.5)

            layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView)
            slicer.util.resetSliceViews()

def makeSlicerLinkedCompositeNodes():
    # Set linked slice views  in all existing slice composite nodes and in the default node
    sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')
    defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')
    if not defaultSliceCompositeNode:
        defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')
        slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)
    for sliceCompositeNode in sliceCompositeNodes:
        sliceCompositeNode.SetLinkedControl(True)
    defaultSliceCompositeNode.SetLinkedControl(True)

Thank you Alex

I tried your code, however, it is still not working
In the volume module, the “Auto W/L” and “Threshold” section was still deactivated.

This happens when you don’t have a display node associated with your volume or the volume is invalid (no or empty vtkImageData).

Does calling CreateDefaultDisplayNodes on the volume node after it was added to the scene fix the problem?

Can you show what you have in “Volume Information” section?

Iassoan, Thank you for your reply

The vtkImageData is not empty because I made a volume rendering scene from this vtkImageData.
(like figure below)

And this is my Volume Information

After you do this

you always need to do

result_volume.CreateDefaultDisplayNodes()

as @lassoan explained

1 Like

Maybe the issue is that a volume rendering display node is created very early and therefore a regular volume display node is not created (since you already have display node). Creating the default scalar volume display node before creating any additional special display nodes should fix the problem.

Thanks for your reply

As your advise, I added “CreateDefaultDisplayNodes()”
After added that the “Auto W/L” and “Threshold” section was activated

However, when I click the “visibility” in volume model
Slicer program immediately turn off

My code was written like this,
Is there any problem?

 ## read vtk object convert to vtkimage
result_image = hlp.vtk_grid2image("/Users/home/Desktop/Simulation/Simulation/SMA_full_0.vtk")
result_volume = slicer.vtkMRMLScalarVolumeNode()
result_volume.SetAndObserveImageData(result_image)
result_volume.SetName("simulation_result")
slicer.mrmlScene.AddNode(result_volume)
result_volume.CreateDefaultDisplayNodes()

## image to 2D scene
displaynode = result_volume.GetScalarVolumeDisplayNode()
displaynode.AutoWindowLevelOff()
displaynode.SetWindowLevelMinMax(10,900)
displaynode.AddWindowLevelPresetFromString("ColdToHotRainbow")
# displaynode.SetInputImageDataConnection(result_volume.GetImageDataConnection())
displaynode.SetVisibility(True)
slicer.mrmlScene.AddDefaultNode(displaynode)
result_volume.SetAndObserveDisplayNodeID(displaynode.GetID())

The problem is in these lines:

If you allocate memory in Python then you cannot transfer its ownership to a VTK class. If performance is extremely important and you work with enormous data sets then you may try to manually manage memory, but in general I would recommend to use slicer.util.updateVolumeFromArray to safely copy values from numpy array to vtkImageData in a volume node.

Finally It is work !!
Thank you

However ,
Why I could not see negative coordinate on this scene ?
Is there any other code do I have to update ?

## read vtk object convert to vtkimage
result_image, pressure = hlp.vtk_grid2image("/Users/home/Desktop/Simulation/Simulation/SMA_full_0.vtk")
dimension = result_image.GetDimensions()
reshapePressure = np.reshape(pressure, (dimension[2]-1,dimension[0]-1, dimension[1]-1))

result_volume = slicer.vtkMRMLScalarVolumeNode()
result_volume.SetAndObserveImageData(result_image)
slicer.util.updateVolumeFromArray(result_volume, reshapePressure)
result_volume.SetName("simulation_result")
slicer.mrmlScene.AddNode(result_volume)
result_volume.CreateDefaultDisplayNodes()

## image to 2D scene
displaynode = result_volume.GetScalarVolumeDisplayNode()
displaynode.AutoWindowLevelOff()
displaynode.SetWindowLevelMinMax(10,900)
displaynode.AddWindowLevelPresetFromString("ColdToHotRainbow")
# displaynode.SetInputImageDataConnection(result_volume.GetImageDataConnection())
displaynode.SetVisibility(True)
slicer.mrmlScene.AddDefaultNode(displaynode)
result_volume.SetAndObserveDisplayNodeID(displaynode.GetID())

Slice offset slider range is determined from the extent of the displayed background volume. If you have a single-slice volume then you will not be able to move away from it using the slider. You can use Shift + Mouse Move in other views or set a larger volume as background volume.

How could I set extent in my volume node or make large background volume?
I already set extent in “vtkimage.SetExtent()” but it seems like not working.

After calling SetExent() you need to call AllocateScalars (see example here). Of course reallocation clears current image content, so if you want to keep the image content then create a new image and resample the old image into that (an implementation of this is available in “Crop volume” module).