예제 #1
0
    def setupOptionsFrame(self):

        self.methodSelectorComboBox = qt.QComboBox()
        self.methodSelectorComboBox.addItem("Median", MEDIAN)
        self.methodSelectorComboBox.addItem("Opening (remove extrusions)",
                                            MORPHOLOGICAL_OPENING)
        self.methodSelectorComboBox.addItem("Closing (fill holes)",
                                            MORPHOLOGICAL_CLOSING)
        self.methodSelectorComboBox.addItem("Gaussian", GAUSSIAN)
        self.methodSelectorComboBox.setToolTip(
            '<html>Smoothing methods:<ul style="margin: 0"><li><b>Median:</b> removes small details while keeps smooth contours mostly unchanged.</li><li><b>Opening:</b> removes extrusions smaller than the specified kernel size.</li><li><b>Closing:</b> fills sharp corners and holes smaller than the specified kernel size.</li><li><b>Gaussian:</b> smoothes all contours, tends to shrink the segment.</li></ul></html>'
        )
        self.scriptedEffect.addLabeledOptionsWidget(
            "Smoothing method:", self.methodSelectorComboBox)

        self.kernelSizeMmSpinBox = slicer.qMRMLSpinBox()
        self.kernelSizeMmSpinBox.setMRMLScene(slicer.mrmlScene)
        self.kernelSizeMmSpinBox.setToolTip(
            "Diameter of the neighborhood that will be considered around each voxel. Higher value makes smoothing stronger (more details are suppressed)."
        )
        self.kernelSizeMmSpinBox.quantity = "length"
        self.kernelSizeMmSpinBox.unitAwareProperties &= ~slicer.qMRMLSpinBox.MinimumValue  # disable setting deafult minimum value (it would be a large negative value)
        self.kernelSizeMmSpinBox.minimum = 0.0
        self.kernelSizeMmSpinBox.value = 3.0
        self.kernelSizeMmSpinBox.singleStep = 1.0

        self.kernelSizePixel = qt.QLabel()
        self.kernelSizePixel.setToolTip(
            "Diameter of the neighborhood in pixels. Computed from the segment's spacing and the specified kernel size."
        )

        kernelSizeFrame = qt.QHBoxLayout()
        kernelSizeFrame.addWidget(self.kernelSizePixel)
        kernelSizeFrame.addWidget(self.kernelSizeMmSpinBox)
        self.kernelSizeMmLabel = self.scriptedEffect.addLabeledOptionsWidget(
            "Kernel size:", kernelSizeFrame)

        self.gaussianStandardDeviationMmSpinBox = slicer.qMRMLSpinBox()
        self.gaussianStandardDeviationMmSpinBox.setMRMLScene(slicer.mrmlScene)
        self.gaussianStandardDeviationMmSpinBox.setToolTip(
            "Standard deviation of the Gaussian smoothing filter coefficients. Higher value makes smoothing stronger (more details are suppressed)."
        )
        self.gaussianStandardDeviationMmSpinBox.quantity = "length"
        self.gaussianStandardDeviationMmSpinBox.value = 3.0
        self.gaussianStandardDeviationMmSpinBox.singleStep = 1.0
        self.gaussianStandardDeviationMmLabel = self.scriptedEffect.addLabeledOptionsWidget(
            "Standard deviation:", self.gaussianStandardDeviationMmSpinBox)

        self.applyButton = qt.QPushButton("Apply")
        self.applyButton.objectName = self.__class__.__name__ + 'Apply'
        self.applyButton.setToolTip("Apply smoothing to selected segment")
        self.scriptedEffect.addOptionsWidget(self.applyButton)

        self.methodSelectorComboBox.connect("currentIndexChanged(int)",
                                            self.updateMRMLFromGUI)
        self.kernelSizeMmSpinBox.connect("valueChanged(double)",
                                         self.updateMRMLFromGUI)
        self.gaussianStandardDeviationMmSpinBox.connect(
            "valueChanged(double)", self.updateMRMLFromGUI)
        self.applyButton.connect('clicked()', self.onApply)
    def setupOptionsFrame(self):

        self.methodSelectorComboBox = qt.QComboBox()
        self.methodSelectorComboBox.addItem("Median", MEDIAN)
        self.methodSelectorComboBox.addItem("Opening (remove extrusions)", MORPHOLOGICAL_OPENING)
        self.methodSelectorComboBox.addItem("Closing (fill holes)", MORPHOLOGICAL_CLOSING)
        self.methodSelectorComboBox.addItem("Gaussian", GAUSSIAN)
        self.methodSelectorComboBox.setToolTip(
            '<html>Smoothing methods:<ul style="margin: 0"><li><b>Median:</b> removes small details while keeps smooth contours mostly unchanged.</li><li><b>Opening:</b> removes extrusions smaller than the specified kernel size.</li><li><b>Closing:</b> fills sharp corners and holes smaller than the specified kernel size.</li><li><b>Gaussian:</b> smoothes all contours, tends to shrink the segment.</li></ul></html>'
        )
        self.scriptedEffect.addLabeledOptionsWidget("Smoothing method:", self.methodSelectorComboBox)

        self.kernelSizeMmSpinBox = slicer.qMRMLSpinBox()
        self.kernelSizeMmSpinBox.setMRMLScene(slicer.mrmlScene)
        self.kernelSizeMmSpinBox.setToolTip(
            "Diameter of the neighborhood that will be considered around each voxel. Higher value makes smoothing stronger (more details are suppressed)."
        )
        self.kernelSizeMmSpinBox.quantity = "length"
        self.kernelSizeMmSpinBox.unitAwareProperties &= (
            ~slicer.qMRMLSpinBox.MinimumValue
        )  # disable setting deafult minimum value (it would be a large negative value)
        self.kernelSizeMmSpinBox.minimum = 0.0
        self.kernelSizeMmSpinBox.value = 3.0
        self.kernelSizeMmSpinBox.singleStep = 1.0

        self.kernelSizePixel = qt.QLabel()
        self.kernelSizePixel.setToolTip(
            "Diameter of the neighborhood in pixels. Computed from the segment's spacing and the specified kernel size."
        )

        kernelSizeFrame = qt.QHBoxLayout()
        kernelSizeFrame.addWidget(self.kernelSizePixel)
        kernelSizeFrame.addWidget(self.kernelSizeMmSpinBox)
        self.kernelSizeMmLabel = self.scriptedEffect.addLabeledOptionsWidget("Kernel size:", kernelSizeFrame)

        self.gaussianStandardDeviationMmSpinBox = slicer.qMRMLSpinBox()
        self.gaussianStandardDeviationMmSpinBox.setMRMLScene(slicer.mrmlScene)
        self.gaussianStandardDeviationMmSpinBox.setToolTip(
            "Standard deviation of the Gaussian smoothing filter coefficients. Higher value makes smoothing stronger (more details are suppressed)."
        )
        self.gaussianStandardDeviationMmSpinBox.quantity = "length"
        self.gaussianStandardDeviationMmSpinBox.value = 3.0
        self.gaussianStandardDeviationMmSpinBox.singleStep = 1.0
        self.gaussianStandardDeviationMmLabel = self.scriptedEffect.addLabeledOptionsWidget(
            "Standard deviation:", self.gaussianStandardDeviationMmSpinBox
        )

        self.applyButton = qt.QPushButton("Apply")
        self.applyButton.objectName = self.__class__.__name__ + "Apply"
        self.applyButton.setToolTip("Apply smoothing to selected segment")
        self.scriptedEffect.addOptionsWidget(self.applyButton)

        self.methodSelectorComboBox.connect("currentIndexChanged(int)", self.updateMRMLFromGUI)
        self.kernelSizeMmSpinBox.connect("valueChanged(double)", self.updateMRMLFromGUI)
        self.gaussianStandardDeviationMmSpinBox.connect("valueChanged(double)", self.updateMRMLFromGUI)
        self.applyButton.connect("clicked()", self.onApply)
