Пример #1
0
    def __init__(self, anglePlanes, id, pointlocatordictionary):
        qt.QFrame.__init__(self)
        self.id = id

        self.setLayout(qt.QFormLayout())
        self.pointLocatorDictionary = pointlocatordictionary

        landmarkLayout = qt.QHBoxLayout()

        planeLabel = qt.QLabel('Plane ' + str(id) + ":")
        landmarkLayout.addWidget(planeLabel)

        self.logic = AnglePlanesLogic(id)

        label1 = qt.QLabel(' L1:')
        self.landmark1ComboBox = qt.QComboBox()
        landmark1ComboBox = self.landmark1ComboBox
        landmark1ComboBox.addItem("Select")
        landmark1ComboBox.connect('currentIndexChanged(QString)',
                                  self.placePlaneClicked)

        landmarkLayout.addWidget(label1)
        landmarkLayout.addWidget(landmark1ComboBox)

        label2 = qt.QLabel(' L2:')
        self.landmark2ComboBox = qt.QComboBox()
        landmark2ComboBox = self.landmark2ComboBox
        landmark2ComboBox.addItem("Select")
        landmark2ComboBox.connect('currentIndexChanged(QString)',
                                  self.placePlaneClicked)

        landmarkLayout.addWidget(label2)
        landmarkLayout.addWidget(landmark2ComboBox)

        label3 = qt.QLabel(' L3:')
        self.landmark3ComboBox = qt.QComboBox()
        landmark3ComboBox = self.landmark3ComboBox
        landmark3ComboBox.addItem("Select")
        landmark3ComboBox.connect('currentIndexChanged(QString)',
                                  self.placePlaneClicked)

        landmarkLayout.addWidget(label3)
        landmarkLayout.addWidget(landmark3ComboBox)

        addFiducialLabel = qt.QLabel('Add')
        addFiducialButton = qt.QPushButton(
            qt.QIcon(":/Icons/MarkupsAddFiducial.png"), " ")
        addFiducialButton.setFixedSize(50, 25)
        addFiducialButton.connect('clicked()', self.addLandMarkClicked)
        addFiducialButton.setEnabled(True)
        landmarkLayout.addWidget(addFiducialLabel)
        landmarkLayout.addWidget(addFiducialButton)

        #fiducial list for the plane

        fidNode = self.logic.getFiducialList()
        for i in range(0, fidNode.GetNumberOfFiducials()):
            label = fidNode.GetNthFiducialLabel(i)
            landmark1ComboBox.addItem(label)
            landmark2ComboBox.addItem(label)
            landmark3ComboBox.addItem(label)

            anglePlanes.landmarkComboBox1MidPoint.addItem(label)
            anglePlanes.landmarkComboBox2MidPoint.addItem(label)
            anglePlanes.midPointFiducialDictionaryID[
                label] = fidNode.GetNthMarkupID(i)

        fidNode.AddObserver(fidNode.MarkupAddedEvent, self.onFiducialAdded)
        fidNode.AddObserver(fidNode.MarkupRemovedEvent, self.onFiducialRemoved)

        self.setPointModifiedEventId = fidNode.AddObserver(
            fidNode.PointModifiedEvent, self.onPointModifiedEvent)

        # This observers are in AnglePlaneWidgets, they listen to any fiducial being added
        #
        fidNode.AddObserver(fidNode.MarkupAddedEvent,
                            anglePlanes.onFiducialAddedMidPoint)
        fidNode.AddObserver(fidNode.MarkupRemovedEvent,
                            anglePlanes.onFiducialRemovedMidPoint)

        self.layout().addRow(landmarkLayout)

        self.slider = ctk.ctkSliderWidget()
        slider = self.slider
        slider.singleStep = 0.1
        slider.minimum = 0.1
        slider.maximum = 10
        slider.value = 1.0
        slider.toolTip = "Set the size of your plane."

        self.slideOpacity = ctk.ctkSliderWidget()
        slideOpacity = self.slideOpacity
        slideOpacity.singleStep = 0.1
        slideOpacity.minimum = 0.1
        slideOpacity.maximum = 1
        slideOpacity.value = 1.0
        slideOpacity.toolTip = "Set the opacity of your plane."

        slider.connect('valueChanged(double)', self.placePlaneClicked)
        slideOpacity.connect('valueChanged(double)', self.placePlaneClicked)

        landmarkSliderLayout = qt.QHBoxLayout()

        label = qt.QLabel(' Size:')
        label2 = qt.QLabel(' Opacity:')

        landmarkSliderLayout.addWidget(label)
        landmarkSliderLayout.addWidget(self.slider)
        landmarkSliderLayout.addWidget(label2)
        landmarkSliderLayout.addWidget(self.slideOpacity)

        self.surfaceDeplacementCheckBox = qt.QCheckBox("On Surface")
        self.surfaceDeplacementCheckBox.setChecked(True)
        self.surfaceDeplacementCheckBox.connect(
            'stateChanged(int)', self.onSurfaceDeplacementStateChanged)

        landmarkSliderLayout.addWidget(self.surfaceDeplacementCheckBox)

        self.layout().addRow(landmarkSliderLayout)
Пример #2
0
    def loadFromMRML(self, mrmlNode=None):
        '''
    '''
        if not self.__updating:

            self.__updating = 1

            self.resetPanel()

            if mrmlNode:
                # adjust the panel to the given mrmlNode
                vtkId = self.mrmlManager().MapMRMLNodeIDToVTKNodeID(
                    mrmlNode.GetID())

                # number of volumes
                numberOfVolumes = self.mrmlManager(
                ).GetTargetNumberOfSelectedVolumes()

                # re-enable the widgets
                self.resetPanel(True)

                self.__classLabel2.setText("Class: " + mrmlNode.GetName())

                self.setupManualSampleTable(mrmlNode)

                for c in range(numberOfVolumes):

                    value = self.mrmlManager(
                    ).GetTreeNodeDistributionMeanWithCorrection(vtkId, c)

                for r in range(numberOfVolumes):
                    for c in range(numberOfVolumes):
                        value = self.mrmlManager(
                        ).GetTreeNodeDistributionLogCovarianceWithCorrection(
                            vtkId, r, c)

                #
                # overview panel
                #

                # first, clear it all
                for i in self.__classWeights:
                    self.__overviewBoxLayout.removeWidget(i)
                    i.deleteLater()
                    i.setParent(None)
                    i = None

                self.__classWeights = []
                self.__classWeightLayouts = []
                self.__classWeightLabels = []
                self.__classWeightSpinBoxes = []
                self.__classWeightCheckBoxes = []

                # fill it again
                if vtkId != self.mrmlManager().GetTreeRootNodeID():
                    # other node than root selected
                    parent = self.mrmlManager().GetTreeNodeParentNodeID(vtkId)
                    numberOfChildren = self.mrmlManager(
                    ).GetTreeNodeNumberOfChildren(parent)
                    for i in range(numberOfChildren):
                        child = self.mrmlManager().GetTreeNodeChildNodeID(
                            parent, i)
                        name = self.mrmlManager().GetTreeNodeName(child)
                        probability = self.mrmlManager(
                        ).GetTreeNodeClassProbability(child)

                        label = qt.QLabel(name + ":")

                        spinBox = qt.QDoubleSpinBox()
                        spinBox.minimum = 0
                        spinBox.maximum = 1
                        spinBox.singleStep = 0.01
                        spinBox.value = probability

                        checkBox = qt.QCheckBox("  ")
                        checkBox.toolTip = 'Toggle for auto-update when changing other weights.'

                        self.__classWeightLabels.append(label)
                        self.__classWeightSpinBoxes.append(spinBox)
                        self.__classWeightCheckBoxes.append(checkBox)

                        self.__classWeightSpinBoxes[-1].connect(
                            'valueChanged(double)', self.updateClassWeights)
                        self.__classWeightCheckBoxes[-1].connect(
                            'stateChanged(int)', self.updateClassWeights)

                        weightRow = qt.QWidget()
                        weightRowLayout = qt.QHBoxLayout(weightRow)
                        weightRowLayout.addWidget(self.__classWeightLabels[-1])
                        weightRowLayout.addWidget(
                            self.__classWeightSpinBoxes[-1])
                        weightRowLayout.addWidget(
                            self.__classWeightCheckBoxes[-1])

                        self.__classWeights.append(weightRow)
                        self.__classWeightLayouts.append(weightRowLayout)

                        self.__overviewBoxLayout.addWidget(
                            self.__classWeights[-1], 0, 2)

            self.__updating = 0
