Segmentation memory size variations

Hi to everyone. Today we’re concerned with segmentation memory sizes.
We are using two different approaches to the same problem: linear (input driven) and non-linear (event/button driven).

The main steps of the process can be summarized as:

· Loading the CT image and resampling it programatically. We’ll call the resampled volume ‘resliced’ from here onwards.

· Create a Segmentation node and set the ‘Source Volume’ as ‘resliced’.

· From a labelmap, we generate segments in this segmentation.

· For the linear case, the segments occupy ~300 MB whereas for the event-driven case the segments occupy ~2 GB.

We have also observed for the linear scenario that re-selecting the ‘resliced’ volume as ‘source geometry’ with the ‘Specify Geometry’ button in the SegmentEditor extension, the segments increase their memory size from ~300 MB to ~2GB.

For additional detail:

  • In both cases we use the same functions to generate both the segmentation and the segments.

  • In the event-driven approach, the volumeNode is being stored as a global parameter, and functions are being called from classes, which control the button logic to launch each event.

So, to summarize, we have a couple questions:

  • Is it possible that our non-linear approach has a negative effect on RAM usage?

  • Can this effect be associated with the use of global variables to store the reference to the VolumeNode?

  • Why resetting the source geometry by hand increases the memory needed to store segments?

Thank you all in advance :slight_smile:

These mechanisms should explain all the variations in memory size that you described:

  • Segmentation geometry is determined from the source volume you select first.
  • If you then select a source volume that has a different geometry than the segmentation then an internal temporary volume is created that stores the source volume resampled to the segmentation’s geometry.
  • If you import a segment into a segmentation then it is not resampled until it is necessary (to allow copying segments between segmentations without data loss and heavy computation). When you edit any of the segments then it may trigger resampling of all segments.

Thanks @lassoan for a quick an enlightening answer. We have noticed all this behaviours but we were not sure about their origin. Now it’s clear. But one question remains:

The code using input('text') to stop the script, calls the functions in exactly the same way the code driven with buttons. Both codes uses the line:

segmentEditorWidget.setSourceVolumeNode(volumeNode)

, all the times we need to automatically create and modify segments. Calling this line could affect to memory size segment if we uses it every time we create a new segment in the same segmentation? In that case, why this could affect in button process and not in input process?

The following code is the start of the segmentation process:

    # 1. Create the empty segmentation in slicer
    
    if (slicer.mrmlScene.GetNodesByClassByName('vtkMRMLSegmentationNode', segmentation_name).GetNumberOfItems() > 0):
        # Segmentation node exists
        segmentationNode = slicer.mrmlScene.GetNodesByClassByName('vtkMRMLSegmentationNode', segmentation_name).GetItemAsObject(0)
    else:
        segmentationNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentationNode", segmentation_name)
            
    
    segmentEditorWidget = slicer.modules.segmenteditor.widgetRepresentation().self().editor
    segmentEditorWidget.setSegmentationNode(segmentationNode)
    segmentEditorWidget.setSourceVolumeNode(volumeNode)

    segmentPrefix = f'{patientID}'
    segmentId = segmentationNode.GetSegmentation().AddEmptySegment(segmentPrefix)
    
    # Use random color
    red = random.random()
    green = random.random()
    blue = random.random()
    segmentationNode.GetSegmentation().GetSegment(segmentId).SetColor(red,green,blue)
    segmentationNode.GetSegmentation().SetConversionParameter("Smoothing factor","0.0")
       

    # Get segment as numpy array
    segmentArray = slicer.util.arrayFromSegmentBinaryLabelmap(segmentationNode, segmentId, volumeNode)

Thanks for your helpful responses :smiley: .