예제 #3
0
  def setupOptionsFrame(self):

    self.methodSelectorComboBox = qt.QComboBox()
    self.methodSelectorComboBox.addItem("Median", MEDIAN)
    self.methodSelectorComboBox.addItem("Opening (remove extrusions)", MORPHOLOGICAL_OPENING)
    self.methodSelectorComboBox.addItem("Closing (fill holes)", MORPHOLOGICAL_CLOSING)
    self.methodSelectorComboBox.addItem("Gaussian", GAUSSIAN)
    self.methodSelectorComboBox.addItem("Joint smoothing", JOINT_TAUBIN)
    self.scriptedEffect.addLabeledOptionsWidget("Smoothing method:", self.methodSelectorComboBox)

    self.kernelSizeMmSpinBox = slicer.qMRMLSpinBox()
    self.kernelSizeMmSpinBox.setMRMLScene(slicer.mrmlScene)
    self.kernelSizeMmSpinBox.setToolTip("Diameter of the neighborhood that will be considered around each voxel. Higher value makes smoothing stronger (more details are suppressed).")
    self.kernelSizeMmSpinBox.quantity = "length"
    self.kernelSizeMmSpinBox.minimum = 0.0
    self.kernelSizeMmSpinBox.value = 3.0
    self.kernelSizeMmSpinBox.singleStep = 1.0

    self.kernelSizePixel = qt.QLabel()
    self.kernelSizePixel.setToolTip("Diameter of the neighborhood in pixels. Computed from the segment's spacing and the specified kernel size.")

    kernelSizeFrame = qt.QHBoxLayout()
    kernelSizeFrame.addWidget(self.kernelSizeMmSpinBox)
    kernelSizeFrame.addWidget(self.kernelSizePixel)
    self.kernelSizeMmLabel = self.scriptedEffect.addLabeledOptionsWidget("Kernel size:", kernelSizeFrame)

    self.gaussianStandardDeviationMmSpinBox = slicer.qMRMLSpinBox()
    self.gaussianStandardDeviationMmSpinBox.setMRMLScene(slicer.mrmlScene)
    self.gaussianStandardDeviationMmSpinBox.setToolTip("Standard deviation of the Gaussian smoothing filter coefficients. Higher value makes smoothing stronger (more details are suppressed).")
    self.gaussianStandardDeviationMmSpinBox.quantity = "length"
    self.gaussianStandardDeviationMmSpinBox.value = 3.0
    self.gaussianStandardDeviationMmSpinBox.singleStep = 1.0
    self.gaussianStandardDeviationMmLabel = self.scriptedEffect.addLabeledOptionsWidget("Standard deviation:", self.gaussianStandardDeviationMmSpinBox)

    self.jointTaubinSmoothingFactorSlider = ctk.ctkSliderWidget()
    self.jointTaubinSmoothingFactorSlider.setToolTip("Higher value means stronger smoothing.")
    self.jointTaubinSmoothingFactorSlider.minimum = 0.01
    self.jointTaubinSmoothingFactorSlider.maximum = 1.0
    self.jointTaubinSmoothingFactorSlider.value = 0.5
    self.jointTaubinSmoothingFactorSlider.singleStep = 0.01
    self.jointTaubinSmoothingFactorSlider.pageStep = 0.1
    self.jointTaubinSmoothingFactorLabel = self.scriptedEffect.addLabeledOptionsWidget("Smoothing factor:", self.jointTaubinSmoothingFactorSlider)

    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.objectName = self.__class__.__name__ + 'Apply'
    self.applyButton.setToolTip("Apply smoothing to selected segment")
    self.scriptedEffect.addOptionsWidget(self.applyButton)

    self.methodSelectorComboBox.connect("currentIndexChanged(int)", self.updateMRMLFromGUI)
    self.kernelSizeMmSpinBox.connect("valueChanged(double)", self.updateMRMLFromGUI)
    self.gaussianStandardDeviationMmSpinBox.connect("valueChanged(double)", self.updateMRMLFromGUI)
    self.jointTaubinSmoothingFactorSlider.connect("valueChanged(double)", self.updateMRMLFromGUI)
    self.applyButton.connect('clicked()', self.onApply)
  def setupOptionsFrame(self):
    SegmentEditorThresholdEffect.setupOptionsFrame(self)

    # Hide threshold options
    self.applyButton.setHidden(True)
    self.useForPaintButton.setHidden(True)

    # Add diameter selector
    self.minimumDiameterSpinBox = slicer.qMRMLSpinBox()
    self.minimumDiameterSpinBox.setMRMLScene(slicer.mrmlScene)
    self.minimumDiameterSpinBox.quantity = "length"
    self.minimumDiameterSpinBox.value = 3.0
    self.minimumDiameterSpinBox.singleStep = 0.5
    self.minimumDiameterSpinBox.setToolTip("Minimum diameter of the structure. Regions that are connected to the selected point by a bridge"
      " that this is thinner than this size will be excluded to prevent unwanted leaks through small holes.")
    self.kernelSizePixel = qt.QLabel()
    self.kernelSizePixel.setToolTip("Minimum diameter of the structure in pixels. Computed from the segment's spacing and the specified feature size.")
    minimumDiameterFrame = qt.QHBoxLayout()
    minimumDiameterFrame.addWidget(self.minimumDiameterSpinBox)
    minimumDiameterFrame.addWidget(self.kernelSizePixel)
    self.minimumDiameterMmLabel = self.scriptedEffect.addLabeledOptionsWidget("Minimum diameter:", minimumDiameterFrame)
    self.scriptedEffect.addOptionsWidget(minimumDiameterFrame)

    # Add algorithm options
    self.segmentationAlgorithmSelector = qt.QComboBox()
    self.segmentationAlgorithmSelector.addItem(SEGMENTATION_ALGORITHM_MASKING)
    self.segmentationAlgorithmSelector.addItem(SEGMENTATION_ALGORITHM_GROWCUT)
    self.segmentationAlgorithmSelector.addItem(SEGMENTATION_ALGORITHM_WATERSHED)
    self.scriptedEffect.addLabeledOptionsWidget("Segmentation algorithm: ", self.segmentationAlgorithmSelector)

    # Add feature size selector
    self.featureSizeSpinBox = slicer.qMRMLSpinBox()
    self.featureSizeSpinBox.setMRMLScene(slicer.mrmlScene)
    self.featureSizeSpinBox.quantity = "length"
    self.featureSizeSpinBox.value = 3.0
    self.featureSizeSpinBox.singleStep = 0.5
    self.featureSizeSpinBox.setToolTip("Spatial smoothness constraint used for WaterShed. Larger values result in smoother extracted surface.")
    self.scriptedEffect.addLabeledOptionsWidget("Feature size: ", self.featureSizeSpinBox)

    # Add ROI options
    self.roiSelector = slicer.qMRMLNodeComboBox()
    self.roiSelector.nodeTypes = ['vtkMRMLMarkupsROINode', 'vtkMRMLAnnotationROINode']
    self.roiSelector.noneEnabled = True
    self.roiSelector.setMRMLScene(slicer.mrmlScene)
    self.scriptedEffect.addLabeledOptionsWidget("ROI: ", self.roiSelector)

    # Connections
    self.minimumDiameterSpinBox.connect("valueChanged(double)", self.updateMRMLFromGUI)
    self.featureSizeSpinBox.connect("valueChanged(double)", self.updateMRMLFromGUI)
    self.segmentationAlgorithmSelector.connect("currentIndexChanged(int)", self.updateMRMLFromGUI)
