Esempio n. 1
0
    def setup(self):
        """This is called one time when the module GUI is initialized
        """
        # Declare ALL the GUI components (depending on the context we will add different ones to the layout)
        self.widgetMainFrame = qt.QFrame()
        self.widgetMainLayout = qt.QGridLayout()
        self.widgetMainFrame.setLayout(self.widgetMainLayout)
        self.layout.addWidget(self.widgetMainFrame)

        ## Context
        self.contextLabel = qt.QLabel("Context")
        self.contextComboBox = qt.QComboBox()
        for context in self.contexts.values():
            self.contextComboBox.addItem(context)

        ## Operation
        self.operationLabel = qt.QLabel("Optimization")
        self.operationComboBox = qt.QComboBox()
        for operation in self.operations.values():
            if operation != self.OPERATION_NONE:
                self.operationComboBox.addItem(operation)
        ## Plane
        self.planeLabel = qt.QLabel("Plane")
        # Buttons group
        self.planesButtonGroup = qt.QButtonGroup()
        # Axial
        self.axialButton = qt.QPushButton()
        self.axialButton.setCheckable(True)
        self.axialButton.toolTip = "Axial plane"
        self.axialButton.setFixedSize(40, 40)
        self.axialButton.setIcon(SlicerUtil.getIcon("axial.png"))
        self.planesButtonGroup.addButton(self.axialButton, self.PLANE_AXIAL)
        # Sagittal
        self.sagittalButton = qt.QPushButton()
        self.sagittalButton.setCheckable(True)
        self.sagittalButton.toolTip = "Sagittal plane"
        self.sagittalButton.setFixedSize(40, 40)
        self.sagittalButton.setIcon(SlicerUtil.getIcon("sagittal.png"))
        self.widgetMainLayout.addWidget(self.sagittalButton, 2, 2,
                                        SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
        self.planesButtonGroup.addButton(self.sagittalButton,
                                         self.PLANE_SAGITTAL)
        # Coronal
        self.coronalButton = qt.QPushButton()
        self.coronalButton.setCheckable(True)
        self.coronalButton.toolTip = "coronal plane"
        self.coronalButton.setFixedSize(40, 40)
        self.coronalButton.setIcon(SlicerUtil.getIcon("coronal.png"))
        self.planesButtonGroup.addButton(self.coronalButton,
                                         self.PLANE_CORONAL)
        # Null button (to uncheck all)
        self.nullPlaneButton = qt.QPushButton()
        self.nullPlaneButton.setCheckable(True)
        self.planesButtonGroup.addButton(self.nullPlaneButton, -1)
        # Buttons labels
        self.axialButtonLabel = qt.QLabel("Axial")
        self.axialButtonLabel.setStyleSheet("margin-bottom: 10px")
        self.sagittalButtonLabel = qt.QLabel("Sagittal")
        self.sagittalButtonLabel.setStyleSheet("margin-bottom: 10px")
        self.coronalButtonLabel = qt.QLabel("Coronal")
        self.coronalButtonLabel.setStyleSheet("margin-bottom: 10px")

        ## Layout
        self.layoutLabel = qt.QLabel("Layout")
        # Buttons group
        self.layoutsButtonGroup = qt.QButtonGroup()
        # Single slice Button
        self.singleSlideViewButton = qt.QPushButton()
        self.singleSlideViewButton.setCheckable(True)
        self.singleSlideViewButton.toolTip = "Single slice view"
        self.singleSlideViewButton.setFixedSize(40, 40)
        self.singleSlideViewButton.setIcon(
            qt.QIcon(":/Icons/LayoutOneUpRedSliceView.png"))
        self.layoutsButtonGroup.addButton(self.singleSlideViewButton,
                                          self.LAYOUT_RED_ONLY)
        # Side by side Button
        self.sideBySideViewButton = qt.QPushButton()
        self.sideBySideViewButton.setCheckable(True)
        self.sideBySideViewButton.toolTip = "Side by side view"
        self.sideBySideViewButton.setFixedSize(40, 40)
        self.sideBySideViewButton.setIcon(
            qt.QIcon(":/Icons/LayoutSideBySideView.png"))
        self.layoutsButtonGroup.addButton(self.sideBySideViewButton,
                                          self.LAYOUT_SIDE_BY_SIDE)
        # Three over three button
        self.threeOverThreeViewButton = qt.QPushButton()
        self.threeOverThreeViewButton.setCheckable(True)
        self.threeOverThreeViewButton.toolTip = "Compare 2 images in their 3 planes"
        self.threeOverThreeViewButton.setFixedSize(40, 40)
        self.threeOverThreeViewButton.setIcon(
            qt.QIcon(":/Icons/LayoutThreeOverThreeView.png"))
        self.layoutsButtonGroup.addButton(self.threeOverThreeViewButton,
                                          self.LAYOUT_THREE_OVER_THREE)
        # Comparative MIP-MinIP button
        self.maxMinCompareViewButton = qt.QPushButton()
        self.maxMinCompareViewButton.setCheckable(True)
        self.maxMinCompareViewButton.toolTip = "MIP and MinIP comparison"
        self.maxMinCompareViewButton.setFixedSize(40, 40)
        self.maxMinCompareViewButton.setIcon(
            qt.QIcon(":/Icons/LayoutFourUpView.png"))
        self.layoutsButtonGroup.addButton(self.maxMinCompareViewButton,
                                          self.LAYOUT_COMPARE)
        # Null button (to uncheck all)
        self.nullLayoutButton = qt.QPushButton()
        self.nullLayoutButton.setCheckable(True)
        self.layoutsButtonGroup.addButton(self.nullLayoutButton, -2)
        # Reset Button
        self.resetViewButton = qt.QPushButton()
        self.resetViewButton.toolTip = "Go back to the original layout"
        self.resetViewButton.setFixedSize(40, 40)
        # self.resetViewButton.setIconSize(qt.QSize(24, 24))
        self.resetViewButton.setIcon(
            qt.QIcon(os.path.join(SlicerUtil.CIP_ICON_DIR, "Reload.png")))
        # Buttons labels
        self.singleSlideButtonLabel = qt.QLabel("Single")
        self.sideBySideButtonLabel = qt.QLabel("Side by side")
        self.threeOverThreeButtonLabel = qt.QLabel("3x3")
        self.maxMinCompareButtonLabel = qt.QLabel("MIP+MinIP")
        self.resetLabel = qt.QLabel("Reset")
        self.resetLabel.setStyleSheet("font-weight: bold")

        # Number of slices (different for each operation). The size of the slider also changes
        self.spacingSliderItems = OrderedDict()
        spacingLabel = qt.QLabel("Slice size " +
                                 self.operations[self.OPERATION_MIP])
        spacingSlider = qt.QSlider()
        spacingSlider.orientation = 1
        spacingSlider.setTickPosition(2)
        spacingSlider.minimum = 0
        spacingSlider.maximum = 1000
        spacingSlider.setPageStep(50)
        spacingMmLabel = qt.QLabel()
        self.spacingSliderItems[self.OPERATION_MIP] = (spacingLabel,
                                                       spacingSlider,
                                                       spacingMmLabel)
        self.setCurrentSpacingInMm(self.OPERATION_MIP, 20)

        spacingLabel = qt.QLabel("Slice size " +
                                 self.operations[self.OPERATION_MinIP])
        spacingSlider = qt.QSlider()
        spacingSlider.orientation = 1
        spacingSlider.setTickPosition(2)
        spacingSlider.minimum = 0
        spacingSlider.maximum = 200
        spacingSlider.setPageStep(50)
        spacingMmLabel = qt.QLabel()
        self.spacingSliderItems[self.OPERATION_MinIP] = (spacingLabel,
                                                         spacingSlider,
                                                         spacingMmLabel)
        self.setCurrentSpacingInMm(self.OPERATION_MinIP, 5)

        spacingLabel = qt.QLabel("Slice size " +
                                 self.operations[self.OPERATION_MEAN])
        spacingSlider = qt.QSlider()
        spacingSlider.orientation = 1
        spacingSlider.setTickPosition(2)
        spacingSlider.minimum = 0
        spacingSlider.maximum = 200
        spacingSlider.setPageStep(50)
        spacingMmLabel = qt.QLabel()
        self.spacingSliderItems[self.OPERATION_MEAN] = (spacingLabel,
                                                        spacingSlider,
                                                        spacingMmLabel)
        self.setCurrentSpacingInMm(self.OPERATION_MEAN, 20)

        # Crosshair
        self.crosshairCheckbox = qt.QCheckBox()
        self.crosshairCheckbox.setText("Crosshair cursor")
        self.crosshairCheckbox.toolTip = "Activate/Desactivate the crosshair cursor for a better visualization"
        self.crosshairCheckbox.setStyleSheet("margin-top:10px")

        # Center button
        self.centerButton = qt.QPushButton()
        self.centerButton.setText("Center volumes")
        self.centerButton.setFixedSize(100, 40)
        self.centerButton.setStyleSheet("margin-top:10px")

        if self.fullModeOn:
            ###### FULL MODE
            # Context
            self.widgetMainLayout.addWidget(self.contextLabel, 0, 0)
            self.widgetMainLayout.addWidget(self.contextComboBox, 0, 1, 1, 3)
            # Operation
            self.widgetMainLayout.addWidget(self.operationLabel, 1, 0)
            self.widgetMainLayout.addWidget(self.operationComboBox, 1, 1, 1, 3)
            # Plane
            self.widgetMainLayout.addWidget(self.planeLabel, 2, 0)
            self.widgetMainLayout.addWidget(
                self.axialButton, 2, 1, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.coronalButton, 2, 3,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.axialButtonLabel, 3, 1,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.sagittalButtonLabel, 3, 2,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.coronalButtonLabel, 3, 3,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            # Layout
            self.widgetMainLayout.addWidget(self.layoutLabel, 4, 0)
            self.widgetMainLayout.addWidget(
                self.singleSlideViewButton, 4, 1,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.sideBySideViewButton, 4, 2,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.threeOverThreeViewButton, 4, 3,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.maxMinCompareViewButton, 4, 4,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.resetViewButton, 4, 5,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.singleSlideButtonLabel, 5, 1,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.sideBySideButtonLabel, 5, 2,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.threeOverThreeButtonLabel, 5, 3,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.maxMinCompareButtonLabel, 5, 4,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.resetLabel, 5, 5, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            # Number of slices
            row = 6
            for structure in self.spacingSliderItems.values():
                self.widgetMainLayout.addWidget(structure[0], row, 0, 1, 2)
                self.widgetMainLayout.addWidget(structure[1], row, 2, 1, 3)
                self.widgetMainLayout.addWidget(structure[2], row, 5)
                row += 1
            self.widgetMainLayout.addWidget(self.crosshairCheckbox, row, 0, 1,
                                            2)
            self.crosshairCheckbox.setChecked(True)
            self.widgetMainLayout.addWidget(self.centerButton, row, 2, 1, 2)

        else:
            ##### COLLAPSED MODE
            # Plane
            self.widgetMainLayout.addWidget(self.planeLabel, 0, 0)
            self.widgetMainLayout.addWidget(
                self.axialButton, 0, 1, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.sagittalButton, 0, 2,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.coronalButton, 0, 3,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.threeOverThreeViewButton, 0, 4,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.axialButtonLabel, 1, 1,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.sagittalButtonLabel, 1, 2,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.coronalButtonLabel, 1, 3,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            self.widgetMainLayout.addWidget(
                self.threeOverThreeButtonLabel, 1, 4,
                SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER)
            # Number of slices
            row = 2
            for structure in self.spacingSliderItems.values():
                self.widgetMainLayout.addWidget(structure[0], row, 0)
                self.widgetMainLayout.addWidget(structure[1], row, 1, 1, 3)
                self.widgetMainLayout.addWidget(structure[2], row, 4)
                row += 1
            self.widgetMainLayout.addWidget(self.crosshairCheckbox, row, 0)
            self.widgetMainLayout.addWidget(self.centerButton, row, 1, 1, 2)

        self.layout.addStretch(1)

        self.__refreshUI__()

        # Connections
        self.contextComboBox.connect("currentIndexChanged (int)",
                                     self.__onContextIndexChanged__)
        self.operationComboBox.connect("currentIndexChanged (int)",
                                       self.__onOperationIndexChanged__)
        self.planesButtonGroup.connect("buttonClicked(int)",
                                       self.__onPlaneButtonClicked__)
        self.singleSlideViewButton.connect("clicked()",
                                           self.__onSingleSlideButtonClicked__)
        self.sideBySideViewButton.connect("clicked()",
                                          self.__onSideBySideButtonClicked__)
        self.threeOverThreeViewButton.connect(
            "clicked()", self.__onThreeOverThreeViewButtonClicked__)
        self.maxMinCompareViewButton.connect(
            "clicked()", self.__onMaxMinCompareViewButtonClicked__)
        self.resetViewButton.connect("clicked()",
                                     self.__onResetViewButtonClicked__)
        for slicer in (item[1] for item in self.spacingSliderItems.values()):
            slicer.connect('valueChanged(int)',
                           self.__onNumberOfSlicesChanged__)
        self.crosshairCheckbox.connect("stateChanged(int)",
                                       self.__onCrosshairCheckChanged__)
        self.centerButton.connect("clicked()", self.__onCenterButtonClicked__)
Esempio n. 2
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 = self.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.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 markss. 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)
    def setup(self):
        # Instantiate and connect widgets ...

        # Collapsible button
        autoCTCollapsibleButton = ctk.ctkCollapsibleButton()
        autoCTCollapsibleButton.text = "Collapsible button for CT auto-segmentation"
        self.layout.addWidget(autoCTCollapsibleButton)

        # Layout within the sample collapsible button
        autoCTFormLayout = qt.QFormLayout(autoCTCollapsibleButton)

        #Load CT image button
        loadCTButton = qt.QPushButton("Load CT image and add ROI annotation")
        loadCTButton.toolTip = "Click to load CT image and then annotate tumor location"
        autoCTFormLayout.addWidget(loadCTButton)
        loadCTButton.connect('clicked(bool)', self.onloadCTButtonClicked)

        #Number of nodule to operate
        #        loadCTnodulelabel = qt.QInputDialog()
        #        loadCTnodulelabel.toolTip = "The tumor number to segment"
        #        loadCTnodulelabel.getInt(self, "Get integer","Percentage:")
        #        autoCTFormLayout.addWidget(loadCTnodulelabel)
        #        loadCTnodulelabel.connect('clicked(bool)', self.onloadCTnodulelabelButtonClicked)
        #

        ####Ajust sigma value for CT##########
        #########################################
        #        nodulelabel1 = qt.QLabel()
        #        nodulelabel1.setText("Enter the nodule number to process")
        #        autoCTFormLayout.addWidget(nodulelabel1)
        #        noduleSlider1 = qt.QInputDialog()
        #        noduleSlider1.toolTip = "Slide to change nodule number"
        #        autoCTFormLayout.addWidget(noduleSlider1)
        ##        noduleSlider1.setMinimum(0.0)
        ##        noduleSlider1.setMaximum(20)
        ##        noduleSlider1.setValue(1.0)
        ##        noduleSlider.setTickPosition(qt.QSlider.TicksBelow)
        ##        noduleSlider.setTickInterval(1)
        #        self.noduleSlider1 = noduleSlider1

        nodulelabel = qt.QLabel()
        nodulelabel.setText("Enter the nodule number to segment (1-10)")
        autoCTFormLayout.addWidget(nodulelabel)
        noduleSlider = qt.QSlider(qt.Qt.Horizontal)
        noduleSlider.toolTip = "Slide to change nodule number"
        noduleSlider.setMinimum(0.0)
        noduleSlider.setMaximum(20)
        noduleSlider.setValue(1.0)
        noduleSlider.setTickPosition(qt.QSlider.TicksBelow)
        noduleSlider.setTickInterval(1)
        self.noduleSlider = noduleSlider
        #label for ticks
        nodulevalues = qt.QGridLayout()
        r1 = qt.QLabel("0")
        r2 = qt.QLabel("2")
        r3 = qt.QLabel("4")
        r4 = qt.QLabel("6")
        r5 = qt.QLabel("8")
        nodulevalues.addWidget(noduleSlider, 0, 0, 1, 5)
        nodulevalues.addWidget(r1, 1, 0, 1, 1)
        nodulevalues.addWidget(r2, 1, 1, 1, 1)
        nodulevalues.addWidget(r3, 1, 2, 1, 1)
        nodulevalues.addWidget(r4, 1, 3, 1, 1)
        nodulevalues.addWidget(r5, 1, 4, 1, 1)
        #Apply the changes
        #        noduleApplyButton = qt.QPushButton("Apply")
        #        noduleApplyButton.toolTip = "Click to apply new sigma value"
        #        nodulevalues.addWidget(noduleApplyButton, 0,5,2,1)
        #        noduleApplyButton.connect('clicked(bool)', self.changesApplyButtonClicked)
        autoCTFormLayout.addRow(nodulevalues)
        # Add vertical spacer
        self.layout.addStretch(1)

        #########Button for CT segmentation and 3D generation##########
        ###########################################################
        CTSeg3D_tumorButton = qt.QPushButton("CTSeg3D_tumor")
        CTSeg3D_tumorButton.toolTip = "Click to generate auto segmentation and 3D view of tumor"
        autoCTFormLayout.addWidget(CTSeg3D_tumorButton)
        CTSeg3D_tumorButton.connect('clicked(bool)',
                                    self.onCTSeg3D_tumorButtonClicked)

        ####Ajust multipler value for CT (fine tuning)##########
        #########################################

        #        CTfinetuneButton = qt.QPushButton("Fine_tuning")
        #        CTfinetuneButton.toolTip = "Fine tuning segmentation for better ROI"
        #        autoCTFormLayout.addWidget(CTfinetuneButton)
        #        CTfinetuneButton.connect('clicked(bool)', self.onCTfinetuneButtonClicked)

        ############## Button segment out lung ############
        CTSeg3D_lungButton = qt.QPushButton("CTSeg3D_lung")
        CTSeg3D_lungButton.toolTip = "Click to generate auto segmentation and 3D view of lung"
        autoCTFormLayout.addWidget(CTSeg3D_lungButton)
        CTSeg3D_lungButton.connect('clicked(bool)',
                                   self.onCTSeg3D_lungButtonClicked)

        self.image_loaded = False
Esempio n. 4
0
    def create(self):

        super(BinaryWatershedEffectOptions, self).create()

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

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

        tip = "Sets the a minimum size for labels which will be split into multiple objects."
        self.splitSizeLabel = qt.QLabel("Split Size:", self.frame)
        self.splitSizeLabel.setToolTip(tip)
        self.splitSizeFrame.layout().addWidget(self.splitSizeLabel)
        self.widgets.append(self.splitSizeLabel)

        self.minimumSplitSize = 0
        self.maximumSplitSize = 100

        self.splitSizeSlider = qt.QSlider(qt.Qt.Horizontal, self.frame)
        self.splitSizeSlider.setValue(1)
        self.splitSizeFrame.layout().addWidget(self.splitSizeSlider)
        self.splitSizeFrame.setToolTip(tip)
        self.widgets.append(self.splitSizeSlider)

        self.splitSizeSpinBox = qt.QDoubleSpinBox(self.frame)
        self.splitSizeSpinBox.setToolTip(tip)
        self.splitSizeSpinBox.setValue(1)
        self.splitSizeSpinBox.suffix = "mm"

        self.splitSizeFrame.layout().addWidget(self.splitSizeSpinBox)
        self.widgets.append(self.splitSizeSpinBox)

        self.splitSizeSpinBox.minimum = self.minimumSplitSize
        self.splitSizeSlider.minimum = self.minimumSplitSize
        self.splitSizeSpinBox.maximum = self.maximumSplitSize
        self.splitSizeSlider.maximum = self.maximumSplitSize

        self.apply = qt.QPushButton("Apply", self.frame)
        self.apply.setToolTip("Apply the binary watershed operation")
        self.frame.layout().addWidget(self.apply)
        self.widgets.append(self.apply)

        helpDoc = """Split selected label into separate objects based at minimum size the objects."""
        HelpButton(self.frame, helpDoc)

        self.apply.connect('clicked()', self.onApply)

        self.splitSizeSlider.connect('valueChanged(int)',
                                     self.splitSizeSpinBox.setValue)
        self.splitSizeSpinBox.connect('valueChanged(double)',
                                      self.splitSizeSlider.setValue)

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

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