How to set volume rendering preset using Python

Hi developers,

Using a Python script I am trying to load a volume, set the slice views and also a volume rendering preset. While loading and setting the slice views works out well, the volume rendering always shows up with the default settings and not the targeted preset. Could someone please give me a hint of what’s missing? Is there a way to adjust the preset parameter “shift” in advance?
Since I am new to Slicer development I would also be happy about any hint of how to improve the code (is there something that can be skipped or is there a utitlity function to get similar results easier?). Here is the code I am using:

fileName = "Image01.IMA"
volume_logic = slicer.modules.volumes.logic()
volume_node = volume_logic.AddArchetypeScalarVolume(fileName, "Volume3D", 2, None)

mrmlLogic = slicer.app.applicationLogic()
selNode = mrmlLogic.GetSelectionNode()
selNode.SetReferenceActiveVolumeID(volume_node.GetID())
mrmlLogic.PropagateVolumeSelection()

logic = slicer.modules.volumerendering.logic()
preset = logic.GetPresetByName('CT-AAA')
preset_node = slicer.mrmlScene.AddNode(preset)
display_node = logic.CreateVolumeRenderingDisplayNode()
slicer.mrmlScene.AddNode(display_node)
logic.UpdateDisplayNodeFromVolumeNode(display_node, volume_node, preset_node)
display_node.SetVisibility(1)

Thanks in advance and best wishes,
Oliver

Operating system: Win7
Slicer version: 4.8.1

1 Like

Hi Oliver,

There have been some improvements since 4.8.1 that makes it easier for us to do this. So if you use the latest nightly, then this is what you can do:

Easier setup of volume rendering (no need to create the display node and update it from the logic):

volRenLogic = slicer.modules.volumerendering.logic()
displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)

This is not very clean, because it uses widgets from the volume rendering module, but you can apply a shift like this:

volRenWidget = slicer.modules.volumerendering.widgetRepresentation()
if volRenWidget is None:
  logging.error('Failed to access volume rendering module')
  return
# Make sure the proper volume property node is set
volumePropertyNode = displayNode.GetVolumePropertyNode()
if volumePropertyNode is None:
  logging.error('Failed to access volume properties')
  return
volumePropertyNodeWidget = slicer.util.findChild(volRenWidget, 'VolumePropertyNodeWidget')
volumePropertyNodeWidget.setMRMLVolumePropertyNode(volumePropertyNode)
# Adjust the transfer function
volumePropertyNodeWidget.moveAllPoints(x, 0, false)

where ‘x’ is your shift.
It would be probably possible to do this on the MRML/VTK level, but as there are CTK widget calls involved in moveAllPoints, it is not as easy as it should be, and it was not too high on the priority list thus far.

Hope this helps, let us know if you have further questions.

Hi Csaba,

thanks for your quick answer. That helps a lot. Do you also have a suggestion of how to set the preset (in the example above ‘CT-AAA’) at first? The code I posted to achieve to set a preset doesn’t work. The volume rendering looks the same as not providing a preset in the call

logic.UpdateDisplayNodeFromVolumeNode(display_node, volume_node, preset_node)

Additionally I have one more question that came up today. When activating the “eye” in the slice views the slice appears in the 3D view. I try to achieve the same behaviour using the following Python lines for the red slice in my code:

display_node = slicer.mrmlScene.GetNodeByID(‘vtkMRMLModelDisplayNode1’)
display_node.VisibilityOn()

Which works for the current red slice position until I change that position by scrolling in the red slice window. The slice in the 3D view immediately disappears. I observed that the “eye” in the red slice window also stays closed after the call above. Any idea what could be the cause?

This is not related to the original question. Could you please post this as a separate topic?

I think if you copy the properties of the preset node from the private presets scene to the volume property node of your volume then it should do the trick. Something like this:

volumePropertyNode.Copy(preset)

Sorry, I’ll setup a new post.

Works perfect now!
Thanks for your help Csaba

1 Like

Hi Team,

I am using 3D Slicer and Python for the first time and need some help.

What I am trying to do > Open a example dataset in 3D slicer, Change the view to 3D only and then enable volume rendering so that I can see in MR-Default via Python interactor.

Why I am doing this > I want to automate this, So that I can do it on thousands of machines simultaneously and understand the application requirements in terms of CPU, Storage and GPU.

What I have figured out till now >

Opening of Application #Run - Slicer.exe

Ctrl + 3 #Opening Python Interactor

slicer.util.loadVolume("C:\Medical Data\MR-head.nrrd")   #Open the sample data set 

and after that I am not able to do proceed.

If possible, Please help me with the code or the resources which I can utilize to develop the python script.

-Yash

Since \ is an escape character in Python, the file path is incorrect, and so no volume will be loaded. See more details and description of correct syntax here.

A post was split to a new topic: Adjust volume rendering transfer function in Python