예제 #5
0
    def setupOptionsFrame(self):

        self.marginSizeMmSpinBox = slicer.qMRMLSpinBox()
        self.marginSizeMmSpinBox.setMRMLScene(slicer.mrmlScene)
        self.marginSizeMmSpinBox.setToolTip(
            "Segment boundaries will be shifted by this distance. Positive value means the segments will grow, negative value means segment will shrink."
        )
        self.marginSizeMmSpinBox.quantity = "length"
        self.marginSizeMmSpinBox.value = 3.0
        self.marginSizeMmSpinBox.singleStep = 1.0

        self.kernelSizePixel = qt.QLabel()
        self.kernelSizePixel.setToolTip(
            "Size change in pixels. Computed from the segment's spacing and the specified margin size."
        )

        marginSizeFrame = qt.QHBoxLayout()
        marginSizeFrame.addWidget(self.kernelSizePixel)
        marginSizeFrame.addWidget(self.marginSizeMmSpinBox)
        self.marginSizeMmLabel = self.scriptedEffect.addLabeledOptionsWidget(
            "Margin size:", marginSizeFrame)

        self.applyButton = qt.QPushButton("Apply")
        self.applyButton.objectName = self.__class__.__name__ + 'Apply'
        self.applyButton.setToolTip(
            "Grows or shrinks selected segment by the specified margin.")
        self.scriptedEffect.addOptionsWidget(self.applyButton)

        self.applyButton.connect('clicked()', self.onApply)
        self.marginSizeMmSpinBox.connect("valueChanged(double)",
                                         self.updateMRMLFromGUI)
