def create(self):
        super(RemoveIslandsEffectOptions, self).create()

        self.applyConnectivity = qt.QPushButton("Apply Connectivity Method",
                                                self.frame)
        self.applyConnectivity.setToolTip(
            "Remove islands that are not connected at all to the surface.  Islands with thin connections will not be removed."
        )
        self.frame.layout().addWidget(self.applyConnectivity)
        self.widgets.append(self.applyConnectivity)

        self.applyMorphology = qt.QPushButton("Apply Morphology Method",
                                              self.frame)
        self.applyMorphology.setToolTip(
            "Remove islands by erosion and dilation so that small islands are removed even if they are connected to the outside or if they exist on the outside of the larger segmented regions."
        )
        self.frame.layout().addWidget(self.applyMorphology)
        self.widgets.append(self.applyMorphology)

        self.connections.append(
            (self.applyConnectivity, 'clicked()', self.onApplyConnectivity))
        self.connections.append(
            (self.applyMorphology, 'clicked()', self.onApplyMorphology))

        HelpButton(
            self.frame,
            "Remove connected regions (islands) that are fully enclosed by the current label color and are smaller than the given minimum size."
        )

        # Add vertical spacer
        self.frame.layout().addStretch(1)
Exemple #2
0
    def create(self):
        super(GrowCutEffectOptions, self).create()

        self.helpLabel = qt.QLabel(
            "Run the GrowCut segmentation on the current label map.\nThis will use your current segmentation as an example\nto fill in the rest of the volume.",
            self.frame)
        self.frame.layout().addWidget(self.helpLabel)

        self.apply = qt.QPushButton("Apply", self.frame)
        self.apply.objectName = self.__class__.__name__ + 'Apply'
        self.apply.setToolTip(
            "Apply to run segmentation.\nCreates a new label volume using the current volume as input"
        )
        self.frame.layout().addWidget(self.apply)
        self.widgets.append(self.apply)

        HelpButton(
            self.frame,
            "Use this tool to apply grow cut segmentation.\n\n Select different label colors and paint on foreground and background or as many different classes as you want using the standard drawing tools.\nTo run segmentation correctly, you need to supply a minimum or two class labels."
        )

        self.connections.append((self.apply, 'clicked()', self.onApply))

        # Add vertical spacer
        self.frame.layout().addStretch(1)
Exemple #3
0
    def create(self):
        super(ChangeLabelEffectOptions, self).create()
        self.logic.undoRedo = self.undoRedo
        import EditColor
        self.inputColor = EditColor.EditColor(self.frame,
                                              'ChangeLabelEffect,inputColor')
        self.inputColor.label.setText("Input Color:")
        self.inputColor.colorSpin.setToolTip("Set the label value to replace.")

        self.outputColor = EditColor.EditColor(
            self.frame, 'ChangeLabelEffect,outputColor')
        self.outputColor.label.setText("Output Color:")
        self.outputColor.colorSpin.setToolTip("Set the new label value")

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

        HelpButton(
            self.frame,
            "Replace all instances of input color with output color in current label map"
        )

        self.connections.append((self.apply, 'clicked()', self.onApply))

        # Add vertical spacer
        self.frame.layout().addStretch(1)
Exemple #4
0
  def create(self):
    super(RectangleEffectOptions,self).create()

    HelpButton(self.frame, "Use this tool to draw a rectangle.\n\nLeft Click and Drag: sweep out an outline that will draw when the button is released.")

    # Add vertical spacer
    self.frame.layout().addStretch(1)
  def create(self):
    super(LevelTracingEffectOptions,self).create()

    HelpButton(self.frame, "Use this tool to track around similar intensity levels.\n\nAs you move the mouse, the current background voxel is used to find a closed path that follows the same intensity value back to the starting point within the current slice.  Pressing the left mouse button fills the the path according to the current labeling rules.")

    # Add vertical spacer
    self.frame.layout().addStretch(1)
