Using segment editor programmatically to perform intersection gives strange result

I was performing logical operations on some segmentations programmatically, when I stumbled across a bizarre occurrence: when performing intersection, I had to rerun my intersection function (with the exact same parameters) to completely perform the intersection–running it once resulted in a partially intersected output. I checked using the GUI’s segment editor, and it was able to perform the intersection in one go. I am wondering if there is a parameter I need to change in my intersection and/or setup functions.

For reference, I will paste my setup and intersection code below, along with the script I ran to get this strange output:

def setupSegmentEditor():
    segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
    segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
    slicer.mrmlScene.AddNode(segmentEditorNode)
    segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
    workHorse = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentationNode", "workHorse")  # segmentation node that will do all processing
    masterVolumeNode = slicer.mrmlScene.GetFirstNodeByClass("vtkMRMLScalarVolumeNode")  # background volume (irrelevant, but necessary to define)
    assert(masterVolumeNode is not None)
    segmentEditorWidget.setSegmentationNode(workHorse)
    segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
    segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)
    segmentEditorWidget.setActiveEffectByName('Logical operators')
    segmentationLogic = slicer.modules.segmentations.logic()
    segmentEditorNode.SetMaskMode(workHorse.EditAllowedInsideAllSegments)
    segmentEditorNode.SetOverwriteMode(segmentEditorNode.OverwriteAllSegments)
    return segmentEditorWidget, segmentEditorNode, workHorse, masterVolumeNode, segmentationLogic

def intersectSegments(segmentEditorNode, segmentEditorWidget, baseSegmentID, toIntersectSegmentID):
  segmentEditorNode.SetSelectedSegmentID(baseSegmentID)
  segmentEditorWidget.setActiveEffectByName('Logical operators')
  effect = segmentEditorWidget.activeEffect()
  effect.setParameter("Operation", SegmentEditorEffects.LOGICAL_INTERSECT)
  effect.setParameter("BypassMasking",1)
  effect.setParameter("ModifierSegmentID",toIntersectSegmentID)
  effect.self().onApply()

# script
segmentEditorWidget, segmentEditorNode, workHorse, masterVolumeNode, segmentationLogic = setupSegmentEditor()

# works
intersectSegments(segmentEditorNode, segmentEditorWidget, baseSegmentID, toIntersectSegmentID)
intersectSegments(segmentEditorNode, segmentEditorWidget, baseSegmentID, toIntersectSegmentID)

# Does not work
intersectSegments(segmentEditorNode, segmentEditorWidget, baseSegmentID, toIntersectSegmentID)

If it would help, I would be happy to provide the segmentationNode and segmentIDs I was using. Thanks!

I found something that may help answer this question. Changing the master volume affects the result of the intersection operation without changing other parameters. How does the choice of master volume affect, say, the logical intersection operation between two segmentations?

I suppose to make this question more broadly applicable to the community, what I am trying to do is take segmentations which are registered to one another (but from different source volumes) and perform logical operations to perform a union or an intersection. In that sense, there is no “master volume”, as the segmentations are coming from separate volumes. The logical operations seem like they might depend on the master volume, but I would prefer the operation to be agnostic to the choice of master volume.

But the geometry of the segmentation needs to come from somewhere. That’s what the master volume provides. If you two volumes are registered, then you should be in the same physical space, and you should be able to use either one of them.

I see–it makes sense that the segmentation needs a geometry as a reference. A quick clarifying question: my volumes are registered in the sense that they are in the correct location & orientation in world coordinates. However, they have different relative orientations (and positions). Is it still sufficient to choose either volume as the master volume? And thank you very much!