예제 #6
0
    def setupOptionsFrame(self):

        operationLayout = qt.QVBoxLayout()

        self.shrinkOptionRadioButton = qt.QRadioButton("Shrink")
        self.growOptionRadioButton = qt.QRadioButton("Grow")
        operationLayout.addWidget(self.shrinkOptionRadioButton)
        operationLayout.addWidget(self.growOptionRadioButton)
        self.growOptionRadioButton.setChecked(True)

        self.scriptedEffect.addLabeledOptionsWidget("Operation:",
                                                    operationLayout)

        self.marginSizeMMSpinBox = slicer.qMRMLSpinBox()
        self.marginSizeMMSpinBox.setMRMLScene(slicer.mrmlScene)
        self.marginSizeMMSpinBox.setToolTip(
            "Segment boundaries will be shifted by this distance. Positive value means the segments will grow, negative value means segment will shrink."
        )
        self.marginSizeMMSpinBox.quantity = "length"
        self.marginSizeMMSpinBox.value = 3.0
        self.marginSizeMMSpinBox.singleStep = 1.0

        self.marginSizeLabel = qt.QLabel()
        self.marginSizeLabel.setToolTip(
            "Size change in pixel. Computed from the segment's spacing and the specified margin size."
        )

        marginSizeFrame = qt.QHBoxLayout()
        marginSizeFrame.addWidget(self.marginSizeMMSpinBox)
        self.marginSizeMMLabel = self.scriptedEffect.addLabeledOptionsWidget(
            "Margin size:", marginSizeFrame)
        self.scriptedEffect.addLabeledOptionsWidget("", self.marginSizeLabel)

        self.applyToAllVisibleSegmentsCheckBox = qt.QCheckBox()
        self.applyToAllVisibleSegmentsCheckBox.setToolTip(
            "Grow or shrink all visible segments in this segmentation node. \
                                                      This operation may take a while."
        )
        self.applyToAllVisibleSegmentsCheckBox.objectName = self.__class__.__name__ + 'ApplyToAllVisibleSegments'
        self.applyToAllVisibleSegmentsLabel = self.scriptedEffect.addLabeledOptionsWidget(
            "Apply to all segments:", self.applyToAllVisibleSegmentsCheckBox)

        self.applyButton = qt.QPushButton("Apply")
        self.applyButton.objectName = self.__class__.__name__ + 'Apply'
        self.applyButton.setToolTip(
            "Grows or shrinks selected segment /default) or all segments (checkbox) by the specified margin."
        )
        self.scriptedEffect.addOptionsWidget(self.applyButton)

        self.applyButton.connect('clicked()', self.onApply)
        self.marginSizeMMSpinBox.connect("valueChanged(double)",
                                         self.updateMRMLFromGUI)
        self.growOptionRadioButton.connect("toggled(bool)",
                                           self.growOperationToggled)
        self.shrinkOptionRadioButton.connect("toggled(bool)",
                                             self.shrinkOperationToggled)
        self.applyToAllVisibleSegmentsCheckBox.connect("stateChanged(int)",
                                                       self.updateMRMLFromGUI)
  def create(self):
    super(InterpolateROIsEffectOptions,self).create()

    self.minimumSigma = 0.01
    self.maximumSigma = 1.5

    self.sigmaFrame = qt.QFrame(self.frame)
    self.sigmaFrame.setLayout(qt.QHBoxLayout())
    self.frame.layout().addWidget(self.sigmaFrame)
    self.widgets.append(self.sigmaFrame)
    self.sigmaLabel = qt.QLabel("Sigma:", self.sigmaFrame)
    self.sigmaLabel.setToolTip("Set the sigma of the gaussian filter")
    self.sigmaFrame.layout().addWidget(self.sigmaLabel)
    self.widgets.append(self.sigmaLabel)
    self.sigmaSpinBox = slicer.qMRMLSpinBox(self.sigmaFrame)
    self.sigmaSpinBox.objectName = 'SpinBox_Sigma'
    self.sigmaSpinBox.setToolTip("Set the sigma of the gaussian filter")
    #self.sigmaSpinBox.quantity = "length"
    # QFlags not wrapped in python. Equivalent to Prefix | Suffix
    # See qMRMLSpinBox for more details.
    self.sigmaSpinBox.unitAwareProperties = 0x01 | 0x02
    self.sigmaSpinBox.decimals = 2
    self.sigmaSpinBox.minimum = self.minimumSigma
    self.sigmaSpinBox.maximum = self.maximumSigma
    self.sigmaSpinBox.singleStep = self.minimumSigma
    self.sigmaSpinBox.setMRMLScene(slicer.mrmlScene)
    self.sigmaFrame.layout().addWidget(self.sigmaSpinBox)
    self.widgets.append(self.sigmaSpinBox)

    self.sigma = ctk.ctkDoubleSlider(self.frame)
    self.sigma.objectName = 'DoubleSlider_Sigma'
    self.sigma.minimum = self.minimumSigma
    self.sigma.maximum = self.maximumSigma
    self.sigma.orientation = 1
    self.sigma.singleStep = self.minimumSigma
    self.frame.layout().addWidget(self.sigma)
    self.widgets.append(self.sigma)


    self.apply = qt.QPushButton("Apply", self.frame)
    self.apply.objectName = self.__class__.__name__ + 'Apply'
    self.apply.setToolTip("Interpolate current label")
    self.frame.layout().addWidget(self.apply)
    self.widgets.append(self.apply)

    EditorLib.HelpButton(self.frame, "Use this tool to remove pixels from the boundary of the current label.")

    self.connections.append( (self.sigma, 'valueChanged(double)', self.onSigmaValueChanged) )
    self.connections.append( (self.sigmaSpinBox, 'valueChanged(double)', self.onSigmaSpinBoxChanged) )
    self.connections.append( (self.apply, 'clicked()', self.onApply) )

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

    self.parameterNode.SetParameter("MorphologyEffect,neighborMode","8")
    self.parameterNode.SetParameter("InterpolateROIsEffect,sigma","1.0")
    def setupOptionsFrame(self):

        operationLayout = qt.QVBoxLayout()

        self.insideSurfaceOptionRadioButton = qt.QRadioButton("inside surface")
        self.medialSurfaceOptionRadioButton = qt.QRadioButton("medial surface")
        self.outsideSurfaceOptionRadioButton = qt.QRadioButton(
            "outside surface")
        operationLayout.addWidget(self.insideSurfaceOptionRadioButton)
        operationLayout.addWidget(self.medialSurfaceOptionRadioButton)
        operationLayout.addWidget(self.outsideSurfaceOptionRadioButton)
        self.insideSurfaceOptionRadioButton.setChecked(True)

        self.scriptedEffect.addLabeledOptionsWidget("Use current segment as:",
                                                    operationLayout)

        self.shellThicknessMMSpinBox = slicer.qMRMLSpinBox()
        self.shellThicknessMMSpinBox.setMRMLScene(slicer.mrmlScene)
        self.shellThicknessMMSpinBox.setToolTip(
            "Thickness of the hollow shell.")
        self.shellThicknessMMSpinBox.quantity = "length"
        self.shellThicknessMMSpinBox.minimum = 0.0
        self.shellThicknessMMSpinBox.value = 3.0
        self.shellThicknessMMSpinBox.singleStep = 1.0

        self.shellThicknessLabel = qt.QLabel()
        self.shellThicknessLabel.setToolTip(
            "Closest achievable thickness. Constrained by the segmentation's binary labelmap representation spacing."
        )

        shellThicknessFrame = qt.QHBoxLayout()
        shellThicknessFrame.addWidget(self.shellThicknessMMSpinBox)
        self.shellThicknessMMLabel = self.scriptedEffect.addLabeledOptionsWidget(
            "Shell thickness:", shellThicknessFrame)
        self.scriptedEffect.addLabeledOptionsWidget("",
                                                    self.shellThicknessLabel)

        self.applyButton = qt.QPushButton("Apply")
        self.applyButton.objectName = self.__class__.__name__ + 'Apply'
        self.applyButton.setToolTip(
            "Makes the segment hollow by replacing it with a thick shell at the segment boundary."
        )
        self.scriptedEffect.addOptionsWidget(self.applyButton)

        self.applyButton.connect('clicked()', self.onApply)
        self.shellThicknessMMSpinBox.connect("valueChanged(double)",
                                             self.updateMRMLFromGUI)
        self.insideSurfaceOptionRadioButton.connect(
            "toggled(bool)", self.insideSurfaceModeToggled)
        self.medialSurfaceOptionRadioButton.connect(
            "toggled(bool)", self.medialSurfaceModeToggled)
        self.outsideSurfaceOptionRadioButton.connect(
            "toggled(bool)", self.outsideSurfaceModeToggled)
    def setupOptionsFrame(self):
        SegmentEditorThresholdEffect.setupOptionsFrame(self)

        # Hide threshold options
        self.applyButton.setHidden(True)
        self.useForPaintButton.setHidden(True)

        # Add feature options
        self.minimumMinimumFeatureSize = slicer.qMRMLSpinBox()
        self.minimumMinimumFeatureSize.setMRMLScene(slicer.mrmlScene)
        self.minimumMinimumFeatureSize.quantity = "length"
        self.minimumMinimumFeatureSize.value = 3.0
        self.minimumMinimumFeatureSize.singleStep = 0.5
        self.kernelSizePixel = qt.QLabel()
        self.kernelSizePixel.setToolTip(
            "Minimum size of features in pixels. Computed from the segment's spacing and the specified feature size."
        )
        featureSizeFrame = qt.QHBoxLayout()
        featureSizeFrame.addWidget(self.minimumMinimumFeatureSize)
        featureSizeFrame.addWidget(self.kernelSizePixel)
        self.featureSizeMmLabel = self.scriptedEffect.addLabeledOptionsWidget(
            "Feature size:", featureSizeFrame)
        self.scriptedEffect.addOptionsWidget(featureSizeFrame)

        # Add algorithm options
        self.segmentationAlgorithmSelector = qt.QComboBox()
        self.segmentationAlgorithmSelector.addItem(
            SEGMENTATION_ALGORITHM_MASKING)
        self.segmentationAlgorithmSelector.addItem(
            SEGMENTATION_ALGORITHM_GROWCUT)
        self.segmentationAlgorithmSelector.addItem(
            SEGMENTATION_ALGORITHM_WATERSHED)
        self.scriptedEffect.addLabeledOptionsWidget(
            "Segmentation algorithm: ", self.segmentationAlgorithmSelector)

        # Add ROI options
        self.roiSelector = slicer.qMRMLNodeComboBox()
        self.roiSelector.nodeTypes = ['vtkMRMLAnnotationROINode']
        self.roiSelector.noneEnabled = True
        self.roiSelector.setMRMLScene(slicer.mrmlScene)
        self.scriptedEffect.addLabeledOptionsWidget("ROI: ", self.roiSelector)

        # Connections
        self.minimumMinimumFeatureSize.connect("valueChanged(double)",
                                               self.updateMRMLFromGUI)
        self.segmentationAlgorithmSelector.connect("currentIndexChanged(int)",
                                                   self.updateMRMLFromGUI)