Exemple #6
0
    def create(self):
        super(MakeModelEffectOptions, self).create()

        self.goToModelMaker = qt.QPushButton("Go To Model Maker", self.frame)
        self.goToModelMaker.setToolTip(
            "The Model Maker interface contains a whole range of options for building sets of models and controlling the parameters."
        )
        self.frame.layout().addWidget(self.goToModelMaker)
        self.widgets.append(self.goToModelMaker)

        self.smooth = qt.QCheckBox("Smooth Model", self.frame)
        self.smooth.checked = True
        self.smooth.setToolTip(
            "When smoothed, the model will look better, but some details of the label map will not be visible on the model.  When not smoothed you will see individual voxel boundaries in the model.  Smoothing here corresponds to Decimation of 0.25 and Smooting iterations of 10."
        )
        self.frame.layout().addWidget(self.smooth)
        self.widgets.append(self.smooth)

        #
        # model name
        #
        self.nameFrame = qt.QFrame(self.frame)
        self.nameFrame.setLayout(qt.QHBoxLayout())
        self.frame.layout().addWidget(self.nameFrame)
        self.widgets.append(self.nameFrame)

        self.modelNameLabel = qt.QLabel("Model Name: ", self.nameFrame)
        self.modelNameLabel.setToolTip(
            "Select the name for the newly created model.")
        self.nameFrame.layout().addWidget(self.modelNameLabel)
        self.widgets.append(self.modelNameLabel)

        self.modelName = qt.QLineEdit(self.nameFrame)
        self.modelName.setText(self.getUniqueModelName(
            EditUtil.getLabelName()))
        self.nameFrame.layout().addWidget(self.modelName)
        self.widgets.append(self.modelName)

        self.apply = qt.QPushButton("Apply", self.frame)
        self.apply.objectName = self.__class__.__name__ + 'Apply'
        self.apply.setToolTip(
            "Build a model for the current label value of the label map being edited in the Red slice window.  Model will be created in the background."
        )
        self.frame.layout().addWidget(self.apply)
        self.widgets.append(self.apply)

        HelpButton(
            self.frame,
            "Use this tool build a model.  A subset of model building options is provided here.  Go to the Model Maker module to expose a range of parameters.  Use Merge and Build button in the Advanced... tab to quickly make a model of all defined structures in the merge label map."
        )

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

        self.connections.append((self.apply, 'clicked()', self.onApply))
        self.connections.append(
            (self.goToModelMaker, 'clicked()', self.onGoToModelMaker))
Exemple #7
0
    def create(self):
        super(FastMarchingEffectOptions, self).create()

        self.defaultMaxPercent = 30

        self.percentLabel = qt.QLabel(
            'Expected structure volume as % of image volume:', self.frame)
        self.percentLabel.setToolTip(
            'Segmentation will grow from the seed label until this value is reached'
        )
        self.frame.layout().addWidget(self.percentLabel)
        self.widgets.append(self.percentLabel)

        self.percentMax = ctk.ctkSliderWidget(self.frame)
        self.percentMax.minimum = 0
        self.percentMax.maximum = 100
        self.percentMax.singleStep = 1
        self.percentMax.value = self.defaultMaxPercent
        self.percentMax.setToolTip(
            'Approximate volume of the structure to be segmented relative to the total volume of the image'
        )
        self.frame.layout().addWidget(self.percentMax)
        self.widgets.append(self.percentMax)
        self.percentMax.connect('valueChanged(double)', self.percentMaxChanged)

        self.march = qt.QPushButton("March", self.frame)
        self.march.setToolTip(
            "Perform the Marching operation into the current label map")
        self.frame.layout().addWidget(self.march)
        self.widgets.append(self.march)

        self.percentVolume = qt.QLabel('Maximum volume of the structure: ')
        self.percentVolume.setToolTip('Total maximum volume')
        self.frame.layout().addWidget(self.percentVolume)
        self.widgets.append(self.percentVolume)

        self.marcher = ctk.ctkSliderWidget(self.frame)
        self.marcher.minimum = 0
        self.marcher.maximum = 1
        self.marcher.singleStep = 0.01
        self.marcher.enabled = False
        self.frame.layout().addWidget(self.marcher)
        self.widgets.append(self.marcher)
        self.marcher.connect('valueChanged(double)', self.onMarcherChanged)

        HelpButton(
            self.frame,
            "To use FastMarching effect, first mark the areas that belong to the structure of interest to initialize the algorithm. Define the expected volume of the structure you are trying to segment, and hit March.\nAfter computation is complete, use the Marcher slider to go over the segmentation history."
        )

        self.march.connect('clicked()', self.onMarch)

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

        self.percentMaxChanged(self.percentMax.value)
