Draw tube scripting

Hi all,

I am trying to automate the “Draw Tube” effect in Segment Editor using Python, but I am stuck at two points:

  1. How to pass an existing centerline to the effect programmatically (similar to setting "Radius" or "Interpolation" via setParameter()).

  2. How to trigger the “Import” button automatically via code after setting the parameters.

Here is what I have so far:

segmentEditorWidget = slicer.modules.segmenteditor.widgetRepresentation().self().editor
segmentEditorWidget.setActiveEffectByName("Draw tube")
effect = segmentEditorWidget.activeEffect()

effect.setParameter("Radius", 0.3)
effect.setParameter("Interpolation", "CARDINAL_SPLINE")  # or "LINEAR"

I want to fully automate the workflow: use an existing MarkupsCurveNode as the centerline, generate the tube segment, and “import” it, without any manual interaction.

Could someone please advise:

  • What is the correct parameter name for passing a centerline to the Draw Tube effect?

  • How can I simulate clicking the Import button programmatically in Python?

  • Why does setting "Interpolation" update the GUI but "Radius" does not, and how should I set the radius properly so the interface updates as well?

Thank you in advance!

I’ve just found the solution.


curveNode=getNode('Centerline_Curve_left_2')
effect.self().markupNodeSelector.setCurrentNodeID(curveNode.GetID())
 
effect.self().importButton.click()

Correction:
Radius value is set with:
effect.self().radiusSpinBox.value = 0.3

instead of:
effect.setParameter("Radius", 0.3)

Thank you for posting the solution so that others can learn from it :folded_hands:

2 Likes

Hi to everyone!

Using the DrawTube scriptable effect I found a concerning situation:

def updateModelFromMarkup(self, inputMarkup, outputModel):
“”"Update model to enclose all points in the input markup list“”"interpolationName = self.scriptedEffect.parameter(“Interpolation”)polynomialFitType = slicer.vtkMRMLMarkupsToModelNode.MovingLeastSquaresif interpolationName == “LINEAR”:interpolationType = slicer.vtkMRMLMarkupsToModelNode.Linearelif interpolationName == “CARDINAL_SPLINE”:interpolationType = slicer.vtkMRMLMarkupsToModelNode.CardinalSplineelif interpolationName == “KOCHANEK_SPLINE”:interpolationType = slicer.vtkMRMLMarkupsToModelNode.KochanekSplineelif interpolationName == “GLOBAL_POLYNOMIAL”:interpolationType = slicer.vtkMRMLMarkupsToModelNode.PolynomialpolynomialFitType = slicer.vtkMRMLMarkupsToModelNode.GlobalLeastSquareselif interpolationName == “MOVING_POLYNOMIAL”:interpolationType = slicer.vtkMRMLMarkupsToModelNode.PolynomialpolynomialFitType = slicer.vtkMRMLMarkupsToModelNode.MovingLeastSquares


NumberOfLineSegmentsBetweenControlPoints = self.scriptedEffect.integerParameter("NumberOfLineSegmentsBetweenControlPoints")

markupsToModel = slicer.modules.markupstomodel.logic()
# Create tube from points
markupsToModel.UpdateOutputCurveModel( inputMarkup, outputModel,
  interpolationType, False, self.radius, 8, NumberOfLineSegmentsBetweenControlPoints, True, 3,
  slicer.vtkMRMLMarkupsToModelNode.RawIndices, self.curveGenerator,
  polynomialFitType )

In this fuction (from SegmentEditorDrawTube/SegmentEditorDrawTubeLib/SegmentEditorEffect.py) the number of points in the surface to do the tube faces is set to 8 and this can not be modified. Why? If I set this to 32 for example the generated segment is much smoother than with 8.

In my case, I work with a big cylinder and using 8 points produce a very narrow output.

One option is that someone (or someone with the help of an LLM) adds a parameter in the effect for the resolution of the tube.

The other option is that you open the python file in your installed extension and simply change this number. It is a hack, but since this code is Python and it is interpreted, it will work after restarting Slicer.