예제 #10
0
  def setupOptionsFrame(self):

    operationLayout = qt.QVBoxLayout()

    self.insideSurfaceOptionRadioButton = qt.QRadioButton("inside surface")
    self.medialSurfaceOptionRadioButton = qt.QRadioButton("medial surface")
    self.outsideSurfaceOptionRadioButton = qt.QRadioButton("outside surface")
    operationLayout.addWidget(self.insideSurfaceOptionRadioButton)
    operationLayout.addWidget(self.medialSurfaceOptionRadioButton)
    operationLayout.addWidget(self.outsideSurfaceOptionRadioButton)
    self.insideSurfaceOptionRadioButton.setChecked(True)

    self.scriptedEffect.addLabeledOptionsWidget("Use current segment as:", operationLayout)

    self.shellThicknessMmSpinBox = slicer.qMRMLSpinBox()
    self.shellThicknessMmSpinBox.setMRMLScene(slicer.mrmlScene)
    self.shellThicknessMmSpinBox.setToolTip("Thickness of the hollow shell.")
    self.shellThicknessMmSpinBox.quantity = "length"
    self.shellThicknessMmSpinBox.minimum = 0.0
    self.shellThicknessMmSpinBox.value = 3.0
    self.shellThicknessMmSpinBox.singleStep = 1.0

    self.kernelSizePixel = qt.QLabel()
    self.kernelSizePixel.setToolTip("Thickness in pixels. Computed from the segment's spacing and the specified margin size.")

    shellThicknessFrame = qt.QHBoxLayout()
    shellThicknessFrame.addWidget(self.shellThicknessMmSpinBox)
    shellThicknessFrame.addWidget(self.kernelSizePixel)
    self.shellThicknessMmLabel = self.scriptedEffect.addLabeledOptionsWidget("Shell thickness:", shellThicknessFrame)

    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.objectName = self.__class__.__name__ + 'Apply'
    self.applyButton.setToolTip("Makes the segment hollow by replacing it with a thick shell at the segment boundary.")
    self.scriptedEffect.addOptionsWidget(self.applyButton)

    self.applyButton.connect('clicked()', self.onApply)
    self.shellThicknessMmSpinBox.connect("valueChanged(double)", self.updateMRMLFromGUI)
    self.insideSurfaceOptionRadioButton.connect("toggled(bool)", self.insideSurfaceModeToggled)
    self.medialSurfaceOptionRadioButton.connect("toggled(bool)", self.medialSurfaceModeToggled)
    self.outsideSurfaceOptionRadioButton.connect("toggled(bool)", self.outsideSurfaceModeToggled)
예제 #11
0
  def setupOptionsFrame(self):

    self.marginSizeMmSpinBox = slicer.qMRMLSpinBox()
    self.marginSizeMmSpinBox.setMRMLScene(slicer.mrmlScene)
    self.marginSizeMmSpinBox.setToolTip("Segment boundaries will be shifted by this distance. Positive value means the segments will grow, negative value means segment will shrink.")
    self.marginSizeMmSpinBox.quantity = "length"
    self.marginSizeMmSpinBox.value = 3.0
    self.marginSizeMmSpinBox.singleStep = 1.0

    self.kernelSizePixel = qt.QLabel()
    self.kernelSizePixel.setToolTip("Size change in pixels. Computed from the segment's spacing and the specified margin size.")

    marginSizeFrame = qt.QHBoxLayout()
    marginSizeFrame.addWidget(self.kernelSizePixel)
    marginSizeFrame.addWidget(self.marginSizeMmSpinBox)
    self.marginSizeMmLabel = self.scriptedEffect.addLabeledOptionsWidget("Margin size:", marginSizeFrame)

    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.objectName = self.__class__.__name__ + 'Apply'
    self.applyButton.setToolTip("Grows or shrinks selected segment by the specified margin.")
    self.scriptedEffect.addOptionsWidget(self.applyButton)

    self.applyButton.connect('clicked()', self.onApply)
    self.marginSizeMmSpinBox.connect("valueChanged(double)", self.updateMRMLFromGUI)