Пример #3
0
    def createUserInterface(self):
        '''
    '''
        self.__layout = super(EMSegmentQuickStep3, self).createUserInterface()

        self.__top = qt.QWidget()
        self.__topLayout = qt.QHBoxLayout(self.__top)

        # the anatomical tree
        anatomicalTreeGroupBox = qt.QGroupBox()
        anatomicalTreeGroupBox.setTitle('Anatomical Tree')
        self.__topLayout.addWidget(anatomicalTreeGroupBox)

        anatomicalTreeGroupBoxLayout = qt.QFormLayout(anatomicalTreeGroupBox)

        self.__anatomicalTree = slicer.modulewidget.qSlicerEMSegmentAnatomicalTreeWidget(
        )
        self.__anatomicalTree.structureNameEditable = False
        self.__anatomicalTree.labelColumnVisible = False
        self.__anatomicalTree.probabilityMapColumnVisible = False
        self.__anatomicalTree.classWeightColumnVisible = False
        self.__anatomicalTree.updateClassWeightColumnVisible = False
        self.__anatomicalTree.atlasWeightColumnVisible = False
        self.__anatomicalTree.alphaColumnVisible = False
        self.__anatomicalTree.displayAlphaCheckBoxVisible = False
        self.__anatomicalTree.setMinimumHeight(200)
        self.__anatomicalTree.toolTip = 'Select a structure to configure the intensity distribution.'
        self.__anatomicalTree.setSizePolicy(qt.QSizePolicy.MinimumExpanding,
                                            qt.QSizePolicy.MinimumExpanding)
        self.__anatomicalTree.connect('currentTreeNodeChanged(vtkMRMLNode*)',
                                      self.onTreeSelectionChanged)
        anatomicalTreeGroupBoxLayout.addWidget(self.__anatomicalTree)

        #
        # overview of class weights panel
        #
        self.__overviewBox = qt.QGroupBox()
        self.__overviewBox.title = 'Guesses of Probability'
        self.__overviewBox.toolTip = 'These are your guesses of probability relations between structures. Which structure takes how much percentage of the volume?'
        self.__overviewBoxLayout = qt.QVBoxLayout(self.__overviewBox)
        self.__topLayout.addWidget(self.__overviewBox)

        self.__layout.addWidget(self.__top)

        self.__tabWidget = qt.QTabWidget()
        self.__layout.addWidget(self.__tabWidget)

        #
        # manualSamplingPage
        #
        manualSamplingPage = qt.QWidget()
        manualSamplingPageLayout = qt.QFormLayout(manualSamplingPage)

        self.__classLabel2 = qt.QLabel("Class: XX")
        manualSamplingPageLayout.addWidget(self.__classLabel2)

        self.__infoLabel = qt.QLabel(
            "left mouse Click in a slice window to pick a sample")
        manualSamplingPageLayout.addWidget(self.__infoLabel)

        self.__manualSampleTable = qt.QTableWidget()
        manualSamplingPageLayout.addWidget(self.__manualSampleTable)

        self.__tabWidget.addTab(manualSamplingPage, "Manual Sampling")

        self.__plotDistributionButton = qt.QPushButton()
        self.__plotDistributionButton.text = "Plot Distribution"
        self.__plotDistributionButton.toolTip = 'Click to plot the intensity distributions for all structures.'
        self.__layout.addRow(self.__plotDistributionButton)
        self.__plotDistributionButton.connect('clicked()',
                                              self.plotDistribution)
Пример #4
0
    def setup(self):
        self.developerMode = False
        ScriptedLoadableModuleWidget.setup(self)

        annotationsCollapsibleButton = ctk.ctkCollapsibleButton()
        annotationsCollapsibleButton.text = "Astro Annotations"
        self.layout.addWidget(annotationsCollapsibleButton)
        # Layout within the dummy collapsible button
        annotationsFormLayout = qt.QVBoxLayout(annotationsCollapsibleButton)

        # Color
        horizontalLayout_1 = qt.QHBoxLayout()
        horizontalLayout_1.setObjectName("horizontalLayout_1")

        self.colorLabel = qt.QLabel()
        self.colorLabel.setText("Annotations color:")
        self.colorLabel.setFixedSize(qt.QSize(120, 30))
        horizontalLayout_1.addWidget(self.colorLabel)

        self.colorSelector = ctk.ctkColorPickerButton()
        self.colorSelector.setObjectName("ColorPickerButton")
        sizePolicy = qt.QSizePolicy()
        sizePolicy.setHorizontalPolicy(qt.QSizePolicy.Expanding)
        sizePolicy.setVerticalPolicy(qt.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.colorSelector.sizePolicy.hasHeightForWidth())
        self.colorSelector.setSizePolicy(sizePolicy)
        self.colorSelector.setMinimumSize(qt.QSize(0, 30))
        self.colorSelector.setIconSize(qt.QSize(32, 32))
        self.colorSelector.setColor(qt.QColor(255, 187, 20))
        self.colorSelector.setDisplayColorName(0)
        horizontalLayout_1.addWidget(self.colorSelector)

        annotationsFormLayout.addLayout(horizontalLayout_1)

        # Font Style
        horizontalLayout_2 = qt.QHBoxLayout()
        horizontalLayout_2.setObjectName("horizontalLayout_2")

        self.fontStyleLabel = qt.QLabel()
        self.fontStyleLabel.setText("Font style:")
        self.fontStyleLabel.setFixedSize(qt.QSize(120, 30))
        horizontalLayout_2.addWidget(self.fontStyleLabel)

        self.styleComboBox = qt.QComboBox()
        self.styleComboBox.addItem("Arial")
        self.styleComboBox.addItem("Courier")
        self.styleComboBox.addItem("Times")
        sizePolicy.setHeightForWidth(
            self.styleComboBox.sizePolicy.hasHeightForWidth())
        self.styleComboBox.setMinimumSize(qt.QSize(0, 30))
        horizontalLayout_2.addWidget(self.styleComboBox)

        annotationsFormLayout.addLayout(horizontalLayout_2)

        # Font size
        horizontalLayout_3 = qt.QHBoxLayout()
        horizontalLayout_3.setObjectName("horizontalLayout_3")

        self.fontSizeLabel = qt.QLabel()
        self.fontSizeLabel.setText("Font size:")
        self.fontSizeLabel.setFixedSize(qt.QSize(120, 30))
        horizontalLayout_3.addWidget(self.fontSizeLabel)

        self.sizeSpinBox = qt.QSpinBox()
        sizePolicy.setHeightForWidth(
            self.sizeSpinBox.sizePolicy.hasHeightForWidth())
        self.sizeSpinBox.setMinimumSize(qt.QSize(0, 30))
        self.sizeSpinBox.minimum = 1
        self.sizeSpinBox.maximum = 30
        self.sizeSpinBox.setValue(12)
        self.sizeSpinBox.setToolTip(
            "This value is multiplied for 1.5 if the ruler is set to thick.")

        horizontalLayout_3.addWidget(self.sizeSpinBox)

        annotationsFormLayout.addLayout(horizontalLayout_3)

        verticalSpacer = qt.QSpacerItem(200, 200, qt.QSizePolicy.Minimum,
                                        qt.QSizePolicy.Expanding)
        self.layout.addItem(verticalSpacer)

        # Connections
        self.colorSelector.connect('colorChanged(QColor)',
                                   self.onAnnotationsColorChanged)

        self.styleComboBox.connect('currentTextChanged(QString)',
                                   self.onAnnotationsFontStyleChanged)

        self.sizeSpinBox.connect('valueChanged(int)',
                                 self.onAnnotationsFontSizeChanged)
