Slicer4 ProgrammingTutorial SPujol-SPieper Nightly
Slicer4 ProgrammingTutorial SPujol-SPieper Nightly
Slicer4 ProgrammingTutorial SPujol-SPieper Nightly
in
Slicer4
Ph.D.
Sonia Pujol,
Surgical Planning Laboratory,
Harvard Medical School
• An open-source environment
for soNware development
Image Data on
Disk (DICOM,
Nifti, nrrd…)
Manipulation
with VTK
MRML Scene
Manipulation
MRML: Medical Reality Markup Language, with ITK
the Slicer Data Representation (Slicer CLI)
• Command Comple:on:
Ø Tab Key
• Input History:
Ø Up/Down Arrow Keys
a = slicer.util.array('spgr’)
àUses the slicer.u:l package to
return a numpy array of the image
àThe variable 'a' is a numpy ndarray
of the volume data we just loaded
print(a)
print(a.min(),a.max())
àUse numpy array methods
to analyze and process the data
def toggle():
n = slicer.util.getNode('spgr')
a = slicer.util.array('spgr')
a[:] = a.max() - a
n.Modified()
print('Toggled')
toggle()
• def toggle():
Ø Defines a python func:on
Ø Body of func:on performs element-wise math on
en:re volume
Ø Easy mix of scalar and volume math
b = qt.QPushButton('Toggle')
b.connect('clicked()',toggle)
b.show()
What do you think will happen when you run this code?
What about when you push the button?
S.Pujol, Ph.D. - S.Pieper, Ph.D.
NA-MIC ARR 2012-2017
Result with budon toggling
Original Result
Put the slicer view windows front to see the changes
S.Pujol, Ph.D. - S.Pieper, Ph.D.
NA-MIC ARR 2012-2017
In More Detail
Module Widget
(GUI)
Module Logic
(processing, no
user interface)
Module Test
(automatic self-
tests)
S.Pujol, Ph.D. - S.Pieper, Ph.D.
NA-MIC ARR 2012-2017
Update Module Descrip:on
class HelloPython(ScriptedLoadableModule):
"""Uses ScriptedLoadableModule base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
# HelloWorld button
helloWorldButton = qt.QPushButton("Hello world")
helloWorldButton.toolTip = "Print 'Hello world' in standard output."
parametersFormLayout.addWidget(helloWorldButton)
Update helloWorldButton.connect('clicked(bool)', self.onHelloWorldButtonClicked)
class HelloPythonLogic(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:
"""
def process(self):
return "Hello world!"
def setUp(self):
slicer.mrmlScene.Clear(0)
def runTest(self):
self.setUp()
self.test_HelloPython1()
def test_HelloPython1(self):
If an extension is submitted to the Extension Manager (Slicer App Store) then all
tests of all of its modules are executed for every release and results are reported
on the dashboard: http://slicer.cdash.org/index.php?project=Slicer4
S.Pujol, Ph.D. - S.Pieper, Ph.D.
NA-MIC ARR 2012-2017
Test the module
Laplace* Operator
*named aNer Pierre-Simon, Marquis de Laplace (1749-1827)
X
self.imageThresholdSliderWidget.minimum = -100
self.imageThresholdSliderWidget.maximum = 100
remove self.imageThresholdSliderWidget.value = 0.5
self.imageThresholdSliderWidget.setToolTip("Set threshold value for computing the
threshold output image. Voxels that have intensities lower than this value will set to zero.")
parametersFormLayout.addRow("Image threshold", self.imageThresholdSliderWidget)
value and
#
check box # check box to trigger taking screen shots for later use in tutorials
#
sections from self.enableScreenshotsFlagCheckBox = qt.QCheckBox()
self.enableScreenshotsFlagCheckBox.checked = 0
the self.enableScreenshotsFlagCheckBox.setToolTip("If checked, take screen shots for
tutorials. Use Save Data to write them to disk.")
HelloLaplace parametersFormLayout.addRow("Enable Screenshots",
self.enableScreenshotsFlagCheckBox)
Widget
#
# Apply Button
#
self.applyButton = qt.QPushButton("Apply")
…
S.Pujol, Ph.D. - S.Pieper, Ph.D.
NA-MIC ARR 2012-2017
Implement Module GUI (Part 2)
class HelloLaplaceWidget(ScriptedLoadableModuleWidget):
…
def onSelect(self):
self.applyButton.enabled =
self.inputSelector.currentNode() and
self.outputSelector.currentNode()
Update Apply def onApplyButton(self):
button event logic = HelloLaplaceLogic()
handler logic.run(self.inputSelector.currentNode(),
self.outputSelector.currentNode())
(onApplyButton) # make the output volume appear in all the slice views
to only use input slicer.util.setSliceViewerLayers(
background = self.outputSelector.currentNode())
and output
volumes #
# HelloLaplaceLogic
#
logging.info('Processing completed')
return True
#
# threshold value
#
self.imageThresholdSliderWidget = ctk.ctkSliderWidget()
Remove self.imageThresholdSliderWidget.singleStep = 0.1
X
self.imageThresholdSliderWidget.minimum = -100
unneeded self.imageThresholdSliderWidget.maximum = 100
self.imageThresholdSliderWidget.value = 0.5
slider and self.imageThresholdSliderWidget.setToolTip("Set threshold value for computing the
output image. Voxels that have intensities lower than this value will set to zero.")
checkbox parametersFormLayout.addRow("Image threshold", self.imageThresholdSliderWidget)
(same as for #
# check box to trigger taking screen shots for later use in tutorials
HelloLaplace #
self.enableScreenshotsFlagCheckBox = qt.QCheckBox()
module) self.enableScreenshotsFlagCheckBox.checked = 0
self.enableScreenshotsFlagCheckBox.setToolTip("If checked, take screen shots for
tutorials. Use Save Data to write them to disk.")
parametersFormLayout.addRow("Enable Screenshots",
self.enableScreenshotsFlagCheckBox)
#
# Apply Button
#
self.applyButton = qt.QPushButton("Apply")
…
S.Pujol, Ph.D. - S.Pieper, Ph.D.
NA-MIC ARR 2012-2017
Implement Module GUI (Part 2)
class HelloSharpenWidget(ScriptedLoadableModuleWidget):
…
def onSelect(self):
self.applyButton.enabled =
self.inputSelector.currentNode() and
self.outputSelector.currentNode()
Update Apply def onApplyButton(self):
button event logic = HelloSharpenLogic()
handler logic.run(self.inputSelector.currentNode(),
self.outputSelector.currentNode())
(onApplyButton) # make the output volume appear in all the slice views
to only use input slicer.util.setSliceViewerLayers(
background = self.outputSelector.currentNode())
and output
volumes #
# HelloSharpenLogic
#
module and # Subtract Laplacian from input volume using CLI module
SubtractVolumes parameters = {}
parameters['inputVolume1'] = inputVolume.GetID()
CLI module. parameters['inputVolume2'] = outputVolume.GetID()
parameters['outputVolume'] = outputVolume.GetID()
slicer.cli.runSync(slicer.modules.subtractscalarvolumes, None,
parameters)
logging.info('Processing completed')
return True
class HelloSharpenLogic(ScriptedLoadableModuleLogic):
…
def run(self, inputVolume, outputVolume):
…
slicer.cli.runSync(slicer.modules.subtractscalarvolumes, None,
parameters)
logging.info('Processing completed')
return True