예제 #12
0
    def setupOptionsFrame(self):
        self.interpolationRadioButtons = []

        # Fiducial Placement widget
        self.fiducialPlacementToggle = slicer.qSlicerMarkupsPlaceWidget()
        self.fiducialPlacementToggle.setMRMLScene(slicer.mrmlScene)
        self.fiducialPlacementToggle.placeMultipleMarkups = self.fiducialPlacementToggle.ForcePlaceMultipleMarkups
        self.fiducialPlacementToggle.buttonsVisible = False
        self.fiducialPlacementToggle.show()
        self.fiducialPlacementToggle.placeButton().show()
        self.fiducialPlacementToggle.deleteButton().show()

        # Edit surface button
        self.editButton = qt.QPushButton("Edit")
        self.editButton.objectName = self.__class__.__name__ + 'Edit'
        self.editButton.setToolTip(
            "Edit the previously placed group of fiducials.")

        fiducialActionLayout = qt.QHBoxLayout()
        fiducialActionLayout.addWidget(self.fiducialPlacementToggle)
        fiducialActionLayout.addWidget(self.editButton)
        self.scriptedEffect.addLabeledOptionsWidget("Fiducial Placement: ",
                                                    fiducialActionLayout)

        # Radius spinbox
        self.radiusSpinBox = slicer.qMRMLSpinBox()
        self.radiusSpinBox.value = self.logic.radius
        self.radiusSpinBox.quantity = 'length'
        self.radiusSpinBox.unitAwareProperties = slicer.qMRMLSpinBox.MaximumValue | slicer.qMRMLSpinBox.Precision | slicer.qMRMLSpinBox.Prefix | slicer.qMRMLSpinBox.Suffix
        self.scriptedEffect.addLabeledOptionsWidget("Radius: ",
                                                    self.radiusSpinBox)

        # Interpolation buttons
        self.piecewiseLinearButton = qt.QRadioButton("Piecewise linear")
        self.interpolationRadioButtons.append(self.piecewiseLinearButton)
        self.buttonToInterpolationTypeMap[
            self.piecewiseLinearButton] = "LINEAR"

        self.cardinalSplineButton = qt.QRadioButton("Cardinal spline")
        self.interpolationRadioButtons.append(self.cardinalSplineButton)
        self.buttonToInterpolationTypeMap[
            self.cardinalSplineButton] = "CARDINAL_SPLINE"

        self.kochanekSplineButton = qt.QRadioButton("Kochanek spline")
        self.interpolationRadioButtons.append(self.kochanekSplineButton)
        self.buttonToInterpolationTypeMap[
            self.kochanekSplineButton] = "KOCHANEK_SPLINE"

        self.globalPolynomialButton = qt.QRadioButton("Global polynomial")
        self.interpolationRadioButtons.append(self.globalPolynomialButton)
        self.buttonToInterpolationTypeMap[
            self.globalPolynomialButton] = "GLOBAL_POLYNOMIAL"

        self.movingPolynomialButton = qt.QRadioButton("Moving polynomial")
        self.interpolationRadioButtons.append(self.movingPolynomialButton)
        self.buttonToInterpolationTypeMap[
            self.movingPolynomialButton] = "MOVING_POLYNOMIAL"

        # Interpolation buttons layout
        interpolationLayout = qt.QGridLayout()
        interpolationLayout.addWidget(self.piecewiseLinearButton, 0, 0)
        interpolationLayout.addWidget(self.cardinalSplineButton, 1, 0)
        interpolationLayout.addWidget(self.kochanekSplineButton, 0, 1)
        interpolationLayout.addWidget(self.globalPolynomialButton, 1, 1)
        interpolationLayout.addWidget(self.movingPolynomialButton, 0, 2)

        self.scriptedEffect.addLabeledOptionsWidget("Interpolation:",
                                                    interpolationLayout)

        # Apply button
        self.applyButton = qt.QPushButton("Apply")
        self.applyButton.objectName = self.__class__.__name__ + 'Apply'
        self.applyButton.setToolTip("Generate tube from markup fiducials.")
        self.scriptedEffect.addOptionsWidget(self.applyButton)

        # Cancel button
        self.cancelButton = qt.QPushButton("Cancel")
        self.cancelButton.objectName = self.__class__.__name__ + 'Cancel'
        self.cancelButton.setToolTip("Clear fiducials and remove from scene.")

        # Finish action buttons
        finishAction = qt.QHBoxLayout()
        finishAction.addWidget(self.cancelButton)
        finishAction.addWidget(self.applyButton)
        self.scriptedEffect.addOptionsWidget(finishAction)

        # Connections
        for button in self.interpolationRadioButtons:
            button.connect('toggled(bool)',
                           lambda toggle, widget=self.
                           buttonToInterpolationTypeMap[button]: self.
                           onInterpolationSelectionChanged(widget, toggle))
        self.applyButton.connect('clicked()', self.onApply)
        self.cancelButton.connect('clicked()', self.onCancel)
        self.editButton.connect('clicked()', self.onEdit)
        self.fiducialPlacementToggle.placeButton().clicked.connect(
            self.onFiducialPlacementToggleChanged)
        self.radiusSpinBox.connect('valueChanged(double)',
                                   self.onRadiusChanged)
예제 #13
0
    def create(self):
        super(PaintEffectOptions, self).create()

        self.radiusFrame = qt.QFrame(self.frame)
        self.radiusFrame.setLayout(qt.QHBoxLayout())
        self.frame.layout().addWidget(self.radiusFrame)
        self.widgets.append(self.radiusFrame)
        self.radiusLabel = qt.QLabel("Radius:", self.radiusFrame)
        self.radiusLabel.setToolTip(
            "Set the radius of the paint brush in millimeters")
        self.radiusFrame.layout().addWidget(self.radiusLabel)
        self.widgets.append(self.radiusLabel)
        self.radiusSpinBox = slicer.qMRMLSpinBox(self.radiusFrame)
        self.radiusSpinBox.objectName = 'SpinBox_Radius'
        self.radiusSpinBox.setToolTip(
            "Set the radius of the paint brush in millimeters")
        self.radiusSpinBox.quantity = "length"
        # QFlags not wrapped in python. Equivalent to Prefix | Suffix
        # See qMRMLSpinBox for more details.
        self.radiusSpinBox.unitAwareProperties = 0x01 | 0x02
        self.radiusSpinBox.minimum = self.minimumRadius
        self.radiusSpinBox.maximum = self.maximumRadius
        self.radiusSpinBox.setMRMLScene(slicer.mrmlScene)
        from math import log, floor
        decimals = floor(log(self.minimumRadius, 10))
        if decimals < 0:
            self.radiusSpinBox.decimals = -decimals + 2
        self.radiusFrame.layout().addWidget(self.radiusSpinBox)
        self.widgets.append(self.radiusSpinBox)
        self.radiusUnitsToggle = qt.QPushButton("px:")
        self.radiusUnitsToggle.objectName = 'PushButton_RadiusUnitsToggle'
        self.radiusUnitsToggle.setToolTip(
            "Toggle radius quick set buttons between mm and label volume pixel size units"
        )
        self.radiusUnitsToggle.setFixedWidth(35)
        self.radiusFrame.layout().addWidget(self.radiusUnitsToggle)
        self.radiusUnitsToggle.connect('clicked()', self.onRadiusUnitsToggle)
        self.radiusQuickies = {}
        quickies = ((2, self.onQuickie2Clicked), (3, self.onQuickie3Clicked),
                    (4, self.onQuickie4Clicked), (5, self.onQuickie5Clicked),
                    (10, self.onQuickie10Clicked), (20,
                                                    self.onQuickie20Clicked))
        for rad, callback in quickies:
            self.radiusQuickies[rad] = qt.QPushButton(str(rad))
            self.radiusQuickies[
                rad].objectName = 'PushButton_QuickRadius_{0}'.format(rad)
            self.radiusFrame.layout().addWidget(self.radiusQuickies[rad])
            self.radiusQuickies[rad].setFixedWidth(25)
            self.radiusQuickies[rad].connect('clicked()', callback)
            self.radiusQuickies[rad].setToolTip(
                "Set radius based on mm or label voxel size units depending on toggle value"
            )

        self.radius = ctk.ctkDoubleSlider(self.frame)
        self.radius.objectName = 'DoubleSlider_Radius'
        self.radius.minimum = self.minimumRadius
        self.radius.maximum = self.maximumRadius
        self.radius.orientation = 1
        self.radius.singleStep = self.minimumRadius
        self.frame.layout().addWidget(self.radius)
        self.widgets.append(self.radius)

        self.sphere = qt.QCheckBox("Sphere", self.frame)
        self.sphere.objectName = 'CheckBox_Sphere'
        self.sphere.setToolTip(
            "Use a 3D spherical brush rather than a 2D circular brush.")
        self.frame.layout().addWidget(self.sphere)
        self.widgets.append(self.sphere)

        self.smudge = qt.QCheckBox("Smudge", self.frame)
        self.smudge.objectName = 'CheckBox_Smudge'
        self.smudge.setToolTip(
            "Set the label number automatically by sampling the pixel location where the brush stroke starts."
        )
        self.frame.layout().addWidget(self.smudge)
        self.widgets.append(self.smudge)

        self.pixelMode = qt.QCheckBox("Pixel Mode", self.frame)
        self.pixelMode.objectName = 'CheckBox_PixelMode'
        self.pixelMode.setToolTip(
            "Paint exactly the pixel under the cursor, ignoring the radius, threshold, and paint over."
        )
        self.frame.layout().addWidget(self.pixelMode)
        self.widgets.append(self.pixelMode)

        HelpButton(
            self.frame,
            "Use this tool to paint with a round brush of the selected radius")

        self.connections.append(
            (self.sphere, 'clicked()', self.updateMRMLFromGUI))
        self.connections.append(
            (self.smudge, 'clicked()', self.updateMRMLFromGUI))
        self.connections.append(
            (self.pixelMode, 'clicked()', self.updateMRMLFromGUI))
        self.connections.append(
            (self.radius, 'valueChanged(double)', self.onRadiusValueChanged))
        self.connections.append((self.radiusSpinBox, 'valueChanged(double)',
                                 self.onRadiusSpinBoxChanged))

        # Add vertical spacer
        self.frame.layout().addStretch(1)