Exemple #8
0
    def create(self):
        super(ThresholdEffectOptions, self).create()

        self.thresholdLabel = qt.QLabel("Threshold Range:", self.frame)
        self.thresholdLabel.setToolTip(
            "Set the range of the background values that should be labeled.")
        self.frame.layout().addWidget(self.thresholdLabel)
        self.widgets.append(self.thresholdLabel)
        self.threshold = ctk.ctkRangeWidget(self.frame)
        self.threshold.spinBoxAlignment = 0xff  # put enties on top
        self.threshold.singleStep = 0.01
        # set min/max based on current range
        success, lo, hi = self.getBackgroundScalarRange()
        if success:
            self.threshold.minimum, self.threshold.maximum = lo, hi
            self.threshold.singleStep = (hi - lo) / 1000.
        self.frame.layout().addWidget(self.threshold)
        self.widgets.append(self.threshold)

        self.useForPainting = qt.QPushButton("Use For Paint", self.frame)
        self.useForPainting.setToolTip(
            "Transfer the current threshold settings to be used for labeling operations such as Paint and Draw."
        )
        self.frame.layout().addWidget(self.useForPainting)
        self.widgets.append(self.useForPainting)

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

        self.timer = qt.QTimer()
        self.previewState = 0
        self.previewStep = 1
        self.previewSteps = 5
        self.timer.start(200)

        self.connections.append((self.timer, 'timeout()', self.preview))
        self.connections.append(
            (self.useForPainting, 'clicked()', self.onUseForPainting))
        self.connections.append(
            (self.threshold, 'valuesChanged(double,double)',
             self.onThresholdValuesChanged))
        self.connections.append((self.apply, 'clicked()', self.onApply))

        HelpButton(
            self.frame,
            "Set labels based on threshold range.  Note: this replaces the current label map values."
        )

        # Add vertical spacer
        self.frame.layout().addStretch(1)
Exemple #9
0
  def create(self):
    super(SaveIslandEffectOptions,self).create()
    # don't need minimum size or fully connected options for this
    self.sizeLabel.hide()
    self.minimumSize.hide()
    self.fullyConnected.hide()

    self.helpLabel = qt.QLabel("Click on segmented region to remove all\nsegmentation not directly connected to it.", self.frame)
    self.frame.layout().addWidget(self.helpLabel)

    HelpButton(self.frame, "Save the connected region (island) where you click.")

    # Add vertical spacer
    self.frame.layout().addStretch(1)
Exemple #10
0
    def create(self):
        super(DilateEffectOptions, self).create()
        self.apply = qt.QPushButton("Apply", self.frame)
        self.apply.objectName = self.__class__.__name__ + 'Apply'
        self.apply.setToolTip("Dilate current label")
        self.frame.layout().addWidget(self.apply)
        self.widgets.append(self.apply)

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

        self.connections.append((self.apply, 'clicked()', self.onApply))

        # Add vertical spacer
        self.frame.layout().addStretch(1)
Exemple #11
0
    def create(self):
        super(IdentifyIslandsEffectOptions, self).create()

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

        self.connections.append((self.apply, 'clicked()', self.onApply))

        HelpButton(
            self.frame,
            "IdentifyIslands: create a unique label for islands larger than minimum size (label number is ordered by size of island)"
        )

        # Add vertical spacer
        self.frame.layout().addStretch(1)
