# Help for PerkLab's programming example

**URL:** <https://discourse.slicer.org/t/help-for-perklabs-programming-example/11347>\
**Category:** Support\
**Created:** [April 29, 2020, 1:17pm UTC](https://discourse.slicer.org/t/help-for-perklabs-programming-example/11347 "2020-04-29T13:17:22Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mau_igna_06/32/9056_2.png) [@mau\_igna\_06](https://discourse.slicer.org/u/mau_igna_06)\
**Post date:** [April 29, 2020, 1:17pm UTC](https://discourse.slicer.org/t/help-for-perklabs-programming-example/11347/1 "2020-04-29T13:17:22Z")

</div>

Hi, I have followed this [tutorial](https://github.com/PerkLab/PerkLabBootcamp/blob/master/Doc/day3_2_SlicerProgramming.pptx?raw=true) . I have finished the code for the proposed exercise: “getting a sphere between two fiducial points”. The problem is know how to write the code to get the sphere between the two fiducials but I don’t know in which class or position of the class to append my code. (I wrote “Added by me” everywhere I made a change to the original example-code to make it more searchable)

import os  
import unittest  
import vtk, qt, ctk, slicer  
from slicer.ScriptedLoadableModule import \*  
import logging

# 

# ModuleOne

# 

class ModuleOne(ScriptedLoadableModule):  
“”“Uses ScriptedLoadableModule base class, available at:  
[https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py](https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py)  
“””

def **init** (self, parent):  
ScriptedLoadableModule. **init** (self, parent)  
self.parent.title = “ModuleOne” # TODO make this more human readable by adding spaces  
self.parent.categories = [“Examples”]  
self.parent.dependencies = []  
self.parent.contributors = [“John Doe (AnyWare Corp.)”] # replace with “Firstname Lastname (Organization)”  
self.parent.helpText = “”"  
This is an example of scripted loadable module bundled in an extension.  
It performs a simple thresholding on the input volume and optionally captures a screenshot.  
“”"  
self.parent.helpText += self.getDefaultModuleDocumentationLink()  
self.parent.acknowledgementText = “”"  
This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc.  
and Steve Pieper, Isomics, Inc. and was partially funded by NIH grant 3P41RR013218-12S1.  
“”" # replace with organization, grant and thanks.

# 

# ModuleOneWidget

# 

class ModuleOneWidget(ScriptedLoadableModuleWidget):  
“”“Uses ScriptedLoadableModuleWidget base class, available at:  
[https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py](https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py)  
“””

def setup(self):  
ScriptedLoadableModuleWidget.setup(self)

```
# Load widget from .ui file (created by Qt Designer)
uiWidget = slicer.util.loadUI(self.resourcePath('UI/ModuleOne.ui'))
self.layout.addWidget(uiWidget)
self.ui = slicer.util.childWidgetVariables(uiWidget)

self.ui.inputSelector.setMRMLScene(slicer.mrmlScene)
self.ui.outputSelector.setMRMLScene(slicer.mrmlScene)

# connections
self.ui.applyButton.connect('clicked(bool)', self.onApplyButton)
self.ui.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
self.ui.outputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
#Added by me
self.observedMarkupNode = None
self.markupsObserverTag = None
self.ui.enableScreenshotsFlagCheckBox.connect("toggled(bool)", self.onEnableAutoUpdate)

# Add vertical spacer
self.layout.addStretch(1)

# Refresh Apply button state
self.onSelect()

#Added by me
self.a = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode","sphere")
self.m = vtk.vtkSphereSource()
self.m.Update()
self.a.SetAndObservePolyData(self.m.GetOutput())

```

def cleanup(self):  
pass

def onSelect(self):  
self.ui.applyButton.enabled = self.ui.inputSelector.currentNode()

def onEnableAutoUpdate(self, autoUpdate):  
if self.markupsObserverTag:  
self.observedMarkupNode.RemoveObserver(self.markupsObserverTag)  
self.observedMarkupNode = None  
self.markupsObserverTag = None  
if autoUpdate and self.ui.inputSelector.currentNode:  
self.observedMarkupNode = self.ui.inputSelector.currentNode()  
self.markupsObserverTag = self.observedMarkupNode.AddObserver(  
vtk.vtkCommand.ModifiedEvent, self.onMarkupsUpdated)

def onMarkupsUpdated(self, caller=None, event=None):  
self.onApplyButton()

def onApplyButton(self):  
logic = ModuleOneLogic()  
enableScreenshotsFlag = self.ui.enableScreenshotsFlagCheckBox.checked  
imageThreshold = self.ui.imageThresholdSliderWidget.value  
logic.run(self.ui.inputSelector.currentNode(), self.ui.outputSelector.currentNode(), imageThreshold, enableScreenshotsFlag)  
#Added by me  
self.m.Update()

# 

# ModuleOneLogic

# 

class ModuleOneLogic(ScriptedLoadableModuleLogic):  
“”“This class should implement all the actual  
computation done by your module. The interface  
should be such that other python code can import  
this class and make use of the functionality without  
requiring an instance of the Widget.  
Uses ScriptedLoadableModuleLogic base class, available at:  
[https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py](https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py)  
“””

def hasImageData(self,volumeNode):  
“”“This is an example logic method that  
returns true if the passed in volume  
node has valid image data  
“””  
if not volumeNode:  
logging.debug(‘hasImageData failed: no volume node’)  
return False  
if volumeNode.GetImageData() is None:  
logging.debug(‘hasImageData failed: no image data in volume node’)  
return False  
return True

def isValidInputOutputData(self, inputVolumeNode, outputVolumeNode):  
“”“Validates if the output is not the same as input  
“””  
if not inputVolumeNode:  
logging.debug(‘isValidInputOutputData failed: no input volume node defined’)  
return False  
if not outputVolumeNode:  
logging.debug(‘isValidInputOutputData failed: no output volume node defined’)  
return False  
if inputVolumeNode.GetID()==outputVolumeNode.GetID():  
logging.debug(‘isValidInputOutputData failed: input and output volume is the same. Create a new volume for output to avoid this error.’)  
return False  
return True

#Added by me  
def setSphereRadiusAndCenter(r,c):  
self.m = vtk.vtkSphereSource()  
self.m.SetRadius®  
self.m.SetCenter(c[0],c[1],c[2])  
self.m.Update()  
return

def setSphereTouchingFiducials(self):  
import numpy  
f = slicer.util.getNode(‘F’)  
pos0 = [0,0,0]  
pos1 = [0,0,0]  
if f.GetNumberOfMarkups() == 2:  
f.GetNthFiducialPosition(0,pos0)  
f.GetNthFiducialPosition(1,pos1)  
p0 = numpy.array(pos0)  
p1 = numpy.array(pos1)  
radius = numpy.linalg.norm(p0-p1)/2.0  
center = (p0+p1)/2.0  
self.setSphereRadiusAndCenter(radius,center)  
else:  
logging.info(‘Error: Incorrect number of fiducial points’)

def run(self, inputVolume, outputVolume, imageThreshold, enableScreenshots=0):  
“”"  
Run the actual algorithm  
“”"  
self.setSphereTouchingFiducials()

```
return True

```

class ModuleOneTest(ScriptedLoadableModuleTest):  
“”"  
This is the test case for your scripted module.  
Uses ScriptedLoadableModuleTest base class, available at:  
[https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py](https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py)  
“”"

def setUp(self):  
“”" Do whatever is needed to reset the state - typically a scene clear will be enough.  
“”"  
slicer.mrmlScene.Clear(0)

def runTest(self):  
“”“Run as few or as many tests as needed here.  
“””  
self.setUp()  
self.test\_ModuleOne1()

def test\_ModuleOne1(self):  
“”" Ideally you should have several levels of tests. At the lowest level  
tests should exercise the functionality of the logic with different inputs  
(both valid and invalid). At higher levels your tests should emulate the  
way the user would interact with your code and confirm that it still works  
the way you intended.  
One of the most important features of the tests is that it should alert other  
developers when their changes will have an impact on the behavior of your  
module. For example, if a developer removes a feature that you depend on,  
your test should break so they know that the feature is needed.  
“”"

```
self.delayDisplay("Starting the test")
#
# first, get some data
#
import SampleData
SampleData.downloadFromURL(
  nodeNames='FA',
  fileNames='FA.nrrd',
  uris='http://slicer.kitware.com/midas3/download?items=5767')
self.delayDisplay('Finished with download and loading')

volumeNode = slicer.util.getNode(pattern="FA")
logic = ModuleOneLogic()
self.assertIsNotNone( logic.hasImageData(volumeNode) )
self.delayDisplay('Test passed!')
```

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mau_igna_06/32/9056_2.png) [@mau\_igna\_06](https://discourse.slicer.org/u/mau_igna_06)\
**Post date:** [April 29, 2020, 5:03pm UTC](https://discourse.slicer.org/t/help-for-perklabs-programming-example/11347/2 "2020-04-29T17:03:14Z")

</div>

Maybe someone can post the code of the solution to the exercise if reading the code above is too much work

---

<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:** [April 29, 2020, 8:53pm UTC](https://discourse.slicer.org/t/help-for-perklabs-programming-example/11347/3 "2020-04-29T20:53:00Z")

</div>

The solution is posted in the same repository.

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mau_igna_06/32/9056_2.png) [@mau\_igna\_06](https://discourse.slicer.org/u/mau_igna_06)\
**Post date:** [April 30, 2020, 4:50pm UTC](https://discourse.slicer.org/t/help-for-perklabs-programming-example/11347/4 "2020-04-30T16:50:58Z")

</div>

Hi Andras. The task is given on page 47 of [the tutorial](https://github.com/PerkLab/PerkLabBootcamp/blob/master/Doc/day3_2_SlicerProgramming.pptx) and there is no solution there. I also searched [here](https://github.com/PerkLab/PerkLabBootcamp/tree/master/Doc) with no results. Could you post the link to the solution?

---

<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:** [April 30, 2020, 5:11pm UTC](https://discourse.slicer.org/t/help-for-perklabs-programming-example/11347/5 "2020-04-30T17:11:01Z")

</div>

All information that is needed to create the module is in the slides and students develop their module on their own, and I have just discovered that we stopped providing a “solution” 3 years ago. You can download that old solution (using old templates, does not leverage recent Slicer features, etc.) [here](https://1drv.ms/u/s!Arm_AFxB9yqHr7clmSSvwLxVByo6EQ?e=lLqJdr).