예제 #14
0
  def create(self):
    super(PaintEffectOptions,self).create()

    self.radiusFrame = qt.QFrame(self.frame)
    self.radiusFrame.setLayout(qt.QHBoxLayout())
    self.frame.layout().addWidget(self.radiusFrame)
    self.widgets.append(self.radiusFrame)
    self.radiusLabel = qt.QLabel("Radius:", self.radiusFrame)
    self.radiusLabel.setToolTip("Set the radius of the paint brush in millimeters")
    self.radiusFrame.layout().addWidget(self.radiusLabel)
    self.widgets.append(self.radiusLabel)
    self.radiusSpinBox = slicer.qMRMLSpinBox(self.radiusFrame)
    self.radiusSpinBox.objectName = 'SpinBox_Radius'
    self.radiusSpinBox.setToolTip("Set the radius of the paint brush in millimeters")
    self.radiusSpinBox.quantity = "length"
    # QFlags not wrapped in python. Equivalent to Prefix | Suffix
    # See qMRMLSpinBox for more details.
    self.radiusSpinBox.unitAwareProperties = 0x01 | 0x02
    self.radiusSpinBox.minimum = self.minimumRadius
    self.radiusSpinBox.maximum = self.maximumRadius
    self.radiusSpinBox.setMRMLScene(slicer.mrmlScene)
    from math import log,floor
    decimals = floor(log(self.minimumRadius,10))
    if decimals < 0:
      self.radiusSpinBox.decimals = -decimals + 2
    self.radiusFrame.layout().addWidget(self.radiusSpinBox)
    self.widgets.append(self.radiusSpinBox)
    self.radiusUnitsToggle = qt.QPushButton("px:")
    self.radiusUnitsToggle.objectName = 'PushButton_RadiusUnitsToggle'
    self.radiusUnitsToggle.setToolTip("Toggle radius quick set buttons between mm and label volume pixel size units")
    self.radiusUnitsToggle.setFixedWidth(35)
    self.radiusFrame.layout().addWidget(self.radiusUnitsToggle)
    self.radiusUnitsToggle.connect('clicked()',self.onRadiusUnitsToggle)
    self.radiusQuickies = {}
    quickies = ( (2, self.onQuickie2Clicked), (3,self.onQuickie3Clicked),
                 (4, self.onQuickie4Clicked), (5, self.onQuickie5Clicked),
                 (10, self.onQuickie10Clicked), (20, self.onQuickie20Clicked) )
    for rad,callback in quickies:
      self.radiusQuickies[rad] = qt.QPushButton(str(rad))
      self.radiusQuickies[rad].objectName = 'PushButton_QuickRadius_{0}'.format(rad)
      self.radiusFrame.layout().addWidget(self.radiusQuickies[rad])
      self.radiusQuickies[rad].setFixedWidth(25)
      self.radiusQuickies[rad].connect('clicked()', callback)
      self.radiusQuickies[rad].setToolTip("Set radius based on mm or label voxel size units depending on toggle value")

    self.radius = ctk.ctkDoubleSlider(self.frame)
    self.radius.objectName = 'DoubleSlider_Radius'
    self.radius.minimum = self.minimumRadius
    self.radius.maximum = self.maximumRadius
    self.radius.orientation = 1
    self.radius.singleStep = self.minimumRadius
    self.frame.layout().addWidget(self.radius)
    self.widgets.append(self.radius)

    self.sphere = qt.QCheckBox("Sphere", self.frame)
    self.sphere.objectName = 'CheckBox_Sphere'
    self.sphere.setToolTip("Use a 3D spherical brush rather than a 2D circular brush.")
    self.frame.layout().addWidget(self.sphere)
    self.widgets.append(self.sphere)

    self.smudge = qt.QCheckBox("Smudge", self.frame)
    self.smudge.objectName = 'CheckBox_Smudge'
    self.smudge.setToolTip("Set the label number automatically by sampling the pixel location where the brush stroke starts.")
    self.frame.layout().addWidget(self.smudge)
    self.widgets.append(self.smudge)

    self.pixelMode = qt.QCheckBox("Pixel Mode", self.frame)
    self.pixelMode.objectName = 'CheckBox_PixelMode'
    self.pixelMode.setToolTip("Paint exactly the pixel under the cursor, ignoring the radius, threshold, and paint over.")
    self.frame.layout().addWidget(self.pixelMode)
    self.widgets.append(self.pixelMode)

    HelpButton(self.frame, "Use this tool to paint with a round brush of the selected radius")

    self.connections.append( (self.sphere, 'clicked()', self.updateMRMLFromGUI) )
    self.connections.append( (self.smudge, 'clicked()', self.updateMRMLFromGUI) )
    self.connections.append( (self.pixelMode, 'clicked()', self.updateMRMLFromGUI) )
    self.connections.append( (self.radius, 'valueChanged(double)', self.onRadiusValueChanged) )
    self.connections.append( (self.radiusSpinBox, 'valueChanged(double)', self.onRadiusSpinBoxChanged) )

    # Add vertical spacer
    self.frame.layout().addStretch(1)