Пример #5
0
    def create(self):
        super(PaintEffectOptions, self).create()

        labelVolume = self.editUtil.getLabelVolume()
        if labelVolume and labelVolume.GetImageData():
            spacing = labelVolume.GetSpacing()
            dimensions = labelVolume.GetImageData().GetDimensions()
            self.minimumRadius = 0.5 * min(spacing)
            bounds = [a * b for a, b in zip(spacing, dimensions)]
            self.maximumRadius = 0.5 * max(bounds)
        else:
            self.minimumRadius = 0.01
            self.maximumRadius = 100

        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 = qt.QDoubleSpinBox(self.radiusFrame)
        self.radiusSpinBox.setToolTip(
            "Set the radius of the paint brush in millimeters")
        self.radiusSpinBox.minimum = self.minimumRadius
        self.radiusSpinBox.maximum = self.maximumRadius
        self.radiusSpinBox.suffix = "mm"
        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.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.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.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.smudge = qt.QCheckBox("Smudge", self.frame)
        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)

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

        self.connections.append(
            (self.smudge, '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)

        # set the node parameters that are dependent on the input data
        self.parameterNode.SetParameter("PaintEffect,radius",
                                        str(self.minimumRadius * 10))
Пример #6
0
    def setup(self):
        # Instantiate and connect widgets ...

        #
        # Reload and Test area
        #
        reloadCollapsibleButton = ctk.ctkCollapsibleButton()
        reloadCollapsibleButton.text = "Reload && Test"
        self.layout.addWidget(reloadCollapsibleButton)
        reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton)

        # reload button
        # (use this during development, but remove it when delivering
        #  your module to users)
        self.reloadButton = qt.QPushButton("Reload")
        self.reloadButton.toolTip = "Reload this module."
        self.reloadButton.name = "QuantitativeIndicesTool Reload"
        reloadFormLayout.addWidget(self.reloadButton)
        self.reloadButton.connect('clicked()', self.onReload)

        # reload and test button
        # (use this during development, but remove it when delivering
        #  your module to users)
        self.reloadAndTestButton = qt.QPushButton("Reload and Test")
        self.reloadAndTestButton.toolTip = "Reload this module and then run the self tests."
        reloadFormLayout.addWidget(self.reloadAndTestButton)
        self.reloadAndTestButton.connect('clicked()', self.onReloadAndTest)
        self.reloadAndTestButton.setEnabled(False)

        #
        # Parameters Area
        #
        parametersCollapsibleButton = ctk.ctkCollapsibleButton()
        parametersCollapsibleButton.text = "Parameters"
        self.layout.addWidget(parametersCollapsibleButton)
        parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton)

        #
        # grayscale volume selector
        #
        self.grayscaleSelector = slicer.qMRMLNodeComboBox()
        self.grayscaleSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.grayscaleSelector.addAttribute("vtkMRMLScalarVolumeNode",
                                            "LabelMap", 0)
        self.grayscaleSelector.selectNodeUponCreation = True
        self.grayscaleSelector.addEnabled = False
        self.grayscaleSelector.removeEnabled = False
        self.grayscaleSelector.noneEnabled = True
        self.grayscaleSelector.showHidden = False
        self.grayscaleSelector.showChildNodeTypes = False
        self.grayscaleSelector.setMRMLScene(slicer.mrmlScene)
        self.grayscaleSelector.setToolTip("Input grayscale volume.")
        parametersFormLayout.addRow("Input Volume: ", self.grayscaleSelector)
        self.grayscaleNode = None

        #
        # label map volume selector
        #
        self.labelSelector = slicer.qMRMLNodeComboBox()
        self.labelSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.labelSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap",
                                        1)
        self.labelSelector.selectNodeUponCreation = True
        self.labelSelector.addEnabled = False
        self.labelSelector.removeEnabled = False
        self.labelSelector.noneEnabled = True
        self.labelSelector.showHidden = False
        self.labelSelector.showChildNodeTypes = False
        self.labelSelector.setMRMLScene(slicer.mrmlScene)
        self.labelSelector.setToolTip("Input label map volume.")
        parametersFormLayout.addRow("Label Map: ", self.labelSelector)
        self.labelNode = None

        #
        # CLI node name and set button
        #
        self.parameterFrame = qt.QFrame(self.parent)
        self.parameterFrame.setLayout(qt.QHBoxLayout())
        parametersFormLayout.addRow("Parameter Set: ", self.parameterFrame)

        self.parameterFrameLabel = qt.QLabel(" (none generated) ",
                                             self.parameterFrame)
        self.parameterFrameLabel.setToolTip(
            "Nodes for storing parameter flags and output.")
        self.parameterFrame.layout().addWidget(self.parameterFrameLabel)

        self.parameterName = qt.QLabel("", self.parameterFrame)
        self.parameterName.setToolTip(
            "Nodes for storing parameter flags and output.")
        self.parameterFrame.layout().addWidget(self.parameterName)

        self.parameterSetButton = qt.QPushButton("Generate",
                                                 self.parameterFrame)
        self.parameterSetButton.setToolTip(
            "Generate a set of parameter nodes to store with the scene")
        self.parameterSetButton.setEnabled(False)
        self.parameterFrame.layout().addWidget(self.parameterSetButton)
        self.cliNodes = None

        self.changeVolumesButton = qt.QPushButton("Change Volumes",
                                                  self.parameterFrame)
        self.changeVolumesButton.setToolTip(
            "Change the grayscale volume and/or the label map.  Previous calculations from the scene will be deleted."
        )
        self.changeVolumesButton.setEnabled(False)
        self.parameterFrame.layout().addWidget(self.changeVolumesButton)

        #
        # label map value spin box
        #
        self.labelValueSelector = qt.QSpinBox()
        self.labelValueSelector.setEnabled(False)
        self.labelValueSelector.setMinimum(0)
        self.labelValueSelector.setValue(1)
        self.labelValueSelector.setToolTip("Label value to calculate features")
        parametersFormLayout.addRow("Label Value: ", self.labelValueSelector)
        self.totalLabels = 0

        #
        # check box to trigger taking screen shots for later use in tutorials
        #
        self.enableScreenshotsFlagCheckBox = qt.QCheckBox()
        self.enableScreenshotsFlagCheckBox.checked = False
        self.enableScreenshotsFlagCheckBox.setToolTip(
            "If checked, take screen shots for tutorials. Use Save Data to write them to disk."
        )
        #parametersFormLayout.addRow("Enable Screenshots", self.enableScreenshotsFlagCheckBox)

        #
        # scale factor for screen shots
        #
        self.screenshotScaleFactorSliderWidget = ctk.ctkSliderWidget()
        self.screenshotScaleFactorSliderWidget.singleStep = 1.0
        self.screenshotScaleFactorSliderWidget.minimum = 1.0
        self.screenshotScaleFactorSliderWidget.maximum = 50.0
        self.screenshotScaleFactorSliderWidget.value = 1.0
        self.screenshotScaleFactorSliderWidget.setToolTip(
            "Set scale factor for the screen shots.")
        #parametersFormLayout.addRow("Screenshot scale factor", self.screenshotScaleFactorSliderWidget)

        #
        # Create large list of quantitative features
        #
        self.featuresCollapsibleButton = ctk.ctkCollapsibleButton()
        self.featuresCollapsibleButton.text = "Features to Calculate"
        self.layout.addWidget(self.featuresCollapsibleButton)
        self.featuresFormLayout = qt.QFormLayout(
            self.featuresCollapsibleButton)

        self.QIFrame1 = qt.QFrame(self.parent)
        self.QIFrame1.setLayout(qt.QHBoxLayout())
        self.QIFrame1.layout().setSpacing(0)
        self.QIFrame1.layout().setMargin(0)
        self.featuresFormLayout.addRow("", self.QIFrame1)

        self.MeanCheckBox = qt.QCheckBox("Mean", self.QIFrame1)
        self.QIFrame1.layout().addWidget(self.MeanCheckBox)
        self.MeanCheckBox.checked = False

        self.VarianceCheckBox = qt.QCheckBox("Variance", self.QIFrame1)
        self.QIFrame1.layout().addWidget(self.VarianceCheckBox)
        self.VarianceCheckBox.checked = False

        self.MinCheckBox = qt.QCheckBox("Minimum", self.QIFrame1)
        self.QIFrame1.layout().addWidget(self.MinCheckBox)
        self.MinCheckBox.checked = False

        self.MaxCheckBox = qt.QCheckBox("Maximum", self.QIFrame1)
        self.QIFrame1.layout().addWidget(self.MaxCheckBox)
        self.MaxCheckBox.checked = False

        self.QIFrame2 = qt.QFrame(self.parent)
        self.QIFrame2.setLayout(qt.QHBoxLayout())
        self.QIFrame2.layout().setSpacing(0)
        self.QIFrame2.layout().setMargin(0)
        self.featuresFormLayout.addRow("", self.QIFrame2)

        self.Quart1CheckBox = qt.QCheckBox("1st Quartile", self.QIFrame2)
        self.QIFrame2.layout().addWidget(self.Quart1CheckBox)
        self.Quart1CheckBox.checked = False

        self.MedianCheckBox = qt.QCheckBox("Median", self.QIFrame2)
        self.QIFrame2.layout().addWidget(self.MedianCheckBox)
        self.MedianCheckBox.checked = False

        self.Quart3CheckBox = qt.QCheckBox("3rd Quartile", self.QIFrame2)
        self.QIFrame2.layout().addWidget(self.Quart3CheckBox)
        self.Quart3CheckBox.checked = False

        self.UpperAdjacentCheckBox = qt.QCheckBox("Upper Adjacent",
                                                  self.QIFrame2)
        self.QIFrame2.layout().addWidget(self.UpperAdjacentCheckBox)
        self.UpperAdjacentCheckBox.checked = False

        self.QIFrame3 = qt.QFrame(self.parent)
        self.QIFrame3.setLayout(qt.QHBoxLayout())
        self.QIFrame3.layout().setSpacing(0)
        self.QIFrame3.layout().setMargin(0)
        self.featuresFormLayout.addRow("", self.QIFrame3)

        self.Q1CheckBox = qt.QCheckBox("Q1 Distribution", self.QIFrame3)
        self.QIFrame3.layout().addWidget(self.Q1CheckBox)
        self.Q1CheckBox.checked = False

        self.Q2CheckBox = qt.QCheckBox("Q2 Distribution", self.QIFrame3)
        self.QIFrame3.layout().addWidget(self.Q2CheckBox)
        self.Q2CheckBox.checked = False

        self.Q3CheckBox = qt.QCheckBox("Q3 Distribution", self.QIFrame3)
        self.QIFrame3.layout().addWidget(self.Q3CheckBox)
        self.Q3CheckBox.checked = False

        self.Q4CheckBox = qt.QCheckBox("Q4 Distribution", self.QIFrame3)
        self.QIFrame3.layout().addWidget(self.Q4CheckBox)
        self.Q4CheckBox.checked = False

        self.QIFrame4 = qt.QFrame(self.parent)
        self.QIFrame4.setLayout(qt.QHBoxLayout())
        self.QIFrame4.layout().setSpacing(0)
        self.QIFrame4.layout().setMargin(0)
        self.featuresFormLayout.addRow("", self.QIFrame4)

        self.Gly1CheckBox = qt.QCheckBox("Glycolysis Q1", self.QIFrame4)
        self.QIFrame4.layout().addWidget(self.Gly1CheckBox)
        self.Gly1CheckBox.checked = False

        self.Gly2CheckBox = qt.QCheckBox("Glycolysis Q2", self.QIFrame4)
        self.QIFrame4.layout().addWidget(self.Gly2CheckBox)
        self.Gly2CheckBox.checked = False

        self.Gly3CheckBox = qt.QCheckBox("Glycolysis Q3", self.QIFrame4)
        self.QIFrame4.layout().addWidget(self.Gly3CheckBox)
        self.Gly3CheckBox.checked = False

        self.Gly4CheckBox = qt.QCheckBox("Glycolysis Q4", self.QIFrame4)
        self.QIFrame4.layout().addWidget(self.Gly4CheckBox)
        self.Gly4CheckBox.checked = False

        self.QIFrame5 = qt.QFrame(self.parent)
        self.QIFrame5.setLayout(qt.QHBoxLayout())
        self.QIFrame5.layout().setSpacing(0)
        self.QIFrame5.layout().setMargin(0)
        self.featuresFormLayout.addRow("", self.QIFrame5)

        self.TLGCheckBox = qt.QCheckBox("TLG", self.QIFrame5)
        self.QIFrame5.layout().addWidget(self.TLGCheckBox)
        self.TLGCheckBox.checked = False

        self.SAMCheckBox = qt.QCheckBox("SAM", self.QIFrame5)
        self.QIFrame5.layout().addWidget(self.SAMCheckBox)
        self.SAMCheckBox.checked = False

        self.SAMBGCheckBox = qt.QCheckBox("SAM Background", self.QIFrame5)
        self.QIFrame5.layout().addWidget(self.SAMBGCheckBox)
        self.SAMBGCheckBox.checked = False

        self.RMSCheckBox = qt.QCheckBox("RMS", self.QIFrame5)
        self.QIFrame5.layout().addWidget(self.RMSCheckBox)
        self.RMSCheckBox.checked = False

        self.QIFrame6 = qt.QFrame(self.parent)
        self.QIFrame6.setLayout(qt.QHBoxLayout())
        self.QIFrame6.layout().setSpacing(0)
        self.QIFrame6.layout().setMargin(0)
        self.featuresFormLayout.addRow("", self.QIFrame6)

        self.PeakCheckBox = qt.QCheckBox("Peak", self.QIFrame6)
        self.QIFrame6.layout().addWidget(self.PeakCheckBox)
        self.PeakCheckBox.checked = False

        self.VolumeCheckBox = qt.QCheckBox("Volume", self.QIFrame6)
        self.QIFrame6.layout().addWidget(self.VolumeCheckBox)
        self.VolumeCheckBox.checked = False

        self.selectAllButton = qt.QPushButton("Select All")
        self.selectAllButton.toolTip = "Select all quantitative features."
        self.QIFrame6.layout().addWidget(self.selectAllButton)

        self.deselectAllButton = qt.QPushButton("Deselect All")
        self.deselectAllButton.toolTip = "Deselect all quantitative features."
        self.QIFrame6.layout().addWidget(self.deselectAllButton)

        #
        # Calculate Button
        #
        self.calculateButton = qt.QPushButton("Calculate")
        self.calculateButton.toolTip = "Calculate quantitative features."
        self.calculateButton.enabled = False
        self.featuresFormLayout.addRow(self.calculateButton)

        #
        # Results Frame
        #
        self.resultsCollapsibleButton = ctk.ctkCollapsibleButton()
        self.resultsCollapsibleButton.text = "Results"
        self.layout.addWidget(self.resultsCollapsibleButton)
        self.resultsFormLayout = qt.QFormLayout(self.resultsCollapsibleButton)

        self.resultsFrame = qt.QFrame(self.resultsCollapsibleButton)
        self.resultsFrame.setLayout(qt.QHBoxLayout())
        self.resultsFrame.layout().setSpacing(0)
        self.resultsFrame.layout().setMargin(0)
        self.resultsFormLayout.addWidget(self.resultsFrame)
        self.resultsFrameLabel = qt.QLabel('', self.resultsFrame)
        self.resultsFrame.layout().addWidget(self.resultsFrameLabel)

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

        # connections
        self.calculateButton.connect('clicked(bool)', self.onCalculateButton)
        self.grayscaleSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                       self.onGrayscaleSelect)
        self.labelSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                   self.onLabelSelect)
        self.parameterSetButton.connect('clicked(bool)',
                                        self.onParameterSetButton)
        self.changeVolumesButton.connect('clicked(bool)',
                                         self.onChangeVolumesButton)
        self.labelValueSelector.connect('valueChanged(int)',
                                        self.onLabelValueSelect)
        self.selectAllButton.connect('clicked(bool)', self.onSelectAllButton)
        self.deselectAllButton.connect('clicked(bool)',
                                       self.onDeselectAllButton)