Exemple #12
0
    def create(self):
        super(DrawEffectOptions, self).create()

        self.apply = qt.QPushButton("Apply", self.frame)
        self.apply.objectName = self.__class__.__name__ + 'Apply'
        self.apply.setToolTip(
            "Apply current outline.\nUse the 'a' or 'Enter' hotkey to apply in slice window"
        )
        self.frame.layout().addWidget(self.apply)
        self.widgets.append(self.apply)

        HelpButton(
            self.frame,
            "Use this tool to draw an outline.\n\nLeft Click: add point.\nLeft Drag: add multiple points.\nx: delete last point.\na: apply outline."
        )

        self.connections.append((self.apply, 'clicked()', self.onApply))

        # Add vertical spacer
        self.frame.layout().addStretch(1)
Exemple #13
0
    def create(self):
        super(WandEffectOptions, self).create()

        self.toleranceFrame = qt.QFrame(self.frame)
        self.toleranceFrame.setLayout(qt.QHBoxLayout())
        self.frame.layout().addWidget(self.toleranceFrame)
        self.widgets.append(self.toleranceFrame)
        self.toleranceLabel = qt.QLabel("Tolerance:", self.toleranceFrame)
        self.toleranceLabel.setToolTip(
            "Set the tolerance of the wand in terms of background pixel values"
        )
        self.toleranceFrame.layout().addWidget(self.toleranceLabel)
        self.widgets.append(self.toleranceLabel)
        self.toleranceSpinBox = ctk.ctkDoubleSpinBox(self.toleranceFrame)
        self.toleranceSpinBox.setToolTip(
            "Set the tolerance of the wand in terms of background pixel values"
        )
        self.toleranceSpinBox.minimum = 0
        self.toleranceSpinBox.maximum = 1000
        self.toleranceSpinBox.suffix = ""
        self.toleranceFrame.layout().addWidget(self.toleranceSpinBox)
        self.widgets.append(self.toleranceSpinBox)

        self.maxPixelsFrame = qt.QFrame(self.frame)
        self.maxPixelsFrame.setLayout(qt.QHBoxLayout())
        self.frame.layout().addWidget(self.maxPixelsFrame)
        self.widgets.append(self.maxPixelsFrame)
        self.maxPixelsLabel = qt.QLabel("Max Pixels per click:",
                                        self.maxPixelsFrame)
        self.maxPixelsLabel.setToolTip("Set the maxPixels for each click")
        self.maxPixelsFrame.layout().addWidget(self.maxPixelsLabel)
        self.widgets.append(self.maxPixelsLabel)
        self.maxPixelsSpinBox = ctk.ctkDoubleSpinBox(self.maxPixelsFrame)
        self.maxPixelsSpinBox.setToolTip("Set the maxPixels for each click")
        self.maxPixelsSpinBox.minimum = 1
        self.maxPixelsSpinBox.maximum = 100000
        self.maxPixelsSpinBox.suffix = ""
        self.maxPixelsFrame.layout().addWidget(self.maxPixelsSpinBox)
        self.widgets.append(self.maxPixelsSpinBox)

        self.fillModeFrame = qt.QFrame(self.frame)
        self.fillModeFrame.setLayout(qt.QHBoxLayout())
        self.frame.layout().addWidget(self.fillModeFrame)
        self.widgets.append(self.fillModeFrame)
        self.fillModeCheckBox = qt.QCheckBox(self.fillModeFrame)
        self.fillModeCheckBox.text = "Fill Volume"
        self.fillModeCheckBox.setToolTip(
            "Fill in 3D when checked, else fill plane")
        self.fillModeFrame.layout().addWidget(self.fillModeCheckBox)
        self.widgets.append(self.fillModeCheckBox)

        HelpButton(
            self.frame,
            "Use this tool to label all voxels that are within a tolerance of where you click"
        )

        # don't connect the signals and slots directly - instead, add these
        # to the list of connections so that gui callbacks can be cleanly
        # disabled while the gui is being updated.  This allows several gui
        # elements to be interlinked with signal/slots but still get updated
        # as a unit to the new value of the mrml node.
        self.connections.append((self.toleranceSpinBox, 'valueChanged(double)',
                                 self.onToleranceSpinBoxChanged))
        self.connections.append((self.maxPixelsSpinBox, 'valueChanged(double)',
                                 self.onMaxPixelsSpinBoxChanged))
        self.connections.append(
            (self.fillModeCheckBox, 'clicked()', self.onFillModeClicked))

        # Add vertical spacer
        self.frame.layout().addStretch(1)
