Minimal draw tube effect

Hi

I have a side panel with two widgets laid out vertically: first one is a groupbox to execute simplified segmentation actions by using the second widget, a qMRMLSegmentEditorWidget, that’s hidden.

I have to use the drawTubeEffect from the 2nd widget (only the buttons inside red marks):

I’d like to move the widgets in red to my firstly mentioned widget to keep all connections/logic working.

And I’d like to avoid duplicating the GUI of the segment editor widget inside the first widget to achieve that (but I’ll do it if there is not a simpler way to get it working)

Could you advice? Thanks :slight_smile:

Widgets are not guaranteed to work if they are extracted from the widget that is managing them. Developers of all the reusable high-level widgets assume that the internal widgets are only accessed and displayed through the public API that the widgets provides, otherwise they would never know what they can change in their implementation.

I would recommend to add whatever widgets you need to your own module. Code duplication should be minimal, because you only need to add a markup place widget and a push-button. If you find that you need to add more than a couple of lines of code then you can suggest changes to refactor the Draw Tube effect that avoids any need for substantial code duplication.

2 Likes

This concerns the default segment editor widget as a suggestion, yours is hidden, but it is the same widget class.

The ‘place fiducial’ widget may be obtained thus:

sew = slicer.modules.SegmentEditorWidget.editor
sew.setActiveEffectByName("Draw tube")
dt = sew.activeEffect()
fpt = dt.self().fiducialPlacementToggle

On a quick try, it seems to work more or less when reparented:

fpt.setParent(MyContainerWidget)

If the segment editor is next shown and the ‘Draw tube’ effect is activated with the mouse, then the scene of the re-parented point placement widget needs to be set again. But yours is private and hidden.

All this may just worth a try, may be it’s too much of an ugly hack as @lassoan advised.

Regards.

1 Like

Thanks for your answer

A problem arise from otherwise straightforward solution:

  • cannot access all internal widgets of the above markupsPlaceWidget to disconnect the default established signals and proxy (i.e. connect) them to the effect’s markupsPlaceWidget slots (i.e. both default and draw-tube-logic ones)

Don’t you agree?

All the widgets are synchronized via MRML nodes. You should not need to do such low level things like connect/disconnect signals. Let me know if you run into any specific problem.

1 Like

Right :ok_hand:

My example:

import SampleData
# Load master volume
sampleDataLogic = SampleData.SampleDataLogic()
masterVolumeNode = sampleDataLogic.downloadCTChest()
# Create segmentation
segmentationNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentationNode")
segmentationNode.CreateDefaultDisplayNodes()
segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(masterVolumeNode)
addedSegmentID = segmentationNode.GetSegmentation().AddEmptySegment("test")

slicer.util.selectModule("SegmentEditor")

segmentEditorWidget = mainWindow().findChildren('qMRMLSegmentEditorWidget')[0]
segmentEditorWidget.setActiveEffectByName('Draw tube')
drawTubeEffect = segmentEditorWidget.activeEffect()
drawTubeEffect.self().logic.radius=15
drawTubeEffect.self().updateModelFromSegmentMarkupNode()

Then, I expected just adding points like this would not work, but it does:

drawTubeEffect.self().segmentMarkupNode.AddControlPoint([0,0,0])
drawTubeEffect.self().segmentMarkupNode.AddControlPoint([100,0,0])
drawTubeEffect.self().segmentMarkupNode.AddControlPoint([0,200,0])
drawTubeEffect.self().segmentMarkupNode.AddControlPoint([0,0,-300])
drawTubeEffect.self().segmentMarkupNode.AddControlPoint([0,-400,0])

Thanks!

1 Like