Пример #7
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.itervalues():
            self.contextComboBox.addItem(context)

        ## Operation
        self.operationLabel = qt.QLabel("Optimization")
        self.operationComboBox = qt.QComboBox()
        for operation in self.operations.itervalues():
            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.itervalues():
                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.itervalues():
                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.itervalues()):
            slicer.connect('valueChanged(int)',
                           self.__onNumberOfSlicesChanged__)
        self.crosshairCheckbox.connect("stateChanged(int)",
                                       self.__onCrosshairCheckChanged__)
        self.centerButton.connect("clicked()", self.__onCenterButtonClicked__)
Пример #8
0
    def construct(self):
        """ Constructs the MetadataEditorSet widget.
        """

        #--------------------
        # Loop through all folders as per
        # Xnat.path.DEFAULT_LEVELS.  We create an AnimatedCollapsible
        # for every folder, one MetadataEditor_Custom and one
        # MetadataEditor_Default, along with the relevant buttons for
        # very folder in XNAT_LEVELS.
        #--------------------
        for xnatLevel in Xnat.path.DEFAULT_LEVELS:

            #
            # Set DEFAULT label per xnat level.
            #
            self.labels[xnatLevel] = []
            self.labels[xnatLevel].append(qt.QLabel('<b>DEFAULT<b>'))
            self.labels[xnatLevel][0].setFont(
                XnatSlicerGlobals.LABEL_FONT_BOLD)

            #
            # Set the collapsible's internal layout
            # (a qt.QGridLayout) per folder.
            #
            self.collapsibleLayouts[xnatLevel] = qt.QGridLayout()
            self.collapsibleLayouts[xnatLevel].\
                addWidget(self.labels[xnatLevel][0], 0, 0)

            #
            # Set the MetadataEditor_Default,
            # add to layout.
            #
            self.defaultMetadataEditors[xnatLevel] = \
            MetadataEditor_Default(xnatLevel)
            self.collapsibleLayouts[xnatLevel].\
                addWidget(self.defaultMetadataEditors[xnatLevel], 1, 0)

            #
            # Set the MetadataEditor_Custom,
            # add to layout.
            #
            self.customMetadataEditors[xnatLevel] = \
                MetadataEditor_Custom(xnatLevel)
            self.collapsibleLayouts[xnatLevel].\
                addWidget(self.customMetadataEditors[xnatLevel], 1, 1, 1, 2)

            #
            # Set DEFAULT label per xnat level.
            #
            self.labels[xnatLevel].append(qt.QLabel('<b>CUSTOM<b>'))
            self.labels[xnatLevel][1].setFont(
                XnatSlicerGlobals.LABEL_FONT_BOLD)
            self.collapsibleLayouts[xnatLevel].\
                addWidget(self.labels[xnatLevel][1], 0, 1)

            #
            # Add the 'editCustom' button.
            #
            # NOTE: The user can choose to hide/show these buttons,
            # based on what's needed.  For isntance, the Settings['METADATA']
            # class hides these buttons as they are not necessary for
            # its workflow.
            #
            self.editCustomButtons[xnatLevel] = \
                XnatSlicerUtils.generateButton(iconOrLabel = \
                    "Edit custom tags for '%s'"%(xnatLevel),
                toolTip = "Adds a custom metadata tag to display in the" +
                                               " 'Info' column.",
                font = XnatSlicerGlobals.LABEL_FONT,
                size = qt.QSize(180, 20),
                enabled = True)

            self.collapsibleLayouts[xnatLevel].\
                addWidget(self.editCustomButtons[xnatLevel], 0, 2)
            self.editCustomButtonGroup.\
                addButton(self.editCustomButtons[xnatLevel])

            #
            # Put all of the widgets into first, a contentsWidget.
            # Then set the widget of the AnimatedCollapsible to the
            # contentsWidget.
            #
            self.collapsibles[xnatLevel] = AnimatedCollapsible(self, \
                                                        xnatLevel.title())
            self.collapsibles[xnatLevel].setMaxExpandedHeight(250)
            self.collapsibles[xnatLevel].setMinExpandedHeight(250)

            contentsWidget = qt.QWidget()
            contentsWidget.setLayout(self.collapsibleLayouts[xnatLevel])
            self.collapsibles[xnatLevel].setContents(contentsWidget)
            self.collapsibles[xnatLevel].setFixedWidth(550)

            #
            # Add collapsible to self.mainLayout.
            #
            self.mainLayout.addWidget(self.collapsibles[xnatLevel])
            self.mainLayout.addSpacing(10)

        #--------------------
        # Set callback to Update XNATSlicer's
        # layout when animating.
        #--------------------
        for key, collapsible in self.collapsibles.iteritems():
            collapsible.onEvent('animate', self.updateLayout)

        #--------------------
        # Set mainLayout to the master layout.
        #--------------------
        self.mainLayout.addStretch()
        self.setLayout(self.mainLayout)

        #--------------------
        # Set the current item tyype to label.
        # The user can change it to 'checkbox'
        # later.
        #--------------------
        self.setItemType('label')
Пример #9
0
    def setup(self):
        print("=======================================================")
        print("   VisSim Cervical Spine Tools               ")
        print("=======================================================")

        ScriptedLoadableModuleWidget.setup(self)

        # to access logic class functions and setup global variables
        self.logic = CervicalSpineToolsLogic()
        self.vsc = VisSimCommon.VisSimCommonLogic()
        #------------------------------------------------------------
        #                     Create the GUI interface
        #------------------------------------------------------------
        # Create main collapsible Button
        self.mainCollapsibleBtn = ctk.ctkCollapsibleButton()
        self.mainCollapsibleBtn.setStyleSheet(
            "ctkCollapsibleButton { background-color: DarkSeaGreen  }")
        self.mainCollapsibleBtn.text = "VisSim Cervical Spine Tools"
        self.layout.addWidget(self.mainCollapsibleBtn)
        self.mainFormLayout = qt.QFormLayout(self.mainCollapsibleBtn)

        # Create input Volume Selector
        self.inputSelectorCoBx = slicer.qMRMLNodeComboBox()
        self.inputSelectorCoBx.nodeTypes = ["vtkMRMLScalarVolumeNode"]
        self.inputSelectorCoBx.setFixedWidth(200)
        self.inputSelectorCoBx.selectNodeUponCreation = True
        self.inputSelectorCoBx.addEnabled = False
        self.inputSelectorCoBx.removeEnabled = False
        self.inputSelectorCoBx.noneEnabled = False
        self.inputSelectorCoBx.showHidden = False
        self.inputSelectorCoBx.showChildNodeTypes = False
        self.inputSelectorCoBx.setMRMLScene(slicer.mrmlScene)
        self.inputSelectorCoBx.setToolTip("select the input image")
        self.mainFormLayout.addRow("Input image: ", self.inputSelectorCoBx)

        # use qtcombobox
        self.vILbl = qt.QLabel()
        self.vILbl.setText("Which Vertebra? 1-7")
        self.vILbl.setFixedHeight(20)
        self.vILbl.setFixedWidth(150)

        #TODO: include head and shoulders
        self.vtIDCoBx = qt.QComboBox()
        self.vtIDCoBx.addItems(["C1", "C2", "C3", "C4", "C5", "C6", "C7"])
        self.vtIDCoBx.setCurrentIndex(2)
        self.vtIDCoBx.setFixedHeight(20)
        self.vtIDCoBx.setFixedWidth(100)
        #self.vtIDCoBx.setReadOnly(False) # The point can only be edited by placing a new Fiducial
        # if changed , the default value will change
        self.vtIDCoBx.connect("currentIndexChanged(int)",
                              self.onVtIDCoBxChange)
        #self.mainFormLayout.addRow( self.vILbl,  self.vtIDCoBx )

        # Create a textbox for vertebra location
        # TODO activate input IJK values as well
        self.inputPointEdt = qt.QLineEdit()
        self.inputPointEdt.setFixedHeight(20)
        self.inputPointEdt.setFixedWidth(100)
        self.inputPointEdt.setText("[0,0,0]")
        self.inputPointEdt.connect("textChanged(QString)",
                                   self.onInputPointEdtChanged)
        #self.inputPointEdt.connect("textEdited(str)", self.onInputPointEdtEdited)

        self.mainFormLayout.addRow(self.inputPointEdt, self.vtIDCoBx)

        # Add check box for extracting ligaments points
        self.ligPtsChkBx = qt.QCheckBox("Ligaments points")
        self.ligPtsChkBx.checked = True
        self.ligPtsChkBx.stateChanged.connect(self.onLigPtsChkBxChange)
        self.mainFormLayout.addRow(self.ligPtsChkBx)

        # Create a time label
        self.timeLbl = qt.QLabel("  Time: 00:00")
        self.timeLbl.setFixedWidth(500)
        self.tmLbl = self.timeLbl

        # Create a button to run segmentation
        self.applyBtn = qt.QPushButton("Run")
        self.applyBtn.setFixedHeight(50)
        self.applyBtn.setFixedWidth(150)
        self.applyBtn.setStyleSheet(
            "QPushButton{ background-color: DarkSeaGreen  }")
        self.applyBtn.toolTip = (
            'How to use:'
            ' Load an images into Slicer. Pick vertebra locations using the buttons and the Slicer Fiducial tool '
        )
        self.applyBtn.connect('clicked(bool)', self.onApplyBtnClick)
        self.mainFormLayout.addRow(self.applyBtn, self.timeLbl)
        self.runBtn = self.applyBtn

        # Create a button to display result folder
        self.openResultFolderBtn = qt.QPushButton("open output folder")
        self.openResultFolderBtn.setFixedHeight(20)
        self.openResultFolderBtn.setFixedWidth(150)
        self.openResultFolderBtn.setStyleSheet(
            "QPushButton{ background-color: DarkSeaGreen  }")
        self.openResultFolderBtn.toolTip = (
            'Scale model and points to 1 mm and translate them to the model center of mass '
        )
        self.openResultFolderBtn.connect('clicked(bool)',
                                         self.onOpenResultFolderBtnClick)

        self.mainFormLayout.addRow(self.openResultFolderBtn)

        self.layout.addStretch(
            1
        )  # Collapsible button is held in place when collapsing/expanding.
        lm = slicer.app.layoutManager()
        lm.setLayout(2)
