Annotate a segment with properties from a popup window

I am new to 3D Slicer. I am trying to figure out the following to add some custom enhancement to the MONAIlabel plugin:

Operating system: Ubuntu Jammy

Slicer version: 5.4

Expected behavior:

  • When using the segment editor, user can do Ctrl + RighClick to annotate the segment under the mouse cursor.
  • A popup dialog show up by Ctrl + RighClick (because the default RightClick already has a popup dialog.
  • User then can check or uncheck items and click “OK” to save the choices.
  • Checkboxes state is saved together with the segment, identified by SegmentID.

Actual behavior: Emtpy

There are several easy way to implement this with a little Python scripting.

If you just want to be able to select a segment at the current mouse position and specify some properties for it, you could implement a segment editor effect, which could observe left-click (or any other) event and when it is triggered then get the segment at the current position and show the popup to enter additional information. You can see it in qSlicerSegmentEditorPaintEffectPrivate::segmentAtPosition how you can get the segment(s) visible at the current position in a Segment Editor effect.

If you want to annotate segments independent from Segment Editor widgets then you can implement a Python scripted Subject Hierarchy plugin. Right-click menu items are populated by these plugins by implementing its viewContextMenuActions and showViewContextMenuActionsForItem methods (see for example in qSlicerSubjectHierarchyMarkupsPlugin). The plugin gets notified when the user right-clicks in the view and you can determine what segments are visible at that position and add items to the context menu accordingly. Context menu actions can have submenus, checkboxes, etc. so you may be able to add everything under a single menu action.

To determine what segments are visible at that position you can do what is done in DataProbe module (that displays the list of segments at the current position in the Data Probe window in the bottom-left corner:

        # collect information from displayable managers
        displayableManagerCollection = vtk.vtkCollection()
        if sliceNode:
            sliceWidget =
            if sliceWidget:
                # sliceWidget is owned by the layout manager
                sliceView = sliceWidget.sliceView()
        aggregatedDisplayableManagerInfo = ''
        for index in range(displayableManagerCollection.GetNumberOfItems()):
            displayableManager = displayableManagerCollection.GetItemAsObject(index)
            infoString = displayableManager.GetDataProbeInfoStringForPosition(xyz) 

Instead of calling GetDataProbeInfoStringForPosition, you would call the GetVisibleSegmentsForPosition(double ras[3], vtkMRMLSegmentationDisplayNode* displayNode, vtkStringArray* segmentIDs, vtkDoubleArray* segmentValues = nullptr) method.

1 Like