예제 #15
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        self.logic = CreateMeshLogic()

        # Inputs
        inputsCollapsibleButton = ctk.ctkCollapsibleButton()
        inputsCollapsibleButton.text = 'Inputs'
        self.layout.addWidget(inputsCollapsibleButton)
        inputsFormLayout = qt.QFormLayout(inputsCollapsibleButton)

        # Segmentation selector
        self.segmentationSelector = slicer.qMRMLNodeComboBox()
        self.segmentationSelector.nodeTypes = ['vtkMRMLSegmentationNode']
        self.segmentationSelector.addEnabled = False
        self.segmentationSelector.removeEnabled = False
        self.segmentationSelector.renameEnabled = False
        self.segmentationSelector.setMRMLScene(slicer.mrmlScene)
        self.segmentationSelector.setToolTip(
            'Pick the segmentation to compute a mesh from')
        inputsFormLayout.addRow('Segmentation:', self.segmentationSelector)
        # Fiducials selector
        self.fiducialsSelector = slicer.qMRMLNodeComboBox()
        self.fiducialsSelector.nodeTypes = ['vtkMRMLMarkupsFiducialNode']
        self.fiducialsSelector.addEnabled = False
        self.fiducialsSelector.removeEnabled = False
        self.fiducialsSelector.renameEnabled = False
        self.fiducialsSelector.setMRMLScene(slicer.mrmlScene)
        self.fiducialsSelector.setToolTip(
            'Select the fiducials that will define the light sources and detectors position'
        )
        inputsFormLayout.addRow('Fiducials:', self.fiducialsSelector)

        # Outputs
        outputsCollapsibleButton = ctk.ctkCollapsibleButton()
        outputsCollapsibleButton.text = 'Outputs'
        self.layout.addWidget(outputsCollapsibleButton)
        outputsFormLayout = qt.QFormLayout(outputsCollapsibleButton)

        # Mesh directory
        self.meshPathLineEdit = ctk.ctkPathLineEdit()
        self.meshPathLineEdit.filters = ctk.ctkPathLineEdit.Dirs
        self.meshPathLineEdit.currentPath = self.cachedPathFor(
            'CreateMeshOutputPath')
        outputsFormLayout.addRow('Mesh directory:', self.meshPathLineEdit)
        # Mesh name
        self.meshNameField = qt.QLineEdit()
        outputsFormLayout.addRow('Mesh name:', self.meshNameField)

        # Meshing
        meshingCollapsibleButton = ctk.ctkCollapsibleButton()
        meshingCollapsibleButton.text = 'Meshing'
        self.layout.addWidget(meshingCollapsibleButton)
        meshingFormLayout = qt.QFormLayout(meshingCollapsibleButton)

        # Mesh type
        self.meshTypeComboBox = ctk.ctkComboBox()
        for meshType in self.logic.meshTypes:
            self.meshTypeComboBox.addItem(meshType)
        meshingFormLayout.addRow('Mesh type:', self.meshTypeComboBox)
        # Cell size
        self.cellSizeSpinBox = slicer.qMRMLSpinBox()
        self.cellSizeSpinBox.setValue(1.5)
        self.cellSizeSpinBox.setMRMLScene(slicer.mrmlScene)
        meshingFormLayout.addRow('Cell size:', self.cellSizeSpinBox)
        # Cell radius edge
        self.cellRadiusSpinBox = slicer.qMRMLSpinBox()
        self.cellRadiusSpinBox.setValue(3.0)
        self.cellRadiusSpinBox.setMRMLScene(slicer.mrmlScene)
        meshingFormLayout.addRow('Cell radius edge:', self.cellRadiusSpinBox)
        # Facet size
        self.facetSizeSpinBox = slicer.qMRMLSpinBox()
        self.facetSizeSpinBox.setValue(1.5)
        self.facetSizeSpinBox.setMRMLScene(slicer.mrmlScene)
        meshingFormLayout.addRow('Facet size:', self.facetSizeSpinBox)
        # Facet angle
        self.facetAngleSpinBox = slicer.qMRMLSpinBox()
        self.facetAngleSpinBox.setValue(25.0)
        self.facetAngleSpinBox.setMRMLScene(slicer.mrmlScene)
        meshingFormLayout.addRow('Facet angle:', self.facetAngleSpinBox)
        # Facet distance
        self.facetDistanceSpinBox = slicer.qMRMLSpinBox()
        self.facetDistanceSpinBox.setValue(3.0)
        self.facetDistanceSpinBox.setMRMLScene(slicer.mrmlScene)
        meshingFormLayout.addRow('Facet distance:', self.facetDistanceSpinBox)
        # Optimize mesh
        self.optimizeCheckBox = qt.QCheckBox()
        meshingFormLayout.addRow('Optimize mesh:', self.optimizeCheckBox)

        # NIRFAST
        nirfastCollapsibleButton = ctk.ctkCollapsibleButton()
        nirfastCollapsibleButton.text = 'NIRFAST Matlab'
        self.layout.addWidget(nirfastCollapsibleButton)
        nirfastFormLayout = qt.QFormLayout(nirfastCollapsibleButton)

        # NIRFAST-Matlab
        self.nirfastMatlabPathLineEdit = ctk.ctkPathLineEdit()
        self.nirfastMatlabPathLineEdit.filters = ctk.ctkPathLineEdit.Dirs
        self.nirfastMatlabPathLineEdit.currentPath = self.cachedPathFor(
            'NIRFASTMatlabPath')
        nirfastFormLayout.addRow('NIRFAST Matlab:',
                                 self.nirfastMatlabPathLineEdit)

        # Run
        self.runButton = qt.QPushButton()
        self.runButton.setCheckable(True)
        self.setRunning(False)
        self.layout.addWidget(self.runButton)

        # Progress
        self.progressBar = slicer.qSlicerCLIProgressBar()
        self.logic.setProgressBar(self.progressBar)
        self.layout.addWidget(self.progressBar)

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

        # Connections
        self.segmentationSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                          self.onSegmentationNodeChanged)
        self.onSegmentationNodeChanged(self.segmentationSelector.currentNode())
        self.meshPathLineEdit.connect('currentPathChanged(QString)',
                                      self.logic.cacheOutputMeshDir)
        self.nirfastMatlabPathLineEdit.connect(
            'currentPathChanged(QString)', self.logic.cacheNirfastMatlabDir)
        self.runButton.connect('clicked()', self.onRun)
        self.logic.setBusy = self.setRunning
        self.logic.setError = self.showError