Hide a volume programmatically

I am writing a custom module in Python and I would like to:

  1. Replace the active volume in the slice viewer (similar to clicking on the “eye” icon of a different volume) with the next volume in the subject hierarchy
  2. Shut the eye icon on the subject hierarchy of the volume I just turned off

I was able to do the first bit with the following chunk of code, but I can’t seem to shut the eye in the subject hierarchy–both eyes stay on even though only one volume is present in the slice viewer. Is it possible to shut that eye icon programmatically? Thank you very much!

#  self.shNode is a subjectHierarchy node
def viewNextVolume(self, reverse = False):
  # First, get all valid volume vtkIDs
  sceneID = self.shNode.GetSceneItemID()
  allChildren = []
  self.shNode.GetItemChildren(sceneID, allChildren)
  validChildren = [child for child in allChildren if self.shNode.GetItemDataNode(child).IsTypeOf("vtkMRMLScalarVolumeNode")]

  # Second, get the vtkID of the current volume
  layoutManager = slicer.app.layoutManager()
  redVolumeID=layoutManager.sliceWidget("Red").sliceLogic().GetSliceCompositeNode().GetBackgroundVolumeID()
  currentvtkID = self.shNode.GetItemByDataNode(slicer.mrmlScene.GetNodeByID(redVolumeID))

  # third, advance the slice viewer
  nextDex = (validChildren.index(currentvtkID) + 1* (-1)**reverse) % len(validChildren) 
  newNode = self.shNode.GetItemDataNode(validChildren[nextDex])
  for sliceViewName in layoutManager.sliceViewNames():
    compositeNode = layoutManager.sliceWidget(sliceViewName).sliceLogic().GetSliceCompositeNode()
    compositeNode.SetBackgroundVolumeID(newNode.GetID())
    layoutManager.sliceWidget(sliceViewName).fitSliceToBackground()

  # HOW TO SHUT OFF EYE OF PREVIOUS VOLUME?

For the MRHead example I can set the visibility in the subject hierarchy programmatically using:

volNode = getNode("MRHead")
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
volItem = shNode.GetItemByDataNode(volNode)
pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler().instance()
volPlugin = pluginHandler.getOwnerPluginForSubjectHierarchyItem(volItem)
volPlugin.setDisplayVisibility(volItem, 0)
1 Like

I’m not sure why

volNode.GetDisplayNode().SetVisibility(0)
volNode.SetDisplayVisibility(0)

don’t work to hide the slice view of the volume, maybe someone else can weigh in? I also noticed if the volume is in a folder, hiding the folder does not hide the slice view of the volume.

See the following and the insights liked from there:
(ultimately it is due to turning the visibility on would only work for 2 volumes, since Slicer can’t show more than 2 volumes in a given slice view)

2 Likes

You can show-hide volumes in slice views by using slicer.util.setSliceViewerLayers().

You can hide volume rendering in 3D views like this (if you don’t want to use the subject hierarchy plugin based solution above):

vrDisplayNode = slicer.modules.volumerendering.logic().GetFirstVolumeRenderingDisplayNode(volumeNode)
# hide volume rendering:
vrDisplayNode.SetVisibility(False)
# prevent showing volume rendering if eye icon is clicked in Subject Hierarchy:
vrDisplayNode.SetShowMode(slicer.vtkMRMLDisplayNode.ShowIgnore)
2 Likes

slicer.util.setSliceViewerLayers() link worked very nicely for this purpose. Thanks!

For a newly loaded volume, In the mentioned method

vrDisplayNode = slicer.modules.volumerendering.logic().GetFirstVolumeRenderingDisplayNode(volumeNode)
vrDisplayNode.SetVisibility(False)

it is only show or hide volume if I show volume in Volume Rendering plugin at first time. Otherwise getting error:
AttributeError: 'NoneType' object has no attribute 'SetVisibility'

If the volume rendering display node (the data object that stores volume rendering settings) has not been created yet then you can create it by calling CreateDefaultVolumeRenderingNodes. There are several examples in the script repository.

1 Like

when I use CreateDefaultVolumeRenderingNodes, the volume property set to US-Fetal (Image 1). But if I show volume in Volume Rendering plugin at first time after loading the .mha file, it will automatically create a volume property with actual color of the image (Image 2). How can i solve this?

for file in mha_files:
    volume = slicer.util.loadVolume(file)
    vrDisplayNode = slicer.modules.volumerendering.logic().CreateDefaultVolumeRenderingNodes(volume)
    vrDisplayNode.SetVisibility(True)

Image 1

Image 2

You can get the existing display node like this:

volRenLogic = slicer.modules.volumerendering.logic()
displayNode = volRenLogic.GetFirstVolumeRenderingDisplayNode(volume)