Пример #10
0
  def setupAdvancedPanel(self):
    logging.debug('setupAdvancedPanel')

    self.advancedCollapsibleButton.setProperty('collapsedHeight', 20)
    self.advancedCollapsibleButton.text = "Settings"
    self.sliceletPanelLayout.addWidget(self.advancedCollapsibleButton)

    self.advancedLayout = qt.QFormLayout(self.advancedCollapsibleButton)
    self.advancedLayout.setContentsMargins(12, 4, 4, 4)
    self.advancedLayout.setSpacing(4)

    # Layout selection combo box
    self.viewSelectorComboBox = qt.QComboBox(self.advancedCollapsibleButton)
    self.advancedLayout.addRow("Layout: ", self.viewSelectorComboBox)

    self.registerDefaultGuideletLayouts()

    self.selectView(self.VIEW_ULTRASOUND_3D)

    # OpenIGTLink connector node selection
    self.linkInputSelector = slicer.qMRMLNodeComboBox()
    self.linkInputSelector.nodeTypes = ("vtkMRMLIGTLConnectorNode", "")
    self.linkInputSelector.selectNodeUponCreation = True
    self.linkInputSelector.addEnabled = False
    self.linkInputSelector.removeEnabled = True
    self.linkInputSelector.noneEnabled = False
    self.linkInputSelector.showHidden = False
    self.linkInputSelector.showChildNodeTypes = False
    self.linkInputSelector.setMRMLScene( slicer.mrmlScene )
    self.linkInputSelector.setToolTip( "Select connector node" )
    self.advancedLayout.addRow("OpenIGTLink connector: ", self.linkInputSelector)

    self.showFullSlicerInterfaceButton = qt.QPushButton()
    self.showFullSlicerInterfaceButton.setText("Show 3D Slicer user interface")
    self.advancedLayout.addRow(self.showFullSlicerInterfaceButton)

    self.showGuideletFullscreenButton = qt.QPushButton()
    self.showGuideletFullscreenButton.setText("Show Guidelet in full screen")
    self.advancedLayout.addRow(self.showGuideletFullscreenButton)

    self.saveSceneButton = qt.QPushButton()
    self.saveSceneButton.setText("Save Guidelet scene")
    self.advancedLayout.addRow(self.saveSceneButton)

    self.saveDirectoryLineEdit = ctk.ctkPathLineEdit()
    node = self.logic.getParameterNode()
    sceneSaveDirectory = node.GetParameter('SavedScenesDirectory')
    self.saveDirectoryLineEdit.currentPath = sceneSaveDirectory
    self.saveDirectoryLineEdit.filters = ctk.ctkPathLineEdit.Dirs
    self.saveDirectoryLineEdit.options = ctk.ctkPathLineEdit.DontUseSheet
    self.saveDirectoryLineEdit.options = ctk.ctkPathLineEdit.ShowDirsOnly
    self.saveDirectoryLineEdit.showHistoryButton = False
    self.saveDirectoryLineEdit.setMinimumWidth(100)
    self.saveDirectoryLineEdit.setMaximumWidth(500)

    saveLabel = qt.QLabel()
    saveLabel.setText("Save scene directory:")
    hbox = qt.QHBoxLayout()
    hbox.addWidget(saveLabel)
    hbox.addWidget(self.saveDirectoryLineEdit)
    self.advancedLayout.addRow(hbox)

    self.exitButton = qt.QPushButton()
    self.exitButton.setText("Exit")
    self.advancedLayout.addRow(self.exitButton)
