# Draw tube scripting

**URL:** <https://discourse.slicer.org/t/draw-tube-scripting/44495>\
**Category:** Support\
**Created:** [September 16, 2025, 12:27pm UTC](https://discourse.slicer.org/t/draw-tube-scripting/44495 "2025-09-16T12:27:47Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![bserrano](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/bserrano/32/17034_2.png) [@bserrano](https://discourse.slicer.org/u/bserrano)\
**Post date:** [September 16, 2025, 12:27pm UTC](https://discourse.slicer.org/t/draw-tube-scripting/44495/1 "2025-09-16T12:27:47Z")

</div>

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:

```auto
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!

---

<div class="post-metadata">

**Author:** ![bserrano](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/bserrano/32/17034_2.png) [@bserrano](https://discourse.slicer.org/u/bserrano)\
**Post date:** [September 16, 2025, 1:01pm UTC](https://discourse.slicer.org/t/draw-tube-scripting/44495/2 "2025-09-16T13:01:29Z")

</div>

I’ve just found the solution.

```auto

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

```

---

<div class="post-metadata">

**Author:** ![bserrano](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/bserrano/32/17034_2.png) [@bserrano](https://discourse.slicer.org/u/bserrano)\
**Post date:** [September 17, 2025, 9:49am UTC](https://discourse.slicer.org/t/draw-tube-scripting/44495/3 "2025-09-17T09:49:28Z")

</div>

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

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

---

<div class="post-metadata">

**Author:** ![cpinter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/cpinter/32/7995_2.png) [@cpinter](https://discourse.slicer.org/u/cpinter)\
**Post date:** [September 17, 2025, 11:26am UTC](https://discourse.slicer.org/t/draw-tube-scripting/44495/4 "2025-09-17T11:26:41Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![SANTIAGO\_PENDON\_MING](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/santiago_pendon_ming/32/66060_2.png) [@SANTIAGO\_PENDON\_MING](https://discourse.slicer.org/u/SANTIAGO_PENDON_MING)\
**Post date:** [February 3, 2026, 8:02am UTC](https://discourse.slicer.org/t/draw-tube-scripting/44495/5 "2026-02-03T08:02:50Z")

</div>

Hi to everyone!

Using the DrawTube scriptable effect I found a concerning situation:

```python
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.

---

<div class="post-metadata">

**Author:** ![cpinter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/cpinter/32/7995_2.png) [@cpinter](https://discourse.slicer.org/u/cpinter)\
**Post date:** [February 5, 2026, 9:28am UTC](https://discourse.slicer.org/t/draw-tube-scripting/44495/6 "2026-02-05T09:28:06Z")

</div>

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.
