Assigning thresholded regions to different segments

Operating system: Windows 7
Slicer version: 4.10
Expected behavior: Different thresholded regions get assigned to respective segments
Actual behavior: Both regions getting assigned to the first threshold segment

Hi everyone,
I am working on an extension to 3D Slicer. The final aim of the extension is to segment the CT scan images to 2 base segments based on the thresholding values. For doing this, I am applying the Thresholding operation on 2 cloned segmentation and volume nodes. After this, I canā€™t determine how to assign the thresholded regions to a specific segment?

# Add segments

segmentName = "Threshold-A-B"
addedSegmentID = segmentationNode.GetSegmentation().AddEmptySegment(segmentName)
segment = segmentationNode.GetSegmentation().GetSegment(addedSegmentID)
segment.SetColor(216./256,101./256,79./256)

segmentName = "Threshold-B-MAX"
addedSegmentID = segmentationNode.GetSegmentation().AddEmptySegment(segmentName)
segment = segmentationNode.GetSegmentation().GetSegment(addedSegmentID)
segment.SetColor(200./256,200./256,235./256)	

#Cloning segmentationNode and masterVolumeNode
#Copied from Slicer website, get clonedNode and clonedVolumeNode from here

# Create segment editor to get access to effects
segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
segmentEditorNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentEditorNode")
segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
segmentEditorWidget.setSegmentationNode(segmentationNode)
segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

# Thresholding (From A to B)
segmentEditorWidget.setActiveEffectByName("Threshold")
effect = segmentEditorWidget.activeEffect()
effect.setParameter("MinimumThreshold","A")
effect.setParameter("MaximumThreshold","B") 
effect.self().onApply()

displayNode = segmentationNode.GetDisplayNode()
displayNode.SetSliceIntersectionThickness(2)
#Missing: Assign this to segment 'Threshold-A-B'	

#Creating a  second segment editor to apply second thresholding to cloned volume
segmentEditorWidget2 = slicer.qMRMLSegmentEditorWidget()
segmentEditorWidget2.setMRMLScene(slicer.mrmlScene)
segmentEditorNode2 = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentEditorNode")
segmentEditorWidget2.setMRMLSegmentEditorNode(segmentEditorNode2)
segmentEditorWidget2.setSegmentationNode(clonedNode)
segmentEditorWidget2.setMasterVolumeNode(clonedVolumeNode)	

# Thresholding 2 (From B to MAX)
segmentEditorWidget2.setActiveEffectByName("Threshold")
effect2 = segmentEditorWidget2.activeEffect()
effect2.setParameter("MinimumThreshold","B")
effect2.self().onApply()

displayNode2 = clonedNode.GetDisplayNode()
displayNode2.SetSliceIntersectionThickness(2)
#Missing: Assign this to the segment 'Threshold-B-MAX' 

There is no need to create a second segment editor widget. You can combine segments using Logical operators effect.

Thanks for the help. I found this great example for using the Logical Operators effect, which could be useful for others too: Find islands in a certain voxel size range. Ā· GitHub

I just had a basic question regarding the above file, Is there a way to clear the scene, once the script has run for one image. I have like 50 images that need I want to segment but every time I run this code in Slicer, the segmentation for each next image just appears on top of each other in the scene views.

I tried using the below code at the end

    segmentEditorWidget = None
    slicer.mrmlScene.RemoveNode(segmentationNode)
    slicer.mrmlScene.RemoveNode(masterVolumeNode)

But this just throws an error

Traceback (most recent call last):
File "D:/Users/ishan.saxena/TokExData/SlicerScripts/Segmentation_postop.py", line 72, in onSegmentationButtonClicked
self.addSegmentation(dir_path, filename)
File "D:/Users/ishan.saxena/TokExData/SlicerScripts/Segmentation_postop.py", line 172, in addSegmentation
effect.setParameter("Operation", "COPY")
AttributeError: ā€˜NoneTypeā€™ object has no attribute ā€˜setParameterā€™

If I comment these removeNode commands, the code starts working perfectly only the scenes donā€™t get cleared. Any tips?

This should work:

slicer.mrmlScene.Clear(0)

Also, it should be enough to clear the scene and no need to delete segmentEditorWidget when you switch between data sets.

Thanks for the responses, however the error remains the same even after adding slicer.mrmlScene.Clear(0) at the end of the script and deleting segmentEditorWidget=None and the other RemoveNode commands.

I am guessing there is something wrong with the way I define the Segmentation nodes and volume nodes under addSegmentation which doesnā€™t match with the Logical Operators effect script I used from the link above.
My current definitions are:

slicer.app.processEvents()
masterVolumeNode = slicer.util.loadVolume(file_complete, returnNode = True)[1]
# Create segmentation
segmentationNode_name = filename + "_" + welcheOP + "_segmentation"
segmentationNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentationNode", segmentationNode_name)
segmentationNode.CreateDefaultDisplayNodes() # only needed for display
segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(masterVolumeNode)

The error is in your script. Value of effect variable is None. I would recommend to use a Python debugger and execute your code step by step to see where it does something different than you would expect.

1 Like

I made some observations from the debugging process. Since I am using the SegmentEditor module in a loop in my script, it sets the ActiveEffect to None after the first iteration through the loop, and then during the next iteration, I am unable to set the ActiveEffect using

segmentEditorWidget.setActiveEffectByName(ā€œLogical operatorsā€)

Any ideas, why I am unable to do that?

Without seeing your code and since you say it works for the first time through the loop, Iā€™m going to guess you havenā€™t set SementationNode or MasterVolumeNode correctly at the time of setting active effect to logical operators. This might be because you are removing the nodes from the scene after the first iteration?

You might want to consider interacting with the segment editor widget within Slicer and using the python interactor as a way of debugging. Then you could see looking at the GUI what might be going wrong following specific commands.

I have uploaded my code here: https://gist.github.com/ishansaxena45/2ef0ec665e371a0ff8b91c866129f722

I am sorry I could not really identify the problem while debugging it manually.

Hi again,

the problem with clearing the scene still remains. I have uploaded my script here and am also sharing some test data here. Can someone please help?

A few weeks ago Iā€™ve implemented an example script that creates segments from a CT based on predefined intensity ranges. You may use this as is, or as a starting point.

Thanks so much for your code. The problem is now solved. I was wrong in the definitions of the SegmentEditorWidget and not using SegmentEditorNode. Now everything works as expected.

1 Like