Пример #11
0
    def setup(self):

        # check if the SlicerVmtk4 module is installed properly
        #self.__vmtkInstalled = SlicerVmtk4CommonLib.Helper.CheckIfVmtkIsInstalled()
        #Helper.Debug("VMTK found: " + self.__vmtkInstalled)

        #
        # the I/O panel
        #

        ioCollapsibleButton = ctk.ctkCollapsibleButton()
        ioCollapsibleButton.text = "Input/Output"
        self.layout.addWidget(ioCollapsibleButton)

        ioFormLayout = qt.QFormLayout(ioCollapsibleButton)

        # inputVolume selector
        self.__inputVolumeNodeSelector = slicer.qMRMLNodeComboBox()
        self.__inputVolumeNodeSelector.objectName = 'inputVolumeNodeSelector'
        self.__inputVolumeNodeSelector.toolTip = "Select the input volume. This should always be the original image and not a vesselness image, if possible."
        self.__inputVolumeNodeSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
        self.__inputVolumeNodeSelector.noneEnabled = False
        self.__inputVolumeNodeSelector.addEnabled = False
        self.__inputVolumeNodeSelector.removeEnabled = False
        self.__inputVolumeNodeSelector.addAttribute("vtkMRMLScalarVolumeNode",
                                                    "LabelMap", "0")
        ioFormLayout.addRow("Input Volume:", self.__inputVolumeNodeSelector)
        self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)',
                            self.__inputVolumeNodeSelector,
                            'setMRMLScene(vtkMRMLScene*)')
        self.__inputVolumeNodeSelector.connect(
            'currentNodeChanged(vtkMRMLNode*)', self.onInputVolumeChanged)
        self.__inputVolumeNodeSelector.connect('nodeActivated(vtkMRMLNode*)',
                                               self.onInputVolumeChanged)

        # seed selector
        self.__seedFiducialsNodeSelector = slicer.qMRMLNodeComboBox()
        self.__seedFiducialsNodeSelector.objectName = 'seedFiducialsNodeSelector'
        self.__seedFiducialsNodeSelector.toolTip = "Select a hierarchy containing the fiducials to use as Seeds."
        self.__seedFiducialsNodeSelector.nodeTypes = [
            'vtkMRMLAnnotationHierarchyNode'
        ]
        self.__seedFiducialsNodeSelector.baseName = "Seeds"
        self.__seedFiducialsNodeSelector.noneEnabled = False
        self.__seedFiducialsNodeSelector.addEnabled = False
        self.__seedFiducialsNodeSelector.removeEnabled = False
        ioFormLayout.addRow("Seeds:", self.__seedFiducialsNodeSelector)
        self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)',
                            self.__seedFiducialsNodeSelector,
                            'setMRMLScene(vtkMRMLScene*)')

        self.__ioAdvancedToggle = qt.QCheckBox("Show Advanced I/O Properties")
        self.__ioAdvancedToggle.setChecked(False)
        ioFormLayout.addRow(self.__ioAdvancedToggle)

        #
        # I/O advanced panel
        #

        self.__ioAdvancedPanel = qt.QFrame(ioCollapsibleButton)
        self.__ioAdvancedPanel.hide()
        self.__ioAdvancedPanel.setFrameStyle(6)
        ioFormLayout.addRow(self.__ioAdvancedPanel)
        self.__ioAdvancedToggle.connect("clicked()", self.onIOAdvancedToggle)

        ioAdvancedFormLayout = qt.QFormLayout(self.__ioAdvancedPanel)

        # inputVolume selector
        self.__vesselnessVolumeNodeSelector = slicer.qMRMLNodeComboBox()
        self.__vesselnessVolumeNodeSelector.objectName = 'vesselnessVolumeNodeSelector'
        self.__vesselnessVolumeNodeSelector.toolTip = "Select the input vesselness volume. This is optional input."
        self.__vesselnessVolumeNodeSelector.nodeTypes = [
            'vtkMRMLScalarVolumeNode'
        ]
        self.__vesselnessVolumeNodeSelector.noneEnabled = True
        self.__vesselnessVolumeNodeSelector.addEnabled = False
        self.__vesselnessVolumeNodeSelector.removeEnabled = False
        self.__vesselnessVolumeNodeSelector.addAttribute(
            "vtkMRMLScalarVolumeNode", "LabelMap", "0")
        ioAdvancedFormLayout.addRow("Vesselness Volume:",
                                    self.__vesselnessVolumeNodeSelector)
        self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)',
                            self.__vesselnessVolumeNodeSelector,
                            'setMRMLScene(vtkMRMLScene*)')
        self.__vesselnessVolumeNodeSelector.setCurrentNode(None)

        # stopper selector
        self.__stopperFiducialsNodeSelector = slicer.qMRMLNodeComboBox()
        self.__stopperFiducialsNodeSelector.objectName = 'stopperFiducialsNodeSelector'
        self.__stopperFiducialsNodeSelector.toolTip = "Select a hierarchy containing the fiducials to use as Stoppers. Whenever one stopper is reached, the segmentation stops."
        self.__stopperFiducialsNodeSelector.nodeTypes = [
            'vtkMRMLAnnotationHierarchyNode'
        ]
        self.__stopperFiducialsNodeSelector.baseName = "Stoppers"
        self.__stopperFiducialsNodeSelector.noneEnabled = False
        self.__stopperFiducialsNodeSelector.addEnabled = True
        self.__stopperFiducialsNodeSelector.removeEnabled = False
        ioAdvancedFormLayout.addRow("Stoppers:",
                                    self.__stopperFiducialsNodeSelector)
        self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)',
                            self.__stopperFiducialsNodeSelector,
                            'setMRMLScene(vtkMRMLScene*)')

        # outputVolume selector
        self.__outputVolumeNodeSelector = slicer.qMRMLNodeComboBox()
        self.__outputVolumeNodeSelector.toolTip = "Select the output labelmap."
        self.__outputVolumeNodeSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
        self.__outputVolumeNodeSelector.baseName = "LevelSetSegmentation"
        self.__outputVolumeNodeSelector.noneEnabled = False
        self.__outputVolumeNodeSelector.addEnabled = True
        self.__outputVolumeNodeSelector.selectNodeUponCreation = True
        self.__outputVolumeNodeSelector.addAttribute("vtkMRMLScalarVolumeNode",
                                                     "LabelMap", "1")
        self.__outputVolumeNodeSelector.removeEnabled = True
        ioAdvancedFormLayout.addRow("Output Labelmap:",
                                    self.__outputVolumeNodeSelector)
        self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)',
                            self.__outputVolumeNodeSelector,
                            'setMRMLScene(vtkMRMLScene*)')

        # outputModel selector
        self.__outputModelNodeSelector = slicer.qMRMLNodeComboBox()
        self.__outputModelNodeSelector.objectName = 'outputModelNodeSelector'
        self.__outputModelNodeSelector.toolTip = "Select the output model."
        self.__outputModelNodeSelector.nodeTypes = ['vtkMRMLModelNode']
        self.__outputModelNodeSelector.baseName = "LevelSetSegmentationModel"
        self.__outputModelNodeSelector.hideChildNodeTypes = [
            'vtkMRMLAnnotationNode'
        ]  # hide all annotation nodes
        self.__outputModelNodeSelector.noneEnabled = False
        self.__outputModelNodeSelector.addEnabled = True
        self.__outputModelNodeSelector.selectNodeUponCreation = True
        self.__outputModelNodeSelector.removeEnabled = True
        ioAdvancedFormLayout.addRow("Output Model:",
                                    self.__outputModelNodeSelector)
        self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)',
                            self.__outputModelNodeSelector,
                            'setMRMLScene(vtkMRMLScene*)')

        #
        # the segmentation panel
        #

        segmentationCollapsibleButton = ctk.ctkCollapsibleButton()
        segmentationCollapsibleButton.text = "Segmentation"
        self.layout.addWidget(segmentationCollapsibleButton)

        segmentationFormLayout = qt.QFormLayout(segmentationCollapsibleButton)

        # Threshold slider
        thresholdLabel = qt.QLabel()
        thresholdLabel.text = "Thresholding" + SlicerVmtk4CommonLib.Helper.CreateSpace(
            7)
        thresholdLabel.toolTip = "Choose the intensity range to segment."
        thresholdLabel.setAlignment(4)
        segmentationFormLayout.addRow(thresholdLabel)

        self.__thresholdSlider = slicer.qMRMLRangeWidget()
        segmentationFormLayout.addRow(self.__thresholdSlider)
        self.__thresholdSlider.connect('valuesChanged(double,double)',
                                       self.onThresholdSliderChanged)

        self.__segmentationAdvancedToggle = qt.QCheckBox(
            "Show Advanced Segmentation Properties")
        self.__segmentationAdvancedToggle.setChecked(False)
        segmentationFormLayout.addRow(self.__segmentationAdvancedToggle)

        #
        # segmentation advanced panel
        #

        self.__segmentationAdvancedPanel = qt.QFrame(
            segmentationCollapsibleButton)
        self.__segmentationAdvancedPanel.hide()
        self.__segmentationAdvancedPanel.setFrameStyle(6)
        segmentationFormLayout.addRow(self.__segmentationAdvancedPanel)
        self.__segmentationAdvancedToggle.connect(
            "clicked()", self.onSegmentationAdvancedToggle)

        segmentationAdvancedFormLayout = qt.QFormLayout(
            self.__segmentationAdvancedPanel)

        # inflation slider
        inflationLabel = qt.QLabel()
        inflationLabel.text = "less inflation <-> more inflation" + SlicerVmtk4CommonLib.Helper.CreateSpace(
            14)
        inflationLabel.setAlignment(4)
        inflationLabel.toolTip = "Define how fast the segmentation expands."
        segmentationAdvancedFormLayout.addRow(inflationLabel)

        self.__inflationSlider = ctk.ctkSliderWidget()
        self.__inflationSlider.decimals = 0
        self.__inflationSlider.minimum = -100
        self.__inflationSlider.maximum = 100
        self.__inflationSlider.singleStep = 10
        self.__inflationSlider.toolTip = inflationLabel.toolTip
        segmentationAdvancedFormLayout.addRow(self.__inflationSlider)

        # curvature slider
        curvatureLabel = qt.QLabel()
        curvatureLabel.text = "less curvature <-> more curvature" + SlicerVmtk4CommonLib.Helper.CreateSpace(
            14)
        curvatureLabel.setAlignment(4)
        curvatureLabel.toolTip = "Choose a high curvature to generate a smooth segmentation."
        segmentationAdvancedFormLayout.addRow(curvatureLabel)

        self.__curvatureSlider = ctk.ctkSliderWidget()
        self.__curvatureSlider.decimals = 0
        self.__curvatureSlider.minimum = -100
        self.__curvatureSlider.maximum = 100
        self.__curvatureSlider.singleStep = 10
        self.__curvatureSlider.toolTip = curvatureLabel.toolTip
        segmentationAdvancedFormLayout.addRow(self.__curvatureSlider)

        # attraction slider
        attractionLabel = qt.QLabel()
        attractionLabel.text = "less attraction to gradient <-> more attraction to gradient" + SlicerVmtk4CommonLib.Helper.CreateSpace(
            14)
        attractionLabel.setAlignment(4)
        attractionLabel.toolTip = "Configure how the segmentation travels towards gradient ridges (vessel lumen wall)."
        segmentationAdvancedFormLayout.addRow(attractionLabel)

        self.__attractionSlider = ctk.ctkSliderWidget()
        self.__attractionSlider.decimals = 0
        self.__attractionSlider.minimum = -100
        self.__attractionSlider.maximum = 100
        self.__attractionSlider.singleStep = 10
        self.__attractionSlider.toolTip = attractionLabel.toolTip
        segmentationAdvancedFormLayout.addRow(self.__attractionSlider)

        # iteration spinbox
        self.__iterationSpinBox = qt.QSpinBox()
        self.__iterationSpinBox.minimum = 0
        self.__iterationSpinBox.maximum = 5000
        self.__iterationSpinBox.singleStep = 10
        self.__iterationSpinBox.toolTip = "Choose the number of evolution iterations."
        segmentationAdvancedFormLayout.addRow(
            SlicerVmtk4CommonLib.Helper.CreateSpace(100) + "Iterations:",
            self.__iterationSpinBox)

        #
        # Reset, preview and apply buttons
        #

        self.__buttonBox = qt.QDialogButtonBox()
        self.__resetButton = self.__buttonBox.addButton(
            self.__buttonBox.RestoreDefaults)
        self.__resetButton.toolTip = "Click to reset all input elements to default."
        self.__previewButton = self.__buttonBox.addButton(
            self.__buttonBox.Discard)
        self.__previewButton.setIcon(qt.QIcon())
        self.__previewButton.text = "Preview.."
        self.__previewButton.toolTip = "Click to refresh the preview."
        self.__startButton = self.__buttonBox.addButton(self.__buttonBox.Apply)
        self.__startButton.setIcon(qt.QIcon())
        self.__startButton.text = "Start!"
        self.__startButton.enabled = False
        self.__startButton.toolTip = "Click to start the filtering."
        self.layout.addWidget(self.__buttonBox)
        self.__resetButton.connect("clicked()", self.restoreDefaults)
        self.__previewButton.connect("clicked()", self.onRefreshButtonClicked)
        self.__startButton.connect("clicked()", self.onStartButtonClicked)

        # be ready for events
        self.__updating = 0

        # set default values
        self.restoreDefaults()

        # compress the layout
        self.layout.addStretch(1)
Пример #12
0
    def setup(self):
        # Instantiate and connect widgets ...

        # reload button
        # (use this during development, but remove it when delivering
        #  your module to users)

        # Collapsible button
        dummyCollapsibleButton = ctk.ctkCollapsibleButton()
        dummyCollapsibleButton.text = "Parameters"
        self.layout.addWidget(dummyCollapsibleButton)

        # Layout within the dummy collapsible button
        dummyFormLayout = qt.QFormLayout(dummyCollapsibleButton)

        #LABEL VOLUME SELECTOR

        self.labelSelectorFrame = qt.QFrame()
        self.labelSelectorFrame.setLayout(qt.QHBoxLayout())
        dummyFormLayout.addWidget(self.labelSelectorFrame)

        self.labelSelectorLabel = qt.QLabel()
        self.labelSelectorLabel.setText("Label Map: ")
        dummyFormLayout.addWidget(self.labelSelectorLabel)

        self.labelSelector = slicer.qMRMLNodeComboBox()
        self.labelSelector.nodeTypes = ("vtkMRMLScalarVolumeNode", "")
        self.labelSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap",
                                        "1")
        # todo addAttribute
        self.labelSelector.selectNodeUponCreation = False
        self.labelSelector.addEnabled = False
        self.labelSelector.noneEnabled = True
        self.labelSelector.removeEnabled = False
        self.labelSelector.showHidden = False
        self.labelSelector.showChildNodeTypes = False
        self.labelSelector.setMRMLScene(slicer.mrmlScene)
        self.labelSelector.setToolTip("Pick the label map to edit")
        dummyFormLayout.addWidget(self.labelSelector)
        self.labelSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                   self.onLabelSelect)

        # the grayscale volume selector
        #
        self.grayscaleSelectorFrame = qt.QFrame(self.parent)
        self.grayscaleSelectorFrame.setLayout(qt.QHBoxLayout())
        dummyFormLayout.addWidget(self.grayscaleSelectorFrame)

        self.grayscaleSelectorLabel = qt.QLabel("Grayscale Volume: ",
                                                self.grayscaleSelectorFrame)
        self.grayscaleSelectorLabel.setToolTip(
            "Select the grayscale volume (background grayscale scalar volume node) for statistics calculations"
        )
        dummyFormLayout.addWidget(self.grayscaleSelectorLabel)

        self.grayscaleSelector = slicer.qMRMLNodeComboBox(
            self.grayscaleSelectorFrame)
        self.grayscaleSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.grayscaleSelector.addAttribute("vtkMRMLScalarVolumeNode",
                                            "LabelMap", 0)
        self.grayscaleSelector.selectNodeUponCreation = False
        self.grayscaleSelector.addEnabled = False
        self.grayscaleSelector.removeEnabled = False
        self.grayscaleSelector.noneEnabled = True
        self.grayscaleSelector.showHidden = False
        self.grayscaleSelector.showChildNodeTypes = False
        self.grayscaleSelector.setMRMLScene(slicer.mrmlScene)
        # TODO: need to add a QLabel
        # self.grayscaleSelector.SetLabelText( "Master Volume:" )
        dummyFormLayout.addWidget(self.grayscaleSelector)
        self.grayscaleSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                       self.onGrayscaleSelect)

        self.reloadButton = qt.QPushButton("Reload")
        self.reloadButton.toolTip = "Reload this module."
        self.reloadButton.name = "diagnosis Reload"
        self.layout.addWidget(self.reloadButton)
        self.reloadButton.connect('clicked()', self.onReload)

        # Calculate button
        self.calcButton = qt.QPushButton("Calculates")
        self.calcButton.toolTip = "Calculates the level of stenosis on the most patological slice"
        dummyFormLayout.addWidget(self.calcButton)
        self.calcButton.enabled = False
        self.calcButton.connect('clicked(bool)', self.onCalcButtonClicked)

        # Botton temporal para llenar tabla ***************************************
        self.fillTable = qt.QPushButton("Fill")
        self.fillTable.toolTip = "Testing"
        dummyFormLayout.addWidget(self.fillTable)
        self.fillTable.enabled = True
        self.fillTable.connect('clicked(bool)', self.onFillButtonClicked)

        # Add Vertical Spacer
        self.layout.addStretch(1)

        # Parametros tabla
        self.vista = qt.QTableView()
        self.vista.sortingEnabled = False
        self.vista.visible = False
        self.vista.verticalHeader().visible = False
        self.vista.horizontalHeader().visible = False
        self.vista.setAlternatingRowColors(True)
        dummyFormLayout.addWidget(self.vista)

        # Add vertical spacer
        self.layout.addStretch(1)
Пример #13
0
  def setup(self):
    # Instantiate and connect widgets ...

    #
    # Reload and Test area
    #
    reloadCollapsibleButton = ctk.ctkCollapsibleButton()
    reloadCollapsibleButton.text = "Reload && Test"
    self.layout.addWidget(reloadCollapsibleButton)
    reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton)

    # reload button
    # (use this during development, but remove it when delivering
    #  your module to users)
    self.reloadButton = qt.QPushButton("Reload")
    self.reloadButton.toolTip = "Reload this module."
    self.reloadButton.name = "MarginCalculator Reload"
    reloadFormLayout.addWidget(self.reloadButton)
    self.reloadButton.connect('clicked()', self.onReload)

    # reload and test button
    # (use this during development, but remove it when delivering
    #  your module to users)
    self.reloadAndTestButton = qt.QPushButton("Reload and Test")
    self.reloadAndTestButton.toolTip = "Reload this module and then run the self tests."
    reloadFormLayout.addWidget(self.reloadAndTestButton)
    self.reloadAndTestButton.connect('clicked()', self.onReloadAndTest)

    # Collapsible button
    self.marginCalculationCollapsibleButton = ctk.ctkCollapsibleButton()
    self.marginCalculationCollapsibleButton.text = "Margin Calculation"
    self.layout.addWidget(self.marginCalculationCollapsibleButton)

    # Layout within the collapsible button
    self.marginCalculationFormLayout = qt.QFormLayout(self.marginCalculationCollapsibleButton)

    # Input Dose Volume selector
    self.inputDoseVolumeSelectorLabel = qt.QLabel('Input Dose Volume:')
    self.inputDoseVolumeSelector = slicer.qMRMLNodeComboBox()
    self.inputDoseVolumeSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
    self.inputDoseVolumeSelector.noneEnabled = False
    self.inputDoseVolumeSelector.addEnabled = False
    self.inputDoseVolumeSelector.removeEnabled = False
    self.inputDoseVolumeSelector.setMRMLScene( slicer.mrmlScene )
    self.inputDoseVolumeSelector.setToolTip( "Set the input Dose volume" )
    self.marginCalculationFormLayout.addRow(self.inputDoseVolumeSelectorLabel, self.inputDoseVolumeSelector)

    # Reference Dose Volume selector
    self.referenceDoseVolumeSelectorLabel = qt.QLabel()
    self.referenceDoseVolumeSelectorLabel.setText( "Reference Dose Volume: " )
    self.referenceDoseVolumeSelector = slicer.qMRMLNodeComboBox()
    self.referenceDoseVolumeSelector.nodeTypes = ( "vtkMRMLScalarVolumeNode", "" )
    self.referenceDoseVolumeSelector.noneEnabled = False
    self.referenceDoseVolumeSelector.addEnabled = False
    self.referenceDoseVolumeSelector.removeEnabled = False
    self.referenceDoseVolumeSelector.setMRMLScene( slicer.mrmlScene )
    self.referenceDoseVolumeSelector.setToolTip( "Set the Reference dose volume" )
    self.marginCalculationFormLayout.addRow(self.referenceDoseVolumeSelectorLabel, self.referenceDoseVolumeSelector)

    # Input Contour selector
    self.inputContourSelectorLabel = qt.QLabel('Input Contour Labelmap:')
    self.inputContourSelector = slicer.qMRMLNodeComboBox()
    self.inputContourSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
    self.inputContourSelector.addAttribute( "vtkMRMLScalarVolumeNode", "LabelMap", 1 )
    self.inputContourSelector.noneEnabled = False
    self.inputContourSelector.addEnabled = False
    self.inputContourSelector.removeEnabled = False
    self.inputContourSelector.setMRMLScene( slicer.mrmlScene )
    self.inputContourSelector.setToolTip( "Set the input Contour" )
    self.marginCalculationFormLayout.addRow(self.inputContourSelectorLabel, self.inputContourSelector)

    # Number of simulations
    self.numberOfSimulationsSlider = ctk.ctkSliderWidget()
    self.numberOfSimulationsSlider.decimals = 0
    self.numberOfSimulationsSlider.minimum = 0
    self.numberOfSimulationsSlider.maximum = 2000
    self.numberOfSimulationsSlider.singleStep = 1
    self.numberOfSimulationsSlider.pageStep = 100
    self.numberOfSimulationsSlider.value = 100
    self.marginCalculationFormLayout.addRow("Number of Simulations: ", self.numberOfSimulationsSlider)

    # Number of fractions
    self.numberOfFractionsSlider = ctk.ctkSliderWidget()
    self.numberOfFractionsSlider.decimals = 0
    self.numberOfFractionsSlider.minimum = 0
    self.numberOfFractionsSlider.maximum = 10
    self.numberOfFractionsSlider.singleStep = 1
    self.numberOfFractionsSlider.pageStep = 5
    self.numberOfFractionsSlider.value = 1
    self.marginCalculationFormLayout.addRow("Number of Fractions: ", self.numberOfFractionsSlider)

    # Systematic error slider
    self.systematicErrorRangeSlider = ctk.ctkSliderWidget()
    self.systematicErrorRangeSlider.decimals = 1
    self.systematicErrorRangeSlider.minimum = 0
    self.systematicErrorRangeSlider.maximum = 5
    self.systematicErrorRangeSlider.singleStep = 0.1
    self.systematicErrorRangeSlider.pageStep = 1.0
    self.systematicErrorRangeSlider.value = 0.5
    self.marginCalculationFormLayout.addRow("Systematic Error Range (mm): ", self.systematicErrorRangeSlider)

    # Random error slider
    self.randomErrorRangeSlider = ctk.ctkSliderWidget()
    self.randomErrorRangeSlider.decimals = 1
    self.randomErrorRangeSlider.minimum = 0
    self.randomErrorRangeSlider.maximum = 5
    self.randomErrorRangeSlider.singleStep = 0.1
    self.randomErrorRangeSlider.pageStep = 1.0
    self.randomErrorRangeSlider.value = 0.5
    self.marginCalculationFormLayout.addRow("Random Error Range (mm): ", self.randomErrorRangeSlider)

    self.doseGrowingOptions = ("Dilation","Scaling")
    #
    #Initialization
    #
    self.groupBoxDoseGrow = qt.QGroupBox("Dose Growing Technique")
    self.groupBoxLayout = qt.QHBoxLayout(self.groupBoxDoseGrow)
    self.marginCalculationFormLayout.addRow(self.groupBoxDoseGrow)

    #
    # layout selection
    #
    for doseGrowingOption in self.doseGrowingOptions:
      doseGrowingOptionButton = qt.QRadioButton(doseGrowingOption)
      doseGrowingOptionButton.connect('clicked()', lambda dgo=doseGrowingOption: self.selectDoseGrowingOption(dgo))
      self.groupBoxLayout.addWidget(doseGrowingOptionButton)
      if doseGrowingOption == "Dilation":
        doseGrowingOptionButton.checked = True
      self.doseGrowingOption = "Dilation"
    #self.groupBoxLayout.addRow("Layout", layoutHolder)

    # Dose growing range slider
    self.doseGrowRangeSlider = ctk.ctkSliderWidget()
    self.doseGrowRangeSlider.decimals = 1
    self.doseGrowRangeSlider.minimum = 0
    self.doseGrowRangeSlider.maximum = 10
    self.doseGrowRangeSlider.singleStep = 0.2
    self.doseGrowRangeSlider.pageStep = 1.0
    self.doseGrowRangeSlider.value = 5
    self.marginCalculationFormLayout.addRow("Dose grow Range (mm): ", self.doseGrowRangeSlider)

    # ROI radius x slider
    self.ROIRadiusXSlider = ctk.ctkSliderWidget()
    self.ROIRadiusXSlider.decimals = 1
    self.ROIRadiusXSlider.minimum = 2
    self.ROIRadiusXSlider.maximum = 30
    self.ROIRadiusXSlider.singleStep = 0.1
    self.ROIRadiusXSlider.pageStep = 2.0
    self.ROIRadiusXSlider.value = 10
    self.marginCalculationFormLayout.addRow("ROI Radius X(mm): ", self.ROIRadiusXSlider)

    # ROI radius y slider
    self.ROIRadiusYSlider = ctk.ctkSliderWidget()
    self.ROIRadiusYSlider.decimals = 1
    self.ROIRadiusYSlider.minimum = 2
    self.ROIRadiusYSlider.maximum = 30
    self.ROIRadiusYSlider.singleStep = 0.1
    self.ROIRadiusYSlider.pageStep = 2.0
    self.ROIRadiusYSlider.value = 10
    self.marginCalculationFormLayout.addRow("ROI Radius Y(mm): ", self.ROIRadiusYSlider)

    # ROI radius z slider
    self.ROIRadiusZSlider = ctk.ctkSliderWidget()
    self.ROIRadiusZSlider.decimals = 1
    self.ROIRadiusZSlider.minimum = 2
    self.ROIRadiusZSlider.maximum = 30
    self.ROIRadiusZSlider.singleStep = 0.1
    self.ROIRadiusZSlider.pageStep = 2.0
    self.ROIRadiusZSlider.value = 10
    self.marginCalculationFormLayout.addRow("ROI Radius Z(mm): ", self.ROIRadiusZSlider)

    # Apply button
    self.applyButton = qt.QPushButton("Calculate")
    self.applyButton.toolTip = "Perform margin calculation"
    self.marginCalculationFormLayout.addRow(self.applyButton)
    self.UpdateApplyButtonState()

    # model and view for stats table
    self.tableWidget.sortingEnabled = False
    self.tableWidget.setRowCount(0)
    self.tableWidget.setColumnCount(5)
    self.tableWidget.setHorizontalHeaderLabels(['Systematic','Random','P90','P95','P99'])
    self.marginCalculationFormLayout.addRow(self.tableWidget)

    # Save button
    self.saveButton = qt.QPushButton("Save Result")
    self.saveButton.toolTip = "Save result as csv."
    self.saveButton.enabled = False
    self.marginCalculationFormLayout.addRow(self.saveButton)
    
    # Add vertical spacer
    self.layout.addStretch(1)

    # connections
    self.applyButton.connect('clicked()', self.onApply)
    self.saveButton.connect('clicked()', self.onSave)
    self.inputDoseVolumeSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onInputDoseVolumeSelect)
    self.referenceDoseVolumeSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onReferenceDoseVolumeSelect)
    self.inputContourSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onInputContourSelect)
    self.numberOfSimulationsSlider.connect('valueChanged(double)', self.onNumberOfSimulationsChanged)
    self.numberOfFractionsSlider.connect('valueChanged(double)', self.onNumberOfFractionsChanged)
    self.systematicErrorRangeSlider.connect('valueChanged(double)', self.onSystematicErrorRangeChanged)
    self.randomErrorRangeSlider.connect('valueChanged(double)', self.onRandomErrorRangeChanged)
    self.doseGrowRangeSlider.connect('valueChanged(double)', self.onDoseGrowRangeChanged)
    self.ROIRadiusXSlider.connect('valueChanged(double)', self.onROIRadiusXChanged)
    self.ROIRadiusYSlider.connect('valueChanged(double)', self.onROIRadiusYChanged)
    self.ROIRadiusZSlider.connect('valueChanged(double)', self.onROIRadiusZChanged)
    def setup(self):
        print(" ")
        print("=======================================================")
        print("   Automatic Cochlea Image Registration                ")
        print("=======================================================")

        ScriptedLoadableModuleWidget.setup(self)

        # to access logic class functions and setup global variables
        self.logic = CochleaRegLogic()

        # Set default VisSIm location in the user home
        #TODO: add option user-defined path when installed first time
        self.vsc = VisSimCommon.VisSimCommonLogic()
        self.vsc.setGlobalVariables(0)

        #-----------------------------------------------------------------
        #                     Create the GUI interface
        #-----------------------------------------------------------------
        # Create collapsible Button for registration, transformix and invert transform
        self.mainCollapsibleBtn = ctk.ctkCollapsibleButton()
        self.mainCollapsibleBtn.setStyleSheet(
            "ctkCollapsibleButton { background-color: DarkSeaGreen  }")
        self.mainCollapsibleBtn.text = "ACIR: Automatic Cochlea Image Registration"
        self.layout.addWidget(self.mainCollapsibleBtn)
        self.mainFormLayout = qt.QFormLayout(self.mainCollapsibleBtn)

        # Create fixed Volume Selector
        self.fixedSelectorCoBx = slicer.qMRMLNodeComboBox()
        self.fixedSelectorCoBx.nodeTypes = ["vtkMRMLScalarVolumeNode"]
        self.fixedSelectorCoBx.selectNodeUponCreation = True
        self.fixedSelectorCoBx.addEnabled = False
        self.fixedSelectorCoBx.removeEnabled = False
        self.fixedSelectorCoBx.noneEnabled = False
        self.fixedSelectorCoBx.showHidden = False
        self.fixedSelectorCoBx.showChildNodeTypes = False
        self.fixedSelectorCoBx.setMRMLScene(slicer.mrmlScene)
        self.fixedSelectorCoBx.setToolTip("Pick the fixed volume")
        self.mainFormLayout.addRow("Fixed Volume: ", self.fixedSelectorCoBx)

        # Create moving Volume Selector
        self.movingSelectorCoBx = slicer.qMRMLNodeComboBox()
        self.movingSelectorCoBx.nodeTypes = ["vtkMRMLScalarVolumeNode"]
        self.movingSelectorCoBx.selectNodeUponCreation = True
        self.movingSelectorCoBx.addEnabled = False
        self.movingSelectorCoBx.removeEnabled = False
        self.movingSelectorCoBx.noneEnabled = False
        self.movingSelectorCoBx.showHidden = False
        self.movingSelectorCoBx.showChildNodeTypes = False
        self.movingSelectorCoBx.setMRMLScene(slicer.mrmlScene)
        self.movingSelectorCoBx.setToolTip("Pick the moving volume")
        self.mainFormLayout.addRow("Moving Volume: ", self.movingSelectorCoBx)

        # Create a time label
        self.timeLbl = qt.QLabel("                 Time: 00:00")
        self.timeLbl.setFixedWidth(500)
        self.tmLbl = self.timeLbl

        # Create a textbox for cochlea location
        # TODO activate input IJK values as well
        self.fixedPointEdt = qt.QLineEdit()
        self.fixedPointEdt.setFixedHeight(40)
        self.fixedPointEdt.setText("[0,0,0]")

        # Create a textbox for cochlea location
        # TODO activate input IJK values as well
        self.movingPointEdt = qt.QLineEdit()
        self.movingPointEdt.setFixedHeight(40)
        self.movingPointEdt.setText("[0,0,0]")

        # Create a cochlea locator button
        self.fixedFiducialBtn = qt.QPushButton(
            "Pick cochlea location in fixed image    ")
        self.fixedFiducialBtn.setFixedHeight(40)
        self.fixedFiducialBtn.setToolTip(
            "Pick the fixed fiducial point that will be the center of the cropped image"
        )
        self.fixedFiducialBtn.connect(
            'clicked(bool)', lambda: self.onInputFiducialBtnClick("F"))
        self.mainFormLayout.addRow(self.fixedFiducialBtn, self.fixedPointEdt)

        # Create a cochlea locator button
        self.movingFiducialBtn = qt.QPushButton(
            "Pick cochlea location in moving image    ")
        self.movingFiducialBtn.setFixedHeight(40)
        self.movingFiducialBtn.setToolTip(
            "Pick the moving fiducial point that will be the center of the cropped image"
        )
        self.movingFiducialBtn.connect(
            'clicked(bool)', lambda: self.onInputFiducialBtnClick("M"))
        self.mainFormLayout.addRow(self.movingFiducialBtn, self.movingPointEdt)

        # Add check box for disabling colors in the result of the registration
        self.colorsChkBox = qt.QCheckBox()
        self.colorsChkBox.text = "Disable colors"
        self.colorsChkBox.checked = False
        self.colorsChkBox.stateChanged.connect(self.OnColorsChkBoxChange)
        self.mainFormLayout.addRow(self.colorsChkBox)

        # Create a button to run registration
        self.applyBtn = qt.QPushButton("Run")
        self.applyBtn.setFixedHeight(50)
        self.applyBtn.setFixedWidth(250)
        self.applyBtn.setStyleSheet(
            "QPushButton{ background-color: DarkSeaGreen  }")
        self.applyBtn.toolTip = (
            'How to use:'
            ' Load at least two images into Slicer. Pick cochlea locations using the buttons and the Slicer Fiducial tool '
        )
        self.applyBtn.connect('clicked(bool)', self.onApplyBtnClick)
        self.mainFormLayout.addRow(self.applyBtn, self.timeLbl)
        self.runBtn = self.applyBtn

        self.layout.addStretch(
            1
        )  # Collapsible button is held in place when collapsing/expanding.