Exemple #14
0
    def create(self):
        super(WatershedFromMarkerEffectOptions, self).create()

        if not HAVE_SIMPLEITK:
            self.warningLabel = qt.QLabel()
            self.warningLabel.text = "WatershedFromMarker is not available because\nSimpleITK is not available in this build"
            self.widgets.append(self.warningLabel)
            self.frame.layout().addWidget(self.warningLabel)
            return

        labelVolume = EditUtil.getLabelVolume()
        if labelVolume and labelVolume.GetImageData():
            spacing = labelVolume.GetSpacing()
            self.minimumSigma = 0.1 * min(spacing)
            self.maximumSigma = 100 * self.minimumSigma
        else:
            self.minimumSigma = 0.1
            self.maximumSigma = 10

        self.sigmaFrame = qt.QFrame(self.frame)
        self.sigmaFrame.setLayout(qt.QHBoxLayout())
        self.frame.layout().addWidget(self.sigmaFrame)
        self.widgets.append(self.sigmaFrame)

        tip = "Increasing this value smooths the segmentation and reduces leaks. This is the sigma used for edge detection."
        self.sigmaLabel = qt.QLabel("Object Scale: ", self.frame)
        self.sigmaLabel.setToolTip(tip)
        self.sigmaFrame.layout().addWidget(self.sigmaLabel)
        self.widgets.append(self.sigmaLabel)

        self.sigmaSlider = qt.QSlider(qt.Qt.Horizontal, self.frame)
        self.sigmaFrame.layout().addWidget(self.sigmaSlider)
        self.sigmaFrame.setToolTip(tip)
        self.widgets.append(self.sigmaSlider)

        self.sigmaSpinBox = qt.QDoubleSpinBox(self.frame)
        self.sigmaSpinBox.setToolTip(tip)
        self.sigmaSpinBox.suffix = "mm"

        self.sigmaFrame.layout().addWidget(self.sigmaSpinBox)
        self.widgets.append(self.sigmaSpinBox)

        self.sigmaSpinBox.minimum = self.minimumSigma
        self.sigmaSlider.minimum = self.minimumSigma
        self.sigmaSpinBox.maximum = self.maximumSigma
        self.sigmaSlider.maximum = self.maximumSigma

        decimals = math.floor(math.log(self.minimumSigma, 10))
        if decimals < 0:
            self.sigmaSpinBox.decimals = -decimals + 2

        self.apply = qt.QPushButton("Apply", self.frame)
        self.apply.objectName = self.__class__.__name__ + 'Apply'
        self.apply.setToolTip("Apply the extension operation")

        self.frame.layout().addWidget(self.apply)
        self.widgets.append(self.apply)

        helpDoc = \
            """Use this effect to apply the watershed from markers segmentation from multiple initial labels.

The input to this filter is current labelmap image which is expected to contain multiple labels as initial marks. The marks or labels are grown to fill the image and with edges defining the bondaries between. To segment a single object, mark the object, and then it is suggested to surround the object with a negative label on each axis.

The "Object Scale" parameter is use to adjust the smoothness of the output image and prevent leakage. It is used internally for the sigma of the gradient magnitude.
    """
        HelpButton(self.frame, helpDoc)

        self.sigmaSlider.connect('valueChanged(int)',
                                 self.sigmaSpinBox.setValue)
        self.sigmaSpinBox.connect('valueChanged(double)',
                                  self.sigmaSlider.setValue)

        # if either widget is changed both should change and this should be triggered
        self.connections.append((self.sigmaSpinBox, 'valueChanged(double)',
                                 self.onSigmaValueChanged))

        self.connections.append((self.apply, 'clicked()', self.onApply))

        # Add vertical spacer
        self.frame.layout().addStretch(1)
Exemple #15
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)