Hiding segments with hot key

I need to “hide” all of my segmentations so that I can see only the volume underneath. I would like to map this to a keyboard shortcut so that I can toggle it on and off swiftly.
So far my attempts have not worked:

def hide_segment(segmentID):
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass("vtkMRMLSegmentationNode")
    displayNode = segmentationNode.GetDisplayNode()
    displayNode.SetSegmentVisibility(segmentID, False)

This hides only one segment. You say you want to hide all your segmentations so this only hides some of that.

displayNode.SetVisibility(False) hides a whole segmentation. Or segmentationNode.SetDisplayVisibility(False) the same thing.

To add a shortcut here’s a sample script from the script repository:
https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#customize-keyboard-shortcuts

To show/hide you’ll need something like
segmentationNode.SetDisplayVisibility(not segmentationNode.GetDisplayVisibility())

Thank you very much, after some trial and error, I was able to get the desired results: I can now toggle all my segmentations on and off to see the greyscale data underneath, in the 2D viewer using:

def hide_all_segmentations():
    segmentationNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLSegmentationNode')
    segmentationNodes.InitTraversal()
    segmentationNode = segmentationNodes.GetNextItemAsObject()
    while segmentationNode:
        displayNode = segmentationNode.GetDisplayNode()
        if displayNode:
            displayNode.SetVisibility(False)
        segmentationNode = segmentationNodes.GetNextItemAsObject()

def toggle_first_segmentation_visibility():
    segmentationNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLSegmentationNode')
    segmentationNodes.InitTraversal()
    segmentationNode = segmentationNodes.GetNextItemAsObject()
    if segmentationNode:
        current_visibility = segmentationNode.GetDisplayVisibility()
        segmentationNode.SetDisplayVisibility(not current_visibility)```

I now need to figure out how to see multiple “greyscale” volumes at once, in the 2D viewer. The purpose is to load multiple adjacent volumes, view them in the 2D slice viewer, and compare segmentaiton consistencies.
My understanding is that only one volume file can be actively displayed at a time due to the way the software manages rendering. Would using overlays be possible to achieve my goal?

Thank you for your help

One option is to use the CompareVolumes module to see the volumes side by side and linked. Another option would be to set up the volumes as background in the viewers and set up a hot key to cycle through them with setSliceViewerLayers.

Thank you for your reply.

When I use the CompareVolumes module the volumes appear side by side, but not spatially congrunet in the way I need.
The volumes and segmentations I am working with provide a limited, localized perspective of the data. I need to be able to inspect the “greyscale” volume data underneath the coloured segmentations, in the sagittal slice viewer.

Hopefully these images will clarify my goal:

  1. Here I have 7 segmentation mask files, and one “active” volume (the greyscale underneath) in the sagittal slice viewer.

  2. Here I’ve hidden the 5th segmentation mask to inspect the greyscale volume underneath:

To effectively analyze and visualize the changes in the segmentation masks across a broader spatial context, I need to be able to see all 7 of the corresponding greyscale volumes at the same time as I scrub through the slice.

Are these images acquired in patches like this, or were they broken into smaller volumes from a larger image for segmentation performance? If so, loading the full-scale image for visualization in the slice view would be the easiest path.

Another idea… you could write a script to get the RAS coordinates of where your mouse overlaps the slice view. Loop through all volumes and set visibility based on if the RAS coordinates of the mouse in the slice view are contained within the bounds of the volume.

# Function to check if the given RAS coordinates are within the bounds of a volume
def is_ras_within_volume(ras, volumeNode):
    bounds = [0] * 6
    volumeNode.GetRASBounds(bounds)
    return (bounds[0] <= ras[0] <= bounds[1] and
            bounds[2] <= ras[1] <= bounds[3] and
            bounds[4] <= ras[2] <= bounds[5])

# Function to set slice visibility for a given slice view and volume
def set_slice_visibility(volumeNode, isVisible):
    sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')
    for sliceCompositeNode in sliceCompositeNodes:
        # Set the background or foreground volume in each slice view based on visibility
        if isVisible:
            # If the volume should be visible, set it as the background volume
            sliceCompositeNode.SetBackgroundVolumeID(volumeNode.GetID())
        else:
            # If it should not be visible, clear the background volume ID
            if sliceCompositeNode.GetBackgroundVolumeID() == volumeNode.GetID():
                sliceCompositeNode.SetBackgroundVolumeID(None)

# Function that is triggered when the crosshair position is modified
def onCrosshairPositionModified(observer, eventid):
    ras = [0, 0, 0]
    crosshairNode.GetCursorPositionRAS(ras)
    print(f"Crosshair RAS coordinates: {ras}")

    # Loop through all volumes and set visibility in the slice views based on RAS location
    volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')
    for volumeNode in volumeNodes:
        isVisible = is_ras_within_volume(ras, volumeNode)
        set_slice_visibility(volumeNode, isVisible)
        print(f"Volume '{volumeNode.GetName()}' slice view visibility set to {isVisible}")

# Add the observer for crosshair position updates and store the observer ID for future removal
crosshairNode = slicer.util.getNode("Crosshair")
observerTag = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onCrosshairPositionModified)

print("Crosshair position tracking and volume slice view visibility update script initialized.")

# To remove the observer, use the following line:
# crosshairNode.RemoveObserver(observerTag)

Trying to render a composite of multiple volumes to the slice view is an uncommon but interesting use-case. It kind of reminds me of dealing with geospatial data (like Google Earth), where you can load data in patches on demand for the current field of view, but the full dataset can be potentially infinite.

For that kind of data this extension could be useful: GitHub - gaoyi/SlicerBigImage: Large (GB and above) scale microscopic image computing using 3D Slicer

1 Like

You can stitch these blocks into a single image before display using the Stitch Volumes module (in Sandbox extension).

Reading these old scrolls (Vesuvius Challenge) has been discussed in this forum before, have a look at it here: CRIPPLING LAG during segmentation on a strong computer - #19 by lassoan