Back to Projects List
Best practice when writing new ScriptedLoadableModules is to use a “parameter node” to store state (most commonly the state of the GUI). However, the existing parameter node system was in essence a string to string map (which some exceptions regarding storing MRML node references), while many times the state should not logically be a string.
A wrapper system was created, the parameterNodeWrapper
, to allow better typed access to parameter nodes. This system allows using many Python built-ins by default, and is extensible for custom classes.
Because the parameterNodeWrapper
uses type annotations, automatic connections can also be made to GUI components.
Example:
import enum
from slicer.parameterNodeWrapper import parameterNodeWrapper
class ConversionMethods(enum.Enum):
LUMINANCE = 1
AVERAGE = 2
SINGLE_COMPONENT = 3
@parameterNodeWrapper
class VectorToScalarVolumeParameterNode:
InputVolume: slicer.vtkMRMLVectorVolumeNode
OutputVolume: slicer.vtkMRMLScalarVolumeNode
ConversionMethod: ConversionMethods
ComponentToExtract: int
class VectorToScalarVolumeWidget(ScriptedLoadableModuleWidget):
def setup(self):
self._parameterNode = VectorToScalarVolumeParameterNode(self.logic.getParameterNode())
def updateParameterNodeFromGUI(self, caller=None, event=None):
# Modify all properties in a single batch
with slicer.util.NodeModify(self._parameterNode):
self._parameterNode.InputVolume = self.ui.inputSelector.currentNode()
self._parameterNode.OutputVolume = self.ui.outputSelector.currentNode()
self._parameterNode.ConversionMethod = self.ui.methodSelectorComboBox.currentData
self._parameterNode.ComponentToExtract = self.ui.componentsSpinBox.value
def onApplyButton(self):
self.logic.run(self._parameterNode.InputVolume,
self._parameterNode.OutputVolume,
self._parameterNode.ConversionMethod,
self._parameterNode.ComponentToExtract)
parameterNodeWrapper
.parameterNodeWrapper
functionality.typing.Any
annotation in the parameter node wrapper, with some limitations.