Using Segment Editor effects programmatically

Hi all,
I’m wondering how to script some simple steps from the Segment Editor. I know that there are a few recipes from Andras and others in this forum, which are great, thanks for the continuous support.
In one of the recipes, there is a good example for thresholding:

#Thresholding
segmentEditorWidget.setActiveEffectByName("Threshold")
effect = segmentEditorWidget.activeEffect()
effect.setParameter("MinimumThreshold","35")
effect.setParameter("MaximumThreshold","695")
effect.self().onApply()

Now, the effect I wanna use programmatically is “Logical operators”, specifically I wanna create a hull, i.e. one segment that sums up all the other segments (in other words, a logical_or of all segments contained in the segmentation node), which is easy to automate. The steps I need to do are:

  1. Create a new segment (via node_seg.GetSegmentation().AddSegment(‘hull’))
  2. Copy the first segment into ‘hull’
  3. Add all other segments into ‘hull’.

For this, and other simple steps… Is there a documentation on all the parameters of all effects.
I was trying something like:

segmentEditorWidget.setActiveEffectByName("Logical operators")
effect = segmentEditorWidget.activeEffect()
effect.setParameter('Operation','Copy')

But I have no idea whether these parameters are correct (and there are no error messages, even if I enter random strings).

Thanks in advance!

I found some more information in this thread, and after activating the the “Logical operators” operations one-by-one, I got this list of parameters:

  Logical operators.BypassMasking:1
  Logical operators.ModifierSegmentID:Segment_11
  Logical operators.Operation:COPY
  Logical operators.Operation:UNION
  Logical operators.Operation:SUBTRACT
  Logical operators.Operation:INTERSECT
  Logical operators.Operation:INVERT
  Logical operators.Operation:CLEAR
  Logical operators.Operation:FILL

I will try a bit more, but for future reference, is there a documentation page with the full list of these parameters?

It would be nice to create separate documentation for these - contributions are welcome!

@jcfr, do you have any suggestions for documenting segment editor effect parameters? It would be nice if documentation would be available at the same place for C++ and Python effects. I could create a new markdown file in developer_guide and describe parameters of the effects there, but it would be a bit nicer if the description could be in each effect’s .py or .h file. Could ReadTheDocs fetch documentation from segment editor effect source files (currently Developer guide does not seem to be able to get anything from there).

Until separate documentation is written, then open source code is the documentation. You can find the relevant file by Google search. For example first hit when searching for github slicer Logical operators takes you to SegmentEditorLogicalEffect.py. For all Segment Editor effects, setMRMLDefaults method contains the list of parameters that the effect uses. If there are constants then they are typically defined at the bottom of the file.

1 Like

Could you please elaborate a bit more on calling python effects from C++, for example, what is the C++ equivalence of effect.self.OnApply()?

See this topic for details about how to run Python code from C++:

For more complex Python calls, search for “pythonmanager” in Slicer source code.

Hi Andras,
few weeks ago, I found an alternative way to solve my problem, but now I had to come back to using segment editor effects, in more detail. This time I managed to solve a few problems, one of them was how to use the “logical operators” effect programmatically. You already provide a lot of examples for scripted effects here, but there is no example for the logical effects. Actually it’s simple, but I needed to sift through the source code a bit. Maybe this example will help others to save some time.

# Run segment editor effects from script

# Prerequisites 1/2: 
# Create segment editor widget and node to get scripted access to effects
segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
segmentEditorNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentEditorNode")
segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)

# Prerequisites 2/2:
# nvol ... the reference volume node for the segmentation
# nseg ... the segmentation node
# 'tgtseg' is the name of the target segment, i.e. the region that is being edited
# 'srcseg' is the name of the source segment, i.e. the region from which information is being "transferred" by the logical operator
# Setting up the nodes to be edited
segmentEditorWidget.setSegmentationNode(nseg)
segmentEditorWidget.setMasterVolumeNode(nvol)
# Set overwrite mode: 0/1/2 -> overwrite all/visible/none
segmentEditorNode.SetOverwriteMode(2) # i.e. "allow overlap" in UI
# Get the segment IDs
segid_tgt = nseg.GetSegmentation().GetSegmentIdBySegmentName('tgtseg')
segid_src = nseg.GetSegmentation().GetSegmentIdBySegmentName('srcseg')

# Running the effect:
# The logical operation is set via strings
# 'COPY', 'UNION', 'INTERSECT', 'SUBTRACT', 'INVERT', 'CLEAR', 'FILL'
# (see: https://apidocs.slicer.org/master/SegmentEditorLogicalEffect_8py_source.html)    
segmentEditorNode.SetSelectedSegmentID(segid_tgt)
segmentEditorWidget.setActiveEffectByName("Logical operators")
effect = segmentEditorWidget.activeEffect()
effect.setParameter("Operation","COPY") # change the operation here
effect.setParameter("ModifierSegmentID",segid_src)
effect.self().onApply()
7 Likes

Thanks a lot for sharing.