# Create a mesh in python script

**URL:** <https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543>\
**Category:** Support\
**Tags:** segmentation\
**Created:** [November 28, 2017, 4:31pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543 "2017-11-28T16:31:56Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Frederic](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/frederic/32/4907_2.png) [@Frederic](https://discourse.slicer.org/u/Frederic)\
**Post date:** [November 28, 2017, 4:31pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/1 "2017-11-28T16:31:56Z")

</div>

Hi all,  
Is-it possible since a “head\_T1.nii” to mesh only the scalp by “Segment editor tool” from Python scripts?  
Thanks in advance,  
Frederic

---

<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:** [November 28, 2017, 4:49pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/2 "2017-11-28T16:49:50Z")

</div>

You need to be able to come up with a quasi-automatic way of doing it first. Do you know what effects would you use, in what order, and with what parameters?

Then it will be possible to automatize it from python, yes.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [November 28, 2017, 8:48pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/3 "2017-11-28T20:48:34Z")

</div>

Once you know what effects you’ll use and how, follow these examples for running Segment Editor effects from script: [https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#How\_to\_run\_segment\_editor\_effects\_from\_a\_script](https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#How_to_run_segment_editor_effects_from_a_script)

---

<div class="post-metadata">

**Author:** ![Frederic](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/frederic/32/4907_2.png) [@Frederic](https://discourse.slicer.org/u/Frederic)\
**Post date:** [November 30, 2017, 5:17pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/4 "2017-11-30T17:17:09Z")

</div>

Thanks to both of you.  
I would like to use 1/ threshold effect, with range from 110 to 400 and with default to other parameters and 2/ Smoothing with Gaussian with 2 mm sd.  
So It would be:  
segmentEditorWidget.setActiveEffectByName(“Threshold”, 110,400)  
segmentEditorWidget.setActiveEffectByName(“Smmoting”,"Gaussian ", 2)

Two more question, please.  
Is there in 3dslicer, a RAS to MNI coordinate conversion function?  
Is there a button to trigger the shift key linked motion?

Thanks, once again.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [November 30, 2017, 5:45pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/5 "2017-11-30T17:45:18Z")

</div>

> [@Frederic](#):
>
> So It would be:
> 
> segmentEditorWidget.setActiveEffectByName(“Threshold”, 110,400)
> 
> segmentEditorWidget.setActiveEffectByName(“Smmoting”,"Gaussian ", 2)

It’s a couple of more lines (setActiveEffectByName only activates an effect). See the examples that I linked above.

> [@Frederic](#):
>
> Is there in 3dslicer, a RAS to MNI coordinate conversion function?

RAS is anatomical coordinate system (right-anterior-superior). What is MNI coordinate system?

> [@Frederic](#):
>
> Is there a button to trigger the shift key linked motion?

You can easily add a shortcut for jump to a current cursor position, just open the Python console and copy-paste these lines to make Ctrl+M jump to current slice position:

```
def jumpToCursor():
  ras=[0,0,0]
  slicer.mrmlScene.GetFirstNodeByClass('vtkMRMLCrosshairNode').GetCursorPositionRAS(ras)
  slicer.modules.markups.logic().JumpSlicesToLocation(ras[0], ras[1], ras[2], slicer.vtkMRMLCrosshairNode.JumpSlice)

shortcut = qt.QShortcut(slicer.util.mainWindow())
shortcut.setKey(qt.QKeySequence("Ctrl+M"))
shortcut.connect( 'activated()', jumpToCursor )

```

If you want this feature permanently then add it to your application startup script (edit it in menu: Edit / Application settings / Application startup script).

---

<div class="post-metadata">

**Author:** ![Frederic](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/frederic/32/4907_2.png) [@Frederic](https://discourse.slicer.org/u/Frederic)\
**Post date:** [December 1, 2017, 2:53pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/6 "2017-12-01T14:53:19Z")

</div>

Thanks once again.

1. Ok for the “setActiveEffectByName”, I will try as soon as possible.
2. MNI coordinates is a normalized coordinates (explain here: [http://neuroimage.usc.edu/brainstorm/CoordinateSystems](http://neuroimage.usc.edu/brainstorm/CoordinateSystems))
3. Thanks for this script!

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [December 1, 2017, 4:53pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/7 "2017-12-01T16:53:32Z")

</div>

From [CoordinateSystems - Brainstorm](http://neuroimage.usc.edu/brainstorm/CoordinateSystems#MNI_coordinates) website:

> To be able to get “MNI coordinates” for individual brains, an extra step of normalization is required.  
> The method we use in Brainstorm is based on an affine co-registration with the MNI ICBM152 template from the SPM software.

This means you can easily get these coordinates in Slicer. You just have to download MNI ICBM152 image and register it to your volume in Slicer. You can either use “General registration (BRAINS)” module or install SlicerElastix extension and use “General registration (Elastix)” module. For Elastix, I think default configuration file are available for rigid or b-spline transforms, so you need to change ElastixParameterSetDatabase.xml to create a preset that uses Parameters\_Affine.txt (you can copy-paste the “generic rigid” preset and change Parameters\_Rigid.txt to Parameters\_Affine.txt).

---

<div class="post-metadata">

**Author:** ![Frederic](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/frederic/32/4907_2.png) [@Frederic](https://discourse.slicer.org/u/Frederic)\
**Post date:** [December 4, 2017, 5:44pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/8 "2017-12-04T17:44:45Z")

</div>

Thanks Andras,  
It works fine, but the registration is very rigid.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [December 4, 2017, 6:11pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/9 "2017-12-04T18:11:41Z")

</div>

“generic rigid” preset uses rigid transform. If you need affine or warping transform then you have to modify registration parameter files as I described above.

---

<div class="post-metadata">

**Author:** ![Frederic](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/frederic/32/4907_2.png) [@Frederic](https://discourse.slicer.org/u/Frederic)\
**Post date:** [December 5, 2017, 4:36pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/10 "2017-12-05T16:36:15Z")

</div>

Perfect thanks Andras.  
is-it possible to make this procedure by a Python script?

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [December 5, 2017, 5:06pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/11 "2017-12-05T17:06:48Z")

</div>

Python scripting is not needed. You can edit preset files directly using a text editor.

Of course, everything is exposed to Python, so if you need to run registration from your module then you can do that. An example for that is [Sequence Registration](https://github.com/moselhy/SlicerSequenceRegistration) module, which uses SlicerElastix internally for registering different time points of a 4D volume to each other.

---

<div class="post-metadata">

**Author:** ![Frederic](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/frederic/32/4907_2.png) [@Frederic](https://discourse.slicer.org/u/Frederic)\
**Post date:** [December 6, 2017, 11:52am UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/12 "2017-12-06T11:52:18Z")

</div>

Yes, I have change manually the xml file. 😉  
My python script does no work and I do not understand why, could you help me please?

```
import Elastix
FixedVolume= slicer.util.loadVolume('avg152T1.nii')
MovingVolume= slicer.util.loadVolume('t0697_t1_s03.nii')
outputVolume = slicer.vtkMRMLScalarVolumeNode()
slicer.mrmlScene.AddNode(outputVolume)
outputVolume.CreateDefaultDisplayNodes()
logic = Elastix.ElastixLogic()
RegistrationPresets_ParameterFilenames = 5
parameterFilenames = logic.getRegistrationPresets()[0][RegistrationPresets_ParameterFilenames]
logic.registerVolumes(FixedVolume, MovingVolume, parameterFilenames = parameterFilenames, outputVolumeNode = outputVolume)
```

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [December 6, 2017, 12:28pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/13 "2017-12-06T12:28:11Z")

</div>

What happens? Do you get any error message?

---

<div class="post-metadata">

**Author:** ![Frederic](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/frederic/32/4907_2.png) [@Frederic](https://discourse.slicer.org/u/Frederic)\
**Post date:** [December 6, 2017, 12:54pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/14 "2017-12-06T12:54:56Z")

</div>

The error is:

```auto
> Traceback (most recent call last):
> File "<console>", line 1, in <module>
> File "C:/Users/briend/AppData/Roaming/NA-MIC/Extensions-26489/SlicerElastix/lib/Slicer-4.8/qt-scripted-modules/Elastix.py", line 554, in registerVolumes
> slicer.util.saveNode(volumeNode, filePath, {"useCompression": False})
> File "C:\Program Files\Slicer 4.8.0\bin\Python\slicer\util.py", line 433, in saveNode
> properties["nodeID"] = node.GetID();
> AttributeError: 'bool' object has no attribute 'GetID'

```

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [December 6, 2017, 2:55pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/15 "2017-12-06T14:55:50Z")

</div>

The problem is that `loadVolume` by default returns success=True/False. See an example for getting the loaded volume node here: [https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Load\_volume\_from\_file](https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Load_volume_from_file)

---

<div class="post-metadata">

**Author:** ![Frederic](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/frederic/32/4907_2.png) [@Frederic](https://discourse.slicer.org/u/Frederic)\
**Post date:** [December 6, 2017, 3:21pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/16 "2017-12-06T15:21:45Z")

</div>

Thanks Andras.  
The correct scipt (which works well) is thus:

> import Elastix  
> FixedVolume= slicer.util.loadVolume(‘L:/briend/Olivier\_Slicer\_try1/avg152T1.nii’, returnNode=True)  
> n=slicer.util.getNode(‘avg15\*’)  
> MovingVolume= slicer.util.loadVolume(‘L:/briend/Olivier\_Slicer\_try1/t0697\_t1\_s03.nii’, returnNode=True)  
> m=slicer.util.getNode(‘t06\*’)  
> outputVolume = slicer.vtkMRMLScalarVolumeNode()  
> slicer.mrmlScene.AddNode(outputVolume)  
> outputVolume.CreateDefaultDisplayNodes()  
> logic = Elastix.ElastixLogic()  
> RegistrationPresets\_ParameterFilenames = 5  
> parameterFilenames = logic.getRegistrationPresets()[0][RegistrationPresets\_ParameterFilenames]  
> logic.registerVolumes(n, m, parameterFilenames = parameterFilenames, outputVolumeNode = outputVolume)

---

<div class="post-metadata">

**Author:** ![Frederic](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/frederic/32/4907_2.png) [@Frederic](https://discourse.slicer.org/u/Frederic)\
**Post date:** [December 7, 2017, 3:09pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/17 "2017-12-07T15:09:49Z")

</div>

I am confuse to ask you all theses questions, but I do not arrive to create my mesh.  
Nothing happen after my script:

```auto
import SampleData
sampleDataLogic = SampleData.SampleDataLogic()
masterVolumeNode = sampleDataLogic.downloadMRBrainTumor1()

# Create segmentation
segmentationNode = slicer.vtkMRMLSegmentationNode()
slicer.mrmlScene.AddNode(segmentationNode)
segmentationNode.CreateDefaultDisplayNodes() # only needed for display
segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(masterVolumeNode)
#segmentationNode.AddSegmentFromClosedSurfaceRepresentation(masterVolumeNode, "skin", [1,0,1]) **# I do not understand how to assign my volume here**

# Create segment editor to get access to effects
segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
slicer.mrmlScene.AddNode(segmentEditorNode)
segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
segmentEditorWidget.setSegmentationNode(segmentationNode)
segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

# Run segmentation
segmentEditorWidget.setActiveEffectByName("Threshold")
effect = segmentEditorWidget.activeEffect()
effect.setParameter("MinimumThreshold",35)
effect.setParameter("MaximumThreshold",695)
segmentEditorWidget.setActiveEffectByName('Smooting')
effect.setParameter('Gaussian', 2)

effect.self().onPreview()
effect.self().onApply()

# Clean up
slicer.mrmlScene.RemoveNode(segmentEditorNode)

# Make segmentation results nicely visible in 3D
segmentationDisplayNode = segmentationNode.GetDisplayNode()

```

@lassoan do you know why?  
Thanks in advance

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [December 8, 2017, 4:32pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/18 "2017-12-08T16:32:23Z")

</div>

There were a couple of small issues. Here is a working version:

```
import SampleData
sampleDataLogic = SampleData.SampleDataLogic()
masterVolumeNode = sampleDataLogic.downloadMRBrainTumor1()

# Create segmentation
segmentationNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentationNode")
segmentationNode.CreateDefaultDisplayNodes() # only needed for display
segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(masterVolumeNode)
addedSegmentID = segmentationNode.GetSegmentation().AddEmptySegment("skin")

# Create segment editor to get access to effects
segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
segmentEditorNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentEditorNode")
segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
segmentEditorWidget.setSegmentationNode(segmentationNode)
segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

# Thresholding
segmentEditorWidget.setActiveEffectByName("Threshold")
effect = segmentEditorWidget.activeEffect()
effect.setParameter("MinimumThreshold","35")
effect.setParameter("MaximumThreshold","695")
effect.self().onApply()

segmentEditorWidget.setActiveEffectByName("Smoothing")
effect = segmentEditorWidget.activeEffect()
effect.setParameter("SmoothingMethod", "MEDIAN")
effect.setParameter("KernelSizeMm", 11)
effect.self().onApply()

# Clean up
segmentEditorWidget = None
slicer.mrmlScene.RemoveNode(segmentEditorNode)

# Make segmentation results visible in 3D
segmentationNode.CreateClosedSurfaceRepresentation()

# Write to STL file
surfaceMesh = segmentationNode.GetClosedSurfaceRepresentation(addedSegmentID)
writer = vtk.vtkSTLWriter()
writer.SetInputData(surfaceMesh)
writer.SetFileName("c:/tmp/something.stl")
writer.Update()

```

For future reference: I’ve saved this example and will maintain it on [this page](https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9).

---

<div class="post-metadata">

**Author:** ![Frederic](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/frederic/32/4907_2.png) [@Frederic](https://discourse.slicer.org/u/Frederic)\
**Post date:** [December 8, 2017, 5:40pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/19 "2017-12-08T17:40:18Z")

</div>

Once again, thanks @lassoan. Your generosity makes me blush.  
Little problem however, nothing happen by the smoothing parameter.

Then, how save this volume segmented (after Model Maker) in .stl format in python?  
Thanks in advance!

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [December 8, 2017, 6:30pm UTC](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543/20 "2017-12-08T18:30:14Z")

</div>

If you use Segmentations, “model making” (and real-time updates to the generated 3D mesh) are done automatically. I’ve updated the code sample above to smooth with the correct parameter names and added STL export at the end.

[Next page](https://discourse.slicer.org/t/create-a-mesh-in-python-script/1543.md?page=2)
