Example #1
0
  def create(self):
    """create the segmentation helper box"""

    #
    # Master Frame
    #
    self.masterFrame = qt.QFrame(self.parent)
    self.masterFrame.setLayout(qt.QVBoxLayout())
    self.parent.layout().addWidget(self.masterFrame)

    #
    # the master volume selector
    #
    self.masterSelectorFrame = qt.QFrame(self.parent)
    self.masterSelectorFrame.objectName = 'MasterVolumeFrame'
    self.masterSelectorFrame.setLayout(qt.QHBoxLayout())
    self.masterFrame.layout().addWidget(self.masterSelectorFrame)

    self.masterSelectorLabel = qt.QLabel("Master Volume: ", self.masterSelectorFrame)
    self.masterSelectorLabel.setToolTip( "Select the master volume (background grayscale scalar volume node)")
    self.masterSelectorFrame.layout().addWidget(self.masterSelectorLabel)

    self.masterSelector = slicer.qMRMLNodeComboBox(self.masterSelectorFrame)
    self.masterSelector.objectName = 'MasterVolumeNodeSelector'
    # TODO
    self.masterSelector.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
    self.masterSelector.selectNodeUponCreation = False
    self.masterSelector.addEnabled = False
    self.masterSelector.removeEnabled = False
    self.masterSelector.noneEnabled = True
    self.masterSelector.showHidden = False
    self.masterSelector.showChildNodeTypes = False
    self.masterSelector.setMRMLScene( slicer.mrmlScene )
    # TODO: need to add a QLabel
    # self.masterSelector.SetLabelText( "Master Volume:" )
    self.masterSelector.setToolTip( "Pick the master structural volume to define the segmentation.  A label volume with the with \"%s\" appended to the name will be created if it doesn't already exist." % self.mergeVolumePostfix)
    self.masterSelectorFrame.layout().addWidget(self.masterSelector)


    #
    # merge label name and set button
    #
    self.mergeSelectorFrame = qt.QFrame(self.masterFrame)
    self.mergeSelectorFrame.objectName = 'MergeVolumeFrame'
    self.mergeSelectorFrame.setLayout(qt.QHBoxLayout())
    self.masterFrame.layout().addWidget(self.mergeSelectorFrame)

    mergeNameToolTip = "Composite label map containing the merged structures (be aware that merge operations will overwrite any edits applied to this volume)"
    self.mergeNameLabel = qt.QLabel("Merge Volume: ", self.mergeSelectorFrame)
    self.mergeNameLabel.setToolTip( mergeNameToolTip )
    self.mergeSelectorFrame.layout().addWidget(self.mergeNameLabel)

    self.mergeSelector = slicer.qMRMLNodeComboBox(self.mergeSelectorFrame)
    self.mergeSelector.objectName = 'MergeVolumeNodeSelector'
    self.mergeSelector.setToolTip( mergeNameToolTip )
    self.mergeSelector.nodeTypes = ( ("vtkMRMLLabelMapVolumeNode"), "" )
    self.mergeSelector.addEnabled = False
    self.mergeSelector.removeEnabled = False
    self.mergeSelector.noneEnabled = False
    self.mergeSelector.showHidden = False
    self.mergeSelector.showChildNodeTypes = False
    self.mergeSelector.setMRMLScene( slicer.mrmlScene )
    self.mergeSelectorFrame.layout().addWidget(self.mergeSelector)

    self.newMergeVolumeAction = qt.QAction("Create new LabelMapVolume", self.mergeSelector)
    self.newMergeVolumeAction.connect("triggered()", self.newMerge)
    self.mergeSelector.addMenuAction(self.newMergeVolumeAction)

    #
    # Structures Frame
    #
    self.structuresFrame = ctk.ctkCollapsibleGroupBox(self.masterFrame)
    self.structuresFrame.objectName = 'PerStructureVolumesFrame'
    self.structuresFrame.title = "Per-Structure Volumes"
    self.structuresFrame.collapsed = True
    self.structuresFrame.setLayout(qt.QVBoxLayout())
    self.masterFrame.layout().addWidget(self.structuresFrame)

    self.structureListWidget = LabelStructureListWidget()
    self.structureListWidget.mergeVolumePostfix = self.mergeVolumePostfix
    self.structuresFrame.layout().addWidget(self.structureListWidget)

    #
    # signals, slots, and observers
    #

    # signals/slots on qt widgets are automatically when
    # this class destructs, but observers of the scene must be explicitly
    # removed in the destuctor

    # node selected
    self.masterSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.mergeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onMergeSelect)

    # so buttons will initially be disabled
    self.master = None
    self.structureListWidget.updateStructures()
Example #2
0
    def setupNavigationPanel(self):
        logging.debug("setupNavigationPanel")

        self.sliderTranslationDefaultMm = 0
        self.sliderTranslationMinMm = -500
        self.sliderTranslationMaxMm = 500
        self.sliderViewAngleDefaultDeg = 30
        self.cameraViewAngleMinDeg = 5.0  # maximum magnification
        self.cameraViewAngleMaxDeg = 150.0  # minimum magnification

        self.sliderSingleStepValue = 1
        self.sliderPageStepValue = 10

        self.navigationCollapsibleButton.setProperty("collapsedHeight", 20)
        setButtonStyle(self.navigationCollapsibleButton, 2.0)
        self.navigationCollapsibleButton.text = "Navigation"
        self.sliceletPanelLayout.addWidget(self.navigationCollapsibleButton)

        self.navigationCollapsibleLayout = qt.QFormLayout(self.navigationCollapsibleButton)
        self.navigationCollapsibleLayout.setContentsMargins(12, 4, 4, 4)
        self.navigationCollapsibleLayout.setSpacing(4)

        self.rightCameraButton = qt.QPushButton("Setup right camera")
        self.rightCameraButton.setCheckable(True)
        setButtonStyle(self.rightCameraButton)

        self.leftCameraButton = qt.QPushButton("Setup left camera")
        self.leftCameraButton.setCheckable(True)
        setButtonStyle(self.leftCameraButton)

        hbox = qt.QHBoxLayout()
        hbox.addWidget(self.leftCameraButton)
        hbox.addWidget(self.rightCameraButton)
        self.navigationCollapsibleLayout.addRow(hbox)

        # "Camera Control" Collapsible
        self.zoomCollapsibleButton = ctk.ctkCollapsibleGroupBox()
        self.zoomCollapsibleButton.collapsed = True
        self.zoomCollapsibleButton.title = "Zoom"
        self.navigationCollapsibleLayout.addRow(self.zoomCollapsibleButton)

        # Layout within the collapsible button
        self.zoomFormLayout = qt.QFormLayout(self.zoomCollapsibleButton)

        # Camera distance to focal point slider
        self.cameraViewAngleLabel = qt.QLabel(qt.Qt.Horizontal, None)
        self.cameraViewAngleLabel.setText("Field of view [degrees]: ")
        self.cameraViewAngleSlider = slicer.qMRMLSliderWidget()
        self.cameraViewAngleSlider.minimum = self.cameraViewAngleMinDeg
        self.cameraViewAngleSlider.maximum = self.cameraViewAngleMaxDeg
        self.cameraViewAngleSlider.value = self.sliderViewAngleDefaultDeg
        self.cameraViewAngleSlider.singleStep = self.sliderSingleStepValue
        self.cameraViewAngleSlider.pageStep = self.sliderPageStepValue
        self.cameraViewAngleSlider.setDisabled(True)
        self.zoomFormLayout.addRow(self.cameraViewAngleLabel, self.cameraViewAngleSlider)

        # "Camera Control" Collapsible
        self.translationCollapsibleButton = ctk.ctkCollapsibleGroupBox()
        self.translationCollapsibleButton.title = "Translation"
        self.translationCollapsibleButton.collapsed = True
        self.navigationCollapsibleLayout.addRow(self.translationCollapsibleButton)

        # Layout within the collapsible button
        self.translationFormLayout = qt.QFormLayout(self.translationCollapsibleButton)

        self.cameraXPosLabel = qt.QLabel(qt.Qt.Horizontal, None)
        self.cameraXPosLabel.text = "Left/Right [mm]: "
        self.cameraXPosSlider = slicer.qMRMLSliderWidget()
        setButtonStyle(self.cameraXPosSlider)
        self.cameraXPosSlider.minimum = self.sliderTranslationMinMm
        self.cameraXPosSlider.maximum = self.sliderTranslationMaxMm
        self.cameraXPosSlider.value = self.sliderTranslationDefaultMm
        self.cameraXPosSlider.singleStep = self.sliderSingleStepValue
        self.cameraXPosSlider.pageStep = self.sliderPageStepValue
        self.cameraXPosSlider.setDisabled(True)
        self.translationFormLayout.addRow(self.cameraXPosLabel, self.cameraXPosSlider)

        self.cameraYPosLabel = qt.QLabel(qt.Qt.Horizontal, None)
        self.cameraYPosLabel.setText("Down/Up [mm]: ")
        self.cameraYPosSlider = slicer.qMRMLSliderWidget()
        setButtonStyle(self.cameraYPosSlider)
        self.cameraYPosSlider.minimum = self.sliderTranslationMinMm
        self.cameraYPosSlider.maximum = self.sliderTranslationMaxMm
        self.cameraYPosSlider.value = self.sliderTranslationDefaultMm
        self.cameraYPosSlider.singleStep = self.sliderSingleStepValue
        self.cameraYPosSlider.pageStep = self.sliderPageStepValue
        self.cameraYPosSlider.setDisabled(True)
        self.translationFormLayout.addRow(self.cameraYPosLabel, self.cameraYPosSlider)

        self.cameraZPosLabel = qt.QLabel(qt.Qt.Horizontal, None)
        self.cameraZPosLabel.setText("Front/Back [mm]: ")
        self.cameraZPosSlider = slicer.qMRMLSliderWidget()
        setButtonStyle(self.cameraZPosSlider)
        self.cameraZPosSlider.minimum = self.sliderTranslationMinMm
        self.cameraZPosSlider.maximum = self.sliderTranslationMaxMm
        self.cameraZPosSlider.value = self.sliderTranslationDefaultMm
        self.cameraZPosSlider.singleStep = self.sliderSingleStepValue
        self.cameraZPosSlider.pageStep = self.sliderPageStepValue
        self.cameraZPosSlider.setDisabled(True)
        self.translationFormLayout.addRow(self.cameraZPosLabel, self.cameraZPosSlider)

        # "Contour adjustment" Collapsible
        self.contourAdjustmentCollapsibleButton = ctk.ctkCollapsibleGroupBox()
        self.contourAdjustmentCollapsibleButton.title = "Contour adjustment"
        self.contourAdjustmentCollapsibleButton.collapsed = True
        self.navigationCollapsibleLayout.addRow(self.contourAdjustmentCollapsibleButton)

        # Layout within the collapsible button
        self.contourAdjustmentFormLayout = qt.QFormLayout(self.contourAdjustmentCollapsibleButton)

        self.placeTumorPointAtCauteryTipButton = qt.QPushButton("Mark point at cautery tip")
        setButtonStyle(self.placeTumorPointAtCauteryTipButton)
        self.contourAdjustmentFormLayout.addRow(self.placeTumorPointAtCauteryTipButton)

        self.deleteLastFiducialDuringNavigationButton = qt.QPushButton("Delete last")
        self.deleteLastFiducialDuringNavigationButton.setIcon(qt.QIcon(":/Icons/MarkupsDelete.png"))
        setButtonStyle(self.deleteLastFiducialDuringNavigationButton)
        self.deleteLastFiducialDuringNavigationButton.setEnabled(False)
        self.contourAdjustmentFormLayout.addRow(self.deleteLastFiducialDuringNavigationButton)
  def setup(self):  
    #Instantiate and Connect Widgets 
    #################################################
    #HeterogeneityCAD Inputs Collapsible Button
    
    self.inputHeterogeneityCADCollapsibleButton = ctk.ctkCollapsibleButton()
    self.inputHeterogeneityCADCollapsibleButton.text = "HeterogeneityCAD Input"
    self.layout.addWidget(self.inputHeterogeneityCADCollapsibleButton)
    self.inputHeterogeneityCADLayout = qt.QFormLayout(self.inputHeterogeneityCADCollapsibleButton)
             
    ##Input Volume as a PET/CT/MRI image or parameter map converted to a volume
    self.inputVolHetFrame = qt.QFrame(self.inputHeterogeneityCADCollapsibleButton)
    self.inputVolHetFrame.setLayout(qt.QHBoxLayout())
    self.inputHeterogeneityCADLayout.addRow(self.inputVolHetFrame)     
    # label for selecting individual node
    self.inputVolHet = qt.QLabel("Input Node: ", self.inputVolHetFrame)
    self.inputVolHetFrame.layout().addWidget(self.inputVolHet)    
    # select individual nodes
    self.inputSelectorVolHet = slicer.qMRMLNodeComboBox(self.inputVolHetFrame)
    self.inputSelectorVolHet.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
    self.inputSelectorVolHet.selectNodeUponCreation = False 
    self.inputSelectorVolHet.addEnabled = False
    self.inputSelectorVolHet.removeEnabled = False
    self.inputSelectorVolHet.setMRMLScene( slicer.mrmlScene )
    self.inputVolHetFrame.layout().addWidget(self.inputSelectorVolHet)
    # add Data Node button
    self.addDataNodeButton = qt.QPushButton("Add Node", self.inputVolHetFrame)
    self.addDataNodeButton.objectName = 'AddDataNodeButton'
    self.addDataNodeButton.setToolTip( "Add a Node to Queue" )
    self.addDataNodeButton.connect('clicked()', self.onAddDataNodeButtonClicked)
    self.inputVolHetFrame.layout().addWidget(self.addDataNodeButton)
         
    ## data nodes Frame
    self.dataNodesFrame = ctk.ctkCollapsibleGroupBox(self.inputHeterogeneityCADCollapsibleButton)
    self.dataNodesFrame.title = "Nodes List"
    self.dataNodesFrame.collapsed = False
    self.dataNodesFrame.setLayout(qt.QVBoxLayout())    
    # all buttons frame
    self.allButtonsFrame = qt.QFrame(self.inputHeterogeneityCADCollapsibleButton)
    self.allButtonsFrame.objectName = 'AllButtonsFrameButton'
    self.allButtonsFrame.setLayout(qt.QVBoxLayout())
    self.inputHeterogeneityCADLayout.addRow(self.dataNodesFrame, self.allButtonsFrame)
    # Data Nodes view
    # Use list view here with scroll area widget.
    self.dataScrollArea = qt.QScrollArea()  
    self.dataNodesListWidget = qt.QListWidget()
    self.dataNodesListWidget.name = 'dataNodesListWidget'
    self.dataScrollArea.setWidget(self.dataNodesListWidget)
    self.dataNodesListWidget.resize(350,100)
    self.dataNodesFrame.layout().addWidget(self.dataScrollArea)
    #self.listWidget.setProperty('SH_ItemView_ActivateItemOnSingleClick', 1)
    #self.listWidget.connect('activated(QModelIndex)', self.onActivated)       
    # add all Data Nodes from scene button
    self.addAllDataNodesButton = qt.QPushButton("Add All Nodes From Scene", self.allButtonsFrame)
    self.addAllDataNodesButton.objectName = 'AddAllDataNodesButton'
    self.addAllDataNodesButton.setToolTip( "Add all Nodes from the Scene to Queue" )
    self.addAllDataNodesButton.connect('clicked()', self.onAddAllDataNodesButtonClicked)
    self.allButtonsFrame.layout().addWidget(self.addAllDataNodesButton)
    # remove single Data Node
    self.removeDataNodeButton = qt.QPushButton("Remove Node", self.allButtonsFrame)
    self.removeDataNodeButton.objectName = 'RemoveDataNodeButton'
    self.removeDataNodeButton.setToolTip( "Removes Selected Node from the Queue." )
    self.removeDataNodeButton.connect('clicked()', self.onRemoveDataNodeButtonClicked)
    self.allButtonsFrame.layout().addWidget(self.removeDataNodeButton)   
    # remove all Data Nodes button
    self.removeAllDataNodesButton = qt.QPushButton("Remove All Nodes", self.allButtonsFrame)
    self.removeAllDataNodesButton.objectName = 'RemoveAllDataNodesButton'
    self.removeAllDataNodesButton.setToolTip( "Removes All Nodes from the Queue." )
    self.removeAllDataNodesButton.connect('clicked()', self.onRemoveAllDataNodesButtonClicked)
    self.allButtonsFrame.layout().addWidget(self.removeAllDataNodesButton)
        
    # Use Label Map as ROI(segmentation output or user-selected ROI)
    self.inputLabelROIFrame = qt.QFrame(self.inputHeterogeneityCADCollapsibleButton)
    self.inputLabelROIFrame.setLayout(qt.QHBoxLayout())
    self.inputHeterogeneityCADLayout.addRow(self.inputLabelROIFrame)
    # Enable Input Label Map as ROI
    self.inputLabelROI = qt.QLabel("Label Map ROI: ", self.inputLabelROIFrame)
    self.inputLabelROIFrame.layout().addWidget(self.inputLabelROI) 
    # Select Input Label Map as ROI
    self.inputSelectorLabel = slicer.qMRMLNodeComboBox(self.inputLabelROIFrame)
    self.inputSelectorLabel.nodeTypes = ( ("vtkMRMLLabelMapVolumeNode"), "" )
    self.inputSelectorLabel.selectNodeUponCreation = False
    self.inputSelectorLabel.renameEnabled = True
    self.inputSelectorLabel.removeEnabled = False 
    self.inputSelectorLabel.noneEnabled = True
    self.inputSelectorLabel.addEnabled = False
    self.inputSelectorLabel.setMRMLScene( slicer.mrmlScene )    
    self.inputLabelROIFrame.layout().addWidget(self.inputSelectorLabel)

    #End HeterogeneityCAD Inputs Collapsible Button
    #################################################
    #HeterogeneityCAD Features Collapsible Button
    
    self.HeterogeneityCADCollapsibleButton = ctk.ctkCollapsibleButton()
    self.HeterogeneityCADCollapsibleButton.text = "HeterogeneityCAD Features Selection"
    self.layout.addWidget(self.HeterogeneityCADCollapsibleButton)
    self.featuresHeterogeneityCADLayout = qt.QFormLayout(self.HeterogeneityCADCollapsibleButton)

    # auto-generate QTabWidget Tabs and QCheckBoxes (subclassed in FeatureWidgetHelperLib)
    self.tabsFeatureClasses = FeatureWidgetHelperLib.CheckableTabWidget()
    self.featuresHeterogeneityCADLayout.addRow(self.tabsFeatureClasses)
     
    gridWidth, gridHeight = 3, 9
    for featureClass in self.featureClassKeys:    
      # by default, features from the following features classes are checked:
      if featureClass in ["Node Information", "First-Order Statistics", "Morphology and Shape", "Texture: GLCM", "Texture: GLRL"]:
        check = True
      else:
        check = False 
      tabFeatureClass = qt.QWidget()
      tabFeatureClass.setLayout(qt.QGridLayout())         
      #featureList = (feature for feature in self.featureClassKeys[featureClass])
      gridLayoutCoordinates = ((row,col) for col in range(gridWidth) for row in range(gridHeight))
      for featureName in self.featureClassKeys[featureClass]:
        row, col = next(gridLayoutCoordinates, None)
        if featureName is None or row is None or col is None:
          break       
        featureCheckboxWidget = FeatureWidgetHelperLib.FeatureWidget()      
        featureCheckboxWidget.Setup(featureName=featureName, checkStatus=check)
                   
        tabFeatureClass.layout().addWidget(featureCheckboxWidget, row, col)
        self.featureWidgets[featureClass].append(featureCheckboxWidget)       
      self.tabsFeatureClasses.addTab(tabFeatureClass, featureClass, self.featureWidgets[featureClass], checkStatus=check)
      
    self.tabsFeatureClasses.setCurrentIndex(1)
    
    # note: try using itertools list merging with lists of GLRL diagonal    
    self.heterogeneityFeatureWidgets = list(itertools.chain.from_iterable(self.featureWidgets.values()))
    self.classes = list(self.featureWidgets.keys())
    # or reduce(lambda x,y: x+y, self.featureWidgets.values())
    
    ########## Parameter options 
    # add parameters for top-level feature classes
    self.tabsFeatureClasses.addParameter("Geometrical Measures", "Extrusion Parameter 1")
    self.tabsFeatureClasses.addParameter("Texture: GLCM", "GLCM Matrix Parameter 1")
    self.tabsFeatureClasses.addParameter("Texture: GLRL", "GLRL Matrix Parameter 1")
    
    # compile dict of feature classes with parameter names and values
    self.featureClassParametersDict = collections.OrderedDict()
    for featureClassWidget in self.tabsFeatureClasses.getFeatureClassWidgets():      
      featureClassName = featureClassWidget.getName()  
      self.featureClassParametersDict[featureClassName] = collections.OrderedDict()
      self.updateFeatureClassParameterDict(0,featureClassWidget)
      for parameterName in featureClassWidget.widgetMenu.parameters:
        featureClassWidget.getParameterEditWindow(parameterName).connect('intValueChanged(int)', lambda intValue, featureClassWidget=featureClassWidget: self.updateFeatureClassParameterDict(intValue, featureClassWidget))
    
    # add parameters for individual features
    for featureWidget in self.heterogeneityFeatureWidgets:
      if featureWidget.getName() == "Voxel Count":
        featureWidget.addParameter("Example Parameter 1")
        featureWidget.addParameter("Example Parameter 2")
      if featureWidget.getName() == "Gray Levels":
        featureWidget.addParameter("Example Parameter 1-GL")
        featureWidget.addParameter("Example Parameter 2-GL")
    
    # compile dict of features with parameter names and values
    self.featureParametersDict = collections.OrderedDict()
    for featureWidget in self.heterogeneityFeatureWidgets:
      featureName = featureWidget.getName()      
      self.featureParametersDict[featureName] = collections.OrderedDict()
      self.updateFeatureParameterDict(0,featureWidget)
      for parameterName in featureWidget.widgetMenu.parameters:
        featureWidget.getParameterEditWindow(parameterName).connect('intValueChanged(int)', lambda intValue, featureWidget=featureWidget: self.updateFeatureParameterDict(intValue, featureWidget)) #connect intvaluechanged signals to updateParamaterDict function 
    ##########
    
    # Feature Buttons Frame and Layout
    self.featureButtonFrame = qt.QFrame(self.HeterogeneityCADCollapsibleButton)
    self.featureButtonFrame.setLayout(qt.QHBoxLayout()) 
    self.featuresHeterogeneityCADLayout.addRow(self.featureButtonFrame)
       
    # HeterogeneityCAD Apply Button
    self.HeterogeneityCADButton = qt.QPushButton("Apply HeterogeneityCAD", self.featureButtonFrame)
    self.HeterogeneityCADButton.toolTip = "Analyze input volume using selected Heterogeneity Features."
    self.featureButtonFrame.layout().addWidget(self.HeterogeneityCADButton)
    self.HeterogeneityCADButton.connect('clicked()', self.onHeterogeneityCADButtonClicked)
        
    # Save Button
    self.saveButton = qt.QPushButton("Save to File", self.featureButtonFrame)
    self.saveButton.toolTip = "Save analyses to CSV file"
    self.saveButton.enabled = False
    self.featureButtonFrame.layout().addWidget(self.saveButton)
    self.saveButton.connect('clicked()', self.onSave)
    
    #End HeterogeneityCAD Features Collapsible Button
    #################################################
    #Feature Summary Chart

    #Complete chart options, export list of user-selected options identified via connections to labelstatistics module
    self.chartOptions = ("Count", "Volume mm^3", "Volume cc", "Min", "Max", "Mean", "StdDev")
    self.StatisticsChartCollapsibleButton = ctk.ctkCollapsibleButton()
    self.StatisticsChartCollapsibleButton.text = "HeterogeneityCAD Features Summary"
    self.layout.addWidget(self.StatisticsChartCollapsibleButton)
    self.StatisticsChartLayout = qt.QFormLayout(self.StatisticsChartCollapsibleButton)
    self.StatisticsChartCollapsibleButton.collapsed = False
    
    #Table View to display Label statistics
    self.view = qt.QTableView(self.StatisticsChartCollapsibleButton)
    self.view.sortingEnabled = True
    self.StatisticsChartLayout.addWidget(self.view)
    self.view.minimumHeight = 175   
Example #4
0
    def create(self):
        super(InteractiveConnectedComponentsUsingParzenPDFsOptions,
              self).create()

        ioCollapsibleButton = ctk.ctkCollapsibleGroupBox()
        ioCollapsibleButton.title = "IO"
        ioCollapsibleButton.collapsed = 0
        self.frame.layout().addWidget(ioCollapsibleButton)

        # Layout within the io collapsible button
        ioFormLayout = qt.QFormLayout(ioCollapsibleButton)
        self.additionalInputNodeSelectors = []
        for i in range(0, 2):
            self.additionalInputNodeSelectors.append(
                self.addInputNodeSelector(i, ioFormLayout))
        self.additionalInputNodeSelectors[
            0].toolTip = "Select the 1st additional input volume to be segmented"
        self.additionalInputNodeSelectors[
            1].toolTip = "Select the 2nd additional input volume to be segmented"

        # Objects
        objectCollapsibleGroupBox = ctk.ctkCollapsibleGroupBox()
        objectCollapsibleGroupBox.title = "Objects"
        self.frame.layout().addWidget(objectCollapsibleGroupBox)

        # Layout within the io collapsible button
        objectFormLayout = qt.QFormLayout(objectCollapsibleGroupBox)
        foregroundLayout = qt.QHBoxLayout()
        foregroundLabel = slicer.qMRMLLabelComboBox()
        foregroundLabel.objectName = 'Foreground label'
        foregroundLabel.setMRMLScene(slicer.mrmlScene)
        foregroundLabel.setMRMLColorNode(self.editUtil.getColorNode())
        foregroundLabel.labelValueVisible = True
        foregroundLabel.currentColor = 1
        self.foregroundLabel = foregroundLabel
        self.connections.append(
            (self.foregroundLabel, 'currentColorChanged(int)',
             self.updateMRMLFromGUI))
        foregroundWeightSpinBox = qt.QDoubleSpinBox(foregroundLabel)
        self.foregroundWeightSpinBox = foregroundWeightSpinBox
        foregroundWeightSpinBox.setRange(0.0, 1.0)
        foregroundWeightSpinBox.setSingleStep(0.1)
        foregroundWeightSpinBox.value = 1.0
        foregroundPopup = ctk.ctkPopupWidget(foregroundWeightSpinBox)
        foregroundPopupLayout = qt.QHBoxLayout(foregroundPopup)
        foregroundPopupSlider = ctk.ctkDoubleSlider(foregroundPopup)
        self.foregroundPopupSlider = foregroundPopupSlider
        foregroundPopupSlider.maximum = 1.0
        foregroundPopupSlider.minimum = 0.0
        foregroundPopupSlider.singleStep = 0.1
        foregroundPopupSlider.connect('valueChanged(double)',
                                      self.foregroundWeightSpinBox.setValue)
        foregroundWeightSpinBox.connect('valueChanged(double)',
                                        self.foregroundPopupSlider.setValue)
        self.connections.append(
            (self.foregroundWeightSpinBox, 'valueChanged(double)',
             self.updateMRMLFromGUI))
        foregroundLayout.addWidget(foregroundLabel)
        foregroundLayout.addWidget(foregroundWeightSpinBox)
        foregroundPopupLayout.addWidget(foregroundPopupSlider)
        objectFormLayout.addRow("Foreground Label:", foregroundLayout)
        self.objectLabel = foregroundLabel
        # http://qt-project.org/doc/qt-4.7/qt.html
        foregroundPopup.alignment = 0x0082  # Qt::AlignVCenter | Qt::AlignRight
        foregroundPopup.horizontalDirection = 0  # Qt::LeftToRight
        foregroundPopup.verticalDirection = 0  # Qt::TopToBottom
        foregroundPopup.animationEffect = 1  # Qt::ScrollEffect

        backgroundLayout = qt.QHBoxLayout()
        backgroundLabel = slicer.qMRMLLabelComboBox()
        backgroundLabel.objectName = 'Background label'
        backgroundLabel.setMRMLScene(slicer.mrmlScene)
        backgroundLabel.setMRMLColorNode(self.editUtil.getColorNode())
        backgroundLabel.labelValueVisible = True
        backgroundLabel.currentColor = 2
        self.backgroundLabel = backgroundLabel
        self.connections.append(
            (self.backgroundLabel, 'currentColorChanged(int)',
             self.updateMRMLFromGUI))
        backgroundWeightSpinBox = qt.QDoubleSpinBox(backgroundLabel)
        self.backgroundWeightSpinBox = backgroundWeightSpinBox
        backgroundWeightSpinBox.setRange(0.0, 1.0)
        backgroundWeightSpinBox.setSingleStep(0.1)
        backgroundWeightSpinBox.value = 1.0
        backgroundPopup = ctk.ctkPopupWidget(backgroundWeightSpinBox)
        backgroundPopupLayout = qt.QHBoxLayout(backgroundPopup)
        backgroundPopupSlider = ctk.ctkDoubleSlider(backgroundPopup)
        self.backgroundPopupSlider = backgroundPopupSlider
        backgroundPopupSlider.maximum = 1.0
        backgroundPopupSlider.minimum = 0.0
        backgroundPopupSlider.singleStep = 0.1
        backgroundPopupSlider.connect('valueChanged(double)',
                                      self.backgroundWeightSpinBox.setValue)
        backgroundWeightSpinBox.connect('valueChanged(double)',
                                        self.backgroundPopupSlider.setValue)
        self.connections.append(
            (self.backgroundWeightSpinBox, 'valueChanged(double)',
             self.updateMRMLFromGUI))
        backgroundLayout.addWidget(backgroundLabel)
        backgroundLayout.addWidget(backgroundWeightSpinBox)
        backgroundPopupLayout.addWidget(backgroundPopupSlider)
        objectFormLayout.addRow("Background Label:", backgroundLayout)
        self.backgroundLabel = backgroundLabel
        # http://qt-project.org/doc/qt-4.7/qt.html
        backgroundPopup.alignment = 0x0082  # Qt::AlignVCenter | Qt::AlignRight
        backgroundPopup.horizontalDirection = 0  # Qt::LeftToRight
        backgroundPopup.verticalDirection = 0  # Qt::TopToBottom
        backgroundPopup.animationEffect = 1  # Qt::ScrollEffect

        # Presets
        # Placeholder
        presetsCollapsibleGroupBox = ctk.ctkCollapsibleGroupBox()
        presetsCollapsibleGroupBox.title = "Preset"
        self.frame.layout().addWidget(presetsCollapsibleGroupBox)
        presetComboBox = slicer.qSlicerPresetComboBox()

        # Advanced Parameters
        paramsCollapsibleGroupBox = ctk.ctkCollapsibleGroupBox()
        paramsCollapsibleGroupBox.title = "Advanced Parameters"
        paramsCollapsibleGroupBox.collapsed = 1
        self.frame.layout().addWidget(paramsCollapsibleGroupBox)

        # Layout within the io collapsible button
        paramsFormLayout = qt.QFormLayout(paramsCollapsibleGroupBox)

        erosionSpinBox = qt.QSpinBox()
        erosionSpinBox.objectName = 'erosionSpinBox'
        erosionSpinBox.toolTip = "Set the erosion radius."
        erosionSpinBox.setMinimum(0)
        erosionSpinBox.setValue(5)  # Default
        paramsFormLayout.addRow("Erosion Radius:", erosionSpinBox)
        self.erosionSpinBox = erosionSpinBox
        self.connections.append(
            (self.erosionSpinBox, "valueChanged(int)", self.updateMRMLFromGUI))

        holeFillSpinBox = qt.QSpinBox()
        holeFillSpinBox.objectName = 'holeFillSpinBox'
        holeFillSpinBox.toolTip = "Set the hole fill iterations."
        holeFillSpinBox.setMinimum(0)
        holeFillSpinBox.setValue(5)  #Default
        paramsFormLayout.addRow("Hole Fill Iterations:", holeFillSpinBox)
        self.holeFillSpinBox = holeFillSpinBox
        self.connections.append((self.holeFillSpinBox, "valueChanged(int)",
                                 self.updateMRMLFromGUI))

        # probabilitySmoothingStandardDeviation spin box
        probabilitySmoothingStdDevSpinBox = qt.QDoubleSpinBox()
        probabilitySmoothingStdDevSpinBox.objectName = 'probabilitySmoothingStdDevSpinBox'
        probabilitySmoothingStdDevSpinBox.toolTip = "Standard deviation of blur applied to probability images prior to computing maximum likelihood of each class at each pixel."
        probabilitySmoothingStdDevSpinBox.setMinimum(0.0)
        probabilitySmoothingStdDevSpinBox.setValue(1.0)  # Default
        probabilitySmoothingStdDevSpinBox.setSingleStep(0.5)
        paramsFormLayout.addRow("Probability Smoothing Standard Deviation:",
                                probabilitySmoothingStdDevSpinBox)
        self.probabilitySmoothingStdDevSpinBox = probabilitySmoothingStdDevSpinBox
        self.connections.append(
            (self.probabilitySmoothingStdDevSpinBox, "valueChanged(double)",
             self.updateMRMLFromGUI))

        # histogramSmoothingStandardDeviation spin box
        histogramSmoothingStdDevSpinBox = qt.QDoubleSpinBox()
        histogramSmoothingStdDevSpinBox.objectName = 'histogramSmoothingStdDevSpinBox'
        histogramSmoothingStdDevSpinBox.toolTip = "Standard deviation of blur applied to histograms to convert them to probability density function estimates."
        histogramSmoothingStdDevSpinBox.setMinimum(0.0)
        histogramSmoothingStdDevSpinBox.setValue(5.0)  # Default
        histogramSmoothingStdDevSpinBox.setSingleStep(0.5)
        paramsFormLayout.addRow("Probability Smoothing Standard Deviation:",
                                histogramSmoothingStdDevSpinBox)
        self.histogramSmoothingStdDevSpinBox = histogramSmoothingStdDevSpinBox
        self.connections.append(
            (self.histogramSmoothingStdDevSpinBox, "valueChanged(double)",
             self.updateMRMLFromGUI))

        # draft check box
        draftCheckBox = qt.QCheckBox()
        draftCheckBox.objectName = 'draftCheckBox'
        draftCheckBox.toolTip = "Downsamples results by a factor of 4."
        paramsFormLayout.addRow("Draft Mode:", draftCheckBox)
        self.draftCheckBox = draftCheckBox
        self.connections.append(
            (self.draftCheckBox, "stateChanged(int)", self.updateMRMLFromGUI))

        # force classification check box
        forceClassificationCheckBox = qt.QCheckBox()
        forceClassificationCheckBox.objectName = 'forceClassificationCheckBox'
        forceClassificationCheckBox.toolTip = "Perform the classification of all voxels?"
        forceClassificationCheckBox.setChecked(False)
        paramsFormLayout.addRow("Classify all voxels: ",
                                forceClassificationCheckBox)
        self.forceClassificationCheckBox = forceClassificationCheckBox
        self.connections.append((self.forceClassificationCheckBox,
                                 "stateChanged(int)", self.updateMRMLFromGUI))

        # dilate first check box
        dilateFirstCheckBox = qt.QCheckBox()
        dilateFirstCheckBox.objectName = 'dilateFirstCheckBox'
        dilateFirstCheckBox.toolTip = "Dilate and then erode so as to fill-in holes?"
        dilateFirstCheckBox.setChecked(False)
        paramsFormLayout.addRow("Dilate First: ", dilateFirstCheckBox)
        self.dilateFirstCheckBox = dilateFirstCheckBox
        self.connections.append((self.dilateFirstCheckBox, "stateChanged(int)",
                                 self.updateMRMLFromGUI))

        self.helpLabel = qt.QLabel(
            "Run the PDF Segmentation on the current label map.", self.frame)
        self.frame.layout().addWidget(self.helpLabel)

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

        EditorLib.HelpButton(
            self.frame,
            "Use this tool to apply segmentation using Parzen windowed PDFs.\n\n Select different label colors and paint on the foreground or background voxels using the paint effect.\nTo run segmentation correctly, you need to supply a minimum or two class labels."
        )

        self.connections.append((self.apply, 'clicked()', self.onApply))
Example #5
0
  def create(self):
    """create the segmentation helper box"""

    #
    # Master Frame
    # 
    self.masterFrame = qt.QFrame(self.parent)
    self.masterFrame.setLayout(qt.QVBoxLayout())
    self.parent.layout().addWidget(self.masterFrame)

    #
    # the master volume selector
    #
    self.masterSelectorFrame = qt.QFrame(self.parent)
    self.masterSelectorFrame.setLayout(qt.QHBoxLayout())
    self.masterFrame.layout().addWidget(self.masterSelectorFrame)

    self.masterSelectorLabel = qt.QLabel("Master Volume: ", self.masterSelectorFrame)
    self.masterSelectorLabel.setToolTip( "Select the master volume (background grayscale scalar volume node)")
    self.masterSelectorFrame.layout().addWidget(self.masterSelectorLabel)

    self.masterSelector = slicer.qMRMLNodeComboBox(self.masterSelectorFrame)
    # TODO
    self.masterSelector.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
    self.masterSelector.addAttribute( "vtkMRMLScalarVolumeNode", "LabelMap", 0 )
    self.masterSelector.selectNodeUponCreation = False
    self.masterSelector.addEnabled = False
    self.masterSelector.removeEnabled = False
    self.masterSelector.noneEnabled = True
    self.masterSelector.showHidden = False
    self.masterSelector.showChildNodeTypes = False
    self.masterSelector.setMRMLScene( slicer.mrmlScene )
    # TODO: need to add a QLabel
    # self.masterSelector.SetLabelText( "Master Volume:" )
    self.masterSelector.setToolTip( "Pick the master structural volume to define the segmentation.  A label volume with the with \"-label\" appended to the name will be created if it doesn't already exist." )
    self.masterSelectorFrame.layout().addWidget(self.masterSelector)


    #
    # merge label name and set button
    #
    self.mergeFrame = qt.QFrame(self.masterFrame)
    self.mergeFrame.setLayout(qt.QHBoxLayout())
    self.masterFrame.layout().addWidget(self.mergeFrame)

    mergeNameToolTip = "Composite label map containing the merged structures (be aware that merge operations will overwrite any edits applied to this volume)"
    self.mergeNameLabel = qt.QLabel("Merge Volume: ", self.mergeFrame)
    self.mergeNameLabel.setToolTip( mergeNameToolTip )
    self.mergeFrame.layout().addWidget(self.mergeNameLabel)

    self.mergeName = qt.QLabel("", self.mergeFrame)
    self.mergeName.setToolTip( mergeNameToolTip )
    self.mergeFrame.layout().addWidget(self.mergeName)

    self.setMergeButton = qt.QPushButton("Set...", self.mergeFrame)
    self.setMergeButton.setToolTip( "Set the merge volume to use with this master." )
    self.mergeFrame.layout().addWidget(self.setMergeButton)


    #
    # Structures Frame
    # 

    self.structuresFrame = ctk.ctkCollapsibleGroupBox(self.masterFrame)
    self.structuresFrame.title = "Per-Structure Volumes"
    self.structuresFrame.collapsed = True
    self.structuresFrame.setLayout(qt.QVBoxLayout())
    self.masterFrame.layout().addWidget(self.structuresFrame)

    # buttons frame 

    self.structureButtonsFrame = qt.QFrame(self.structuresFrame)
    self.structureButtonsFrame.setLayout(qt.QHBoxLayout())
    self.structuresFrame.layout().addWidget(self.structureButtonsFrame)

    # add button

    self.addStructureButton = qt.QPushButton("Add Structure", self.structureButtonsFrame)
    self.addStructureButton.setToolTip( "Add a label volume for a structure to edit" )
    self.structureButtonsFrame.layout().addWidget(self.addStructureButton)

    # split button

    self.splitButton = qt.QPushButton("Split Merge Volume", self.structuresFrame)
    self.splitButton.setToolTip( "Split distinct labels from merge volume into new volumes" )
    self.structureButtonsFrame.layout().addWidget(self.splitButton)

    # structures view

    self.structuresView = qt.QTreeView()
    self.structuresView.sortingEnabled = True
    self.structuresFrame.layout().addWidget(self.structuresView)

    # all buttons frame 

    self.allButtonsFrame = qt.QFrame(self.structuresFrame)
    self.allButtonsFrame.setLayout(qt.QHBoxLayout())
    self.structuresFrame.layout().addWidget(self.allButtonsFrame)

    # delete structures button

    self.deleteStructuresButton = qt.QPushButton("Delete Structures", self.allButtonsFrame)
    self.deleteStructuresButton.setToolTip( "Delete all the structure volumes from the scene.\n\nNote: to delete individual structure volumes, use the Data Module." )
    self.allButtonsFrame.layout().addWidget(self.deleteStructuresButton)

    # merge button

    self.mergeButton = qt.QPushButton("Merge All", self.allButtonsFrame)
    self.mergeButton.setToolTip( "Merge all structures into Merge Volume" )
    self.allButtonsFrame.layout().addWidget(self.mergeButton)

    # merge and build button

    self.mergeAndBuildButton = qt.QPushButton("Merge And Build", self.allButtonsFrame)
    self.mergeAndBuildButton.setToolTip( "Merge all structures into Merge Volume and build models from all structures")
    self.allButtonsFrame.layout().addWidget(self.mergeAndBuildButton)
    # options frame

    self.optionsFrame = qt.QFrame(self.structuresFrame)
    self.optionsFrame.setLayout(qt.QHBoxLayout())
    self.structuresFrame.layout().addWidget(self.optionsFrame)

    # replace models button

    self.replaceModels = qt.QCheckBox("Replace Models", self.optionsFrame)
    self.replaceModels.setToolTip( "Replace any existing models when building" )
    self.replaceModels.setChecked(1)
    self.optionsFrame.layout().addWidget(self.replaceModels)

    #
    # signals, slots, and observers
    #

    # signals/slots on qt widgets are automatically when
    # this class destructs, but observers of the scene must be explicitly 
    # removed in the destuctor

    # node selected 
    self.masterSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    # buttons pressed
    self.addStructureButton.connect("clicked()", self.addStructure)
    self.deleteStructuresButton.connect("clicked()", self.deleteStructures)
    # selection changed event
    self.structuresView.connect("clicked(QModelIndex)", self.onStructuresClicked)
    # invoked event
    self.splitButton.connect("clicked()", self.split)
    self.mergeButton.connect("clicked()", self.mergeStructures)
    self.mergeAndBuildButton.connect("clicked()", self.onMergeAndBuild)
    self.setMergeButton.connect("clicked()", self.labelSelectDialog)

    # new scene, node added or removed events
    # TODO: allow observers on speific events: 66000, 66001, 66002
    tag = slicer.mrmlScene.AddObserver("ModifiedEvent", self.updateStructures)
    self.observerTags.append( (slicer.mrmlScene, tag) )

    # so buttons will initially be disabled
    self.master = None
    self.updateStructures()
  def create(self):
    super(InteractiveConnectedComponentsUsingParzenPDFsOptions,self).create()

    ioCollapsibleButton = ctk.ctkCollapsibleGroupBox()
    ioCollapsibleButton.title = "IO"
    ioCollapsibleButton.collapsed = 0
    self.frame.layout().addWidget(ioCollapsibleButton)

    # Layout within the io collapsible button
    ioFormLayout = qt.QFormLayout(ioCollapsibleButton)
    self.additionalInputNodeSelectors = []
    for i in range(0,2):
      self.additionalInputNodeSelectors.append(self.addInputNodeSelector(i, ioFormLayout))
    self.additionalInputNodeSelectors[0].toolTip = "Select the 1st additional input volume to be segmented"
    self.additionalInputNodeSelectors[1].toolTip = "Select the 2nd additional input volume to be segmented"

    # Objects
    objectCollapsibleGroupBox = ctk.ctkCollapsibleGroupBox()
    objectCollapsibleGroupBox.title = "Objects"
    self.frame.layout().addWidget(objectCollapsibleGroupBox)

    # Layout within the io collapsible button
    objectFormLayout = qt.QFormLayout(objectCollapsibleGroupBox)
    foregroundLayout = qt.QHBoxLayout()
    foregroundLabel = slicer.qMRMLLabelComboBox()
    foregroundLabel.objectName = 'Foreground label'
    foregroundLabel.setMRMLScene(slicer.mrmlScene)
    foregroundLabel.setMRMLColorNode(self.editUtil.getColorNode())
    foregroundLabel.labelValueVisible = True
    foregroundLabel.currentColor = 1
    self.foregroundLabel = foregroundLabel
    self.connections.append( (self.foregroundLabel, 'currentColorChanged(int)', self.updateMRMLFromGUI ) )
    foregroundWeightSpinBox = qt.QDoubleSpinBox(foregroundLabel)
    self.foregroundWeightSpinBox = foregroundWeightSpinBox
    foregroundWeightSpinBox.setRange(0.0, 1.0)
    foregroundWeightSpinBox.setSingleStep(0.1)
    foregroundWeightSpinBox.value = 1.0
    foregroundPopup = ctk.ctkPopupWidget( foregroundWeightSpinBox )
    foregroundPopupLayout = qt.QHBoxLayout( foregroundPopup )
    foregroundPopupSlider = ctk.ctkDoubleSlider( foregroundPopup )
    self.foregroundPopupSlider = foregroundPopupSlider
    foregroundPopupSlider.maximum = 1.0
    foregroundPopupSlider.minimum = 0.0
    foregroundPopupSlider.singleStep = 0.1
    foregroundPopupSlider.connect('valueChanged(double)', self.foregroundWeightSpinBox.setValue)
    foregroundWeightSpinBox.connect('valueChanged(double)', self.foregroundPopupSlider.setValue)
    self.connections.append( (self.foregroundWeightSpinBox, 'valueChanged(double)', self.updateMRMLFromGUI ) )
    foregroundLayout.addWidget( foregroundLabel )
    foregroundLayout.addWidget( foregroundWeightSpinBox )
    foregroundPopupLayout.addWidget( foregroundPopupSlider )
    objectFormLayout.addRow("Foreground Label:", foregroundLayout )
    self.objectLabel = foregroundLabel
    # http://qt-project.org/doc/qt-4.7/qt.html
    foregroundPopup.alignment = 0x0082 # Qt::AlignVCenter | Qt::AlignRight
    foregroundPopup.horizontalDirection = 0 # Qt::LeftToRight
    foregroundPopup.verticalDirection = 0 # Qt::TopToBottom
    foregroundPopup.animationEffect = 1 # Qt::ScrollEffect

    backgroundLayout = qt.QHBoxLayout()
    backgroundLabel = slicer.qMRMLLabelComboBox()
    backgroundLabel.objectName = 'Background label'
    backgroundLabel.setMRMLScene(slicer.mrmlScene)
    backgroundLabel.setMRMLColorNode(self.editUtil.getColorNode())
    backgroundLabel.labelValueVisible = True
    backgroundLabel.currentColor = 2
    self.backgroundLabel = backgroundLabel
    self.connections.append( (self.backgroundLabel, 'currentColorChanged(int)', self.updateMRMLFromGUI ) )
    backgroundWeightSpinBox = qt.QDoubleSpinBox(backgroundLabel)
    self.backgroundWeightSpinBox = backgroundWeightSpinBox
    backgroundWeightSpinBox.setRange(0.0, 1.0)
    backgroundWeightSpinBox.setSingleStep(0.1)
    backgroundWeightSpinBox.value = 1.0
    backgroundPopup = ctk.ctkPopupWidget( backgroundWeightSpinBox )
    backgroundPopupLayout = qt.QHBoxLayout( backgroundPopup )
    backgroundPopupSlider = ctk.ctkDoubleSlider( backgroundPopup )
    self.backgroundPopupSlider = backgroundPopupSlider
    backgroundPopupSlider.maximum = 1.0
    backgroundPopupSlider.minimum = 0.0
    backgroundPopupSlider.singleStep = 0.1
    backgroundPopupSlider.connect('valueChanged(double)', self.backgroundWeightSpinBox.setValue)
    backgroundWeightSpinBox.connect('valueChanged(double)', self.backgroundPopupSlider.setValue)
    self.connections.append( (self.backgroundWeightSpinBox, 'valueChanged(double)', self.updateMRMLFromGUI ) )
    backgroundLayout.addWidget( backgroundLabel )
    backgroundLayout.addWidget( backgroundWeightSpinBox )
    backgroundPopupLayout.addWidget( backgroundPopupSlider )
    objectFormLayout.addRow("Background Label:", backgroundLayout)
    self.backgroundLabel = backgroundLabel
    # http://qt-project.org/doc/qt-4.7/qt.html
    backgroundPopup.alignment = 0x0082 # Qt::AlignVCenter | Qt::AlignRight
    backgroundPopup.horizontalDirection = 0 # Qt::LeftToRight
    backgroundPopup.verticalDirection = 0 # Qt::TopToBottom
    backgroundPopup.animationEffect = 1 # Qt::ScrollEffect

    # Presets
    # Placeholder
    presetsCollapsibleGroupBox = ctk.ctkCollapsibleGroupBox()
    presetsCollapsibleGroupBox.title = "Preset"
    self.frame.layout().addWidget(presetsCollapsibleGroupBox)
    presetComboBox = slicer.qSlicerPresetComboBox()

    # Advanced Parameters
    paramsCollapsibleGroupBox = ctk.ctkCollapsibleGroupBox()
    paramsCollapsibleGroupBox.title = "Advanced Parameters"
    paramsCollapsibleGroupBox.collapsed = 1
    self.frame.layout().addWidget(paramsCollapsibleGroupBox)

    # Layout within the io collapsible button
    paramsFormLayout = qt.QFormLayout(paramsCollapsibleGroupBox)

    erosionSpinBox = qt.QSpinBox()
    erosionSpinBox.objectName = 'erosionSpinBox'
    erosionSpinBox.toolTip = "Set the erosion radius."
    erosionSpinBox.setMinimum(0)
    erosionSpinBox.setValue(5) # Default
    paramsFormLayout.addRow("Erosion Radius:", erosionSpinBox)
    self.erosionSpinBox = erosionSpinBox
    self.connections.append( (self.erosionSpinBox, "valueChanged(int)", self.updateMRMLFromGUI ) )

    holeFillSpinBox = qt.QSpinBox()
    holeFillSpinBox.objectName = 'holeFillSpinBox'
    holeFillSpinBox.toolTip = "Set the hole fill iterations."
    holeFillSpinBox.setMinimum(0)
    holeFillSpinBox.setValue(5) #Default
    paramsFormLayout.addRow("Hole Fill Iterations:", holeFillSpinBox)
    self.holeFillSpinBox = holeFillSpinBox
    self.connections.append( (self.holeFillSpinBox, "valueChanged(int)", self.updateMRMLFromGUI ) )

    # probabilitySmoothingStandardDeviation spin box
    probabilitySmoothingStdDevSpinBox = qt.QDoubleSpinBox()
    probabilitySmoothingStdDevSpinBox.objectName = 'probabilitySmoothingStdDevSpinBox'
    probabilitySmoothingStdDevSpinBox.toolTip = "Standard deviation of blur applied to probability images prior to computing maximum likelihood of each class at each pixel."
    probabilitySmoothingStdDevSpinBox.setMinimum(0.0)
    probabilitySmoothingStdDevSpinBox.setValue(1.0) # Default
    probabilitySmoothingStdDevSpinBox.setSingleStep(0.5)
    paramsFormLayout.addRow("Probability Smoothing Standard Deviation:", probabilitySmoothingStdDevSpinBox)
    self.probabilitySmoothingStdDevSpinBox = probabilitySmoothingStdDevSpinBox
    self.connections.append( (self.probabilitySmoothingStdDevSpinBox, "valueChanged(double)", self.updateMRMLFromGUI ) )

    # histogramSmoothingStandardDeviation spin box
    histogramSmoothingStdDevSpinBox = qt.QDoubleSpinBox()
    histogramSmoothingStdDevSpinBox.objectName = 'histogramSmoothingStdDevSpinBox'
    histogramSmoothingStdDevSpinBox.toolTip = "Standard deviation of blur applied to histograms to convert them to probability density function estimates."
    histogramSmoothingStdDevSpinBox.setMinimum(0.0)
    histogramSmoothingStdDevSpinBox.setValue(5.0) # Default
    histogramSmoothingStdDevSpinBox.setSingleStep(0.5)
    paramsFormLayout.addRow("Probability Smoothing Standard Deviation:", histogramSmoothingStdDevSpinBox)
    self.histogramSmoothingStdDevSpinBox = histogramSmoothingStdDevSpinBox
    self.connections.append( (self.histogramSmoothingStdDevSpinBox, "valueChanged(double)", self.updateMRMLFromGUI ) )

    # draft check box
    draftCheckBox = qt.QCheckBox()
    draftCheckBox.objectName = 'draftCheckBox'
    draftCheckBox.toolTip = "Downsamples results by a factor of 4."
    paramsFormLayout.addRow("Draft Mode:", draftCheckBox)
    self.draftCheckBox = draftCheckBox
    self.connections.append( (self.draftCheckBox, "stateChanged(int)", self.updateMRMLFromGUI ) )

    # force classification check box
    forceClassificationCheckBox = qt.QCheckBox()
    forceClassificationCheckBox.objectName = 'forceClassificationCheckBox'
    forceClassificationCheckBox.toolTip = "Perform the classification of all voxels?"
    forceClassificationCheckBox.setChecked(False)
    paramsFormLayout.addRow("Classify all voxels: ", forceClassificationCheckBox)
    self.forceClassificationCheckBox = forceClassificationCheckBox
    self.connections.append( (self.forceClassificationCheckBox, "stateChanged(int)", self.updateMRMLFromGUI ) )

    # dilate first check box
    dilateFirstCheckBox = qt.QCheckBox()
    dilateFirstCheckBox.objectName = 'dilateFirstCheckBox'
    dilateFirstCheckBox.toolTip = "Dilate and then erode so as to fill-in holes?"
    dilateFirstCheckBox.setChecked(False)
    paramsFormLayout.addRow("Dilate First: ", dilateFirstCheckBox)
    self.dilateFirstCheckBox = dilateFirstCheckBox
    self.connections.append( (self.dilateFirstCheckBox, "stateChanged(int)", self.updateMRMLFromGUI ) )

    self.helpLabel = qt.QLabel("Run the PDF Segmentation on the current label map.", self.frame)
    self.frame.layout().addWidget(self.helpLabel)

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

    EditorLib.HelpButton(self.frame, "Use this tool to apply segmentation using Parzen windowed PDFs.\n\n Select different label colors and paint on the foreground or background voxels using the paint effect.\nTo run segmentation correctly, you need to supply a minimum or two class labels.")

    self.connections.append( (self.apply, 'clicked()', self.onApply) )
Example #7
0
  def setup(self):
    # TODO: The following line is strictly for debug purposes, should be removed when this module is done
    slicer.tvwidget = self

    # Collapsible buttons
    self.parametersCollapsibleButton = ctk.ctkCollapsibleButton()
    self.parametersCollapsibleButton.text = "Parameters"
    self.layout.addWidget(self.parametersCollapsibleButton)

    # Layout within the collapsible button
    self.parametersFormLayout = qt.QFormLayout(self.parametersCollapsibleButton)
    
    # Transform combobox
    self.transformLabel = qt.QLabel()
    self.transformLabel.setText("toolCameraToToolTransform: ")
    self.transformSelector = slicer.qMRMLNodeComboBox()
    self.transformSelector.nodeTypes = ( ("vtkMRMLLinearTransformNode"), "" )
    self.transformSelector.noneEnabled = False
    self.transformSelector.addEnabled = False
    self.transformSelector.removeEnabled = False
    self.transformSelector.setMRMLScene( slicer.mrmlScene )
    self.transformSelector.setToolTip("Pick the transform that the camera should follow, e.g. 'cauteryCameraToCauteryTransform'")
    self.parametersFormLayout.addRow(self.transformLabel, self.transformSelector)
    
    # Camera combobox
    self.cameraLabel = qt.QLabel()
    self.cameraLabel.setText("Scene Camera: ")
    self.cameraSelector = slicer.qMRMLNodeComboBox()
    self.cameraSelector.nodeTypes = ( ("vtkMRMLCameraNode"), "" )
    self.cameraSelector.noneEnabled = False
    self.cameraSelector.addEnabled = False
    self.cameraSelector.removeEnabled = False
    self.cameraSelector.setMRMLScene( slicer.mrmlScene )
    self.cameraSelector.setToolTip("Pick the camera which should be moved, e.g. 'Default Scene Camera'")
    self.parametersFormLayout.addRow(self.cameraLabel, self.cameraSelector)

    # "Camera Control" Collapsible
    self.cameraControlCollapsibleButton = ctk.ctkCollapsibleButton()
    self.cameraControlCollapsibleButton.text = "Camera Control"
    self.layout.addWidget(self.cameraControlCollapsibleButton)

    # Layout within the collapsible button
    self.cameraControlFormLayout = qt.QFormLayout(self.cameraControlCollapsibleButton)
    
    # "Degrees of Freedom" Collapsible button
    self.degreesOfFreedomCollapsibleButton = ctk.ctkCollapsibleGroupBox()
    self.degreesOfFreedomCollapsibleButton.title = "Degrees of Freedom"
    self.cameraControlFormLayout.addRow(self.degreesOfFreedomCollapsibleButton)

    # Layout within the collapsible button
    self.degreesOfFreedomFormLayout = qt.QFormLayout(self.degreesOfFreedomCollapsibleButton)
    
    # A series of radio buttons for changing the degrees of freedom
    self.degreesOfFreedom3Label = qt.QLabel(qt.Qt.Horizontal,None)
    self.degreesOfFreedom3Label.setText("3DOF: ")
    self.degreesOfFreedom3RadioButton = qt.QRadioButton()
    self.degreesOfFreedom3RadioButton.setToolTip("The camera will always look at the target model (or if unselected will act like 5DOF)")
    self.degreesOfFreedomFormLayout.addRow(self.degreesOfFreedom3Label,self.degreesOfFreedom3RadioButton)
    
    self.degreesOfFreedom5Label = qt.QLabel(qt.Qt.Horizontal,None)
    self.degreesOfFreedom5Label.setText("5DOF: ")
    self.degreesOfFreedom5RadioButton = qt.QRadioButton()
    self.degreesOfFreedom5RadioButton.setToolTip("The camera will always be oriented with the selected 'up direction'")
    self.degreesOfFreedomFormLayout.addRow(self.degreesOfFreedom5Label,self.degreesOfFreedom5RadioButton)
    
    self.degreesOfFreedom6Label = qt.QLabel(qt.Qt.Horizontal,None)
    self.degreesOfFreedom6Label.setText("6DOF: ")
    self.degreesOfFreedom6RadioButton = qt.QRadioButton()
    self.degreesOfFreedom6RadioButton.setToolTip("The camera will be virtually attached to the tool, and rotate together with it")
    self.degreesOfFreedom6RadioButton.setChecked(True)
    self.degreesOfFreedomFormLayout.addRow(self.degreesOfFreedom6Label,self.degreesOfFreedom6RadioButton)
    
    # "Up Direction" Collapsible button
    self.upDirectionCollapsibleButton = ctk.ctkCollapsibleGroupBox()
    self.upDirectionCollapsibleButton.title = "Up Direction"
    self.upDirectionCollapsibleButton.setVisible(False)
    self.cameraControlFormLayout.addRow(self.upDirectionCollapsibleButton)

    # Layout within the collapsible button
    self.upDirectionFormLayout = qt.QFormLayout(self.upDirectionCollapsibleButton)
    
    # Radio buttons for each of the anatomical directions
    self.upDirectionAnteriorLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.upDirectionAnteriorLabel.setText("Anterior: ")
    self.upDirectionAnteriorRadioButton = qt.QRadioButton()
    self.upDirectionAnteriorRadioButton.setChecked(True)
    self.upDirectionFormLayout.addRow(self.upDirectionAnteriorLabel,self.upDirectionAnteriorRadioButton)
    
    self.upDirectionPosteriorLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.upDirectionPosteriorLabel.setText("Posterior: ")
    self.upDirectionPosteriorRadioButton = qt.QRadioButton()
    self.upDirectionFormLayout.addRow(self.upDirectionPosteriorLabel,self.upDirectionPosteriorRadioButton)
    
    self.upDirectionRightLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.upDirectionRightLabel.setText("Right: ")
    self.upDirectionRightRadioButton = qt.QRadioButton()
    self.upDirectionFormLayout.addRow(self.upDirectionRightLabel,self.upDirectionRightRadioButton)
    
    self.upDirectionLeftLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.upDirectionLeftLabel.setText("Left: ")
    self.upDirectionLeftRadioButton = qt.QRadioButton()
    self.upDirectionFormLayout.addRow(self.upDirectionLeftLabel,self.upDirectionLeftRadioButton)
    
    self.upDirectionSuperiorLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.upDirectionSuperiorLabel.setText("Superior: ")
    self.upDirectionSuperiorRadioButton = qt.QRadioButton()
    self.upDirectionFormLayout.addRow(self.upDirectionSuperiorLabel,self.upDirectionSuperiorRadioButton)
    
    self.upDirectionInferiorLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.upDirectionInferiorLabel.setText("Inferior: ")
    self.upDirectionInferiorRadioButton = qt.QRadioButton()
    self.upDirectionFormLayout.addRow(self.upDirectionInferiorLabel,self.upDirectionInferiorRadioButton)
    
    # "Target Model" Collapsible button
    self.targetModelCollapsibleButton = ctk.ctkCollapsibleGroupBox()
    self.targetModelCollapsibleButton.title = "Target Model"
    self.targetModelCollapsibleButton.setVisible(False)
    self.cameraControlFormLayout.addRow(self.targetModelCollapsibleButton)

    # Layout within the collapsible button
    self.targetModelFormLayout = qt.QFormLayout(self.targetModelCollapsibleButton)
    
    # Selection of the target model
    self.targetModelLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.targetModelLabel.text = "Target model: "
    self.targetModelSelector = slicer.qMRMLNodeComboBox()
    self.targetModelSelector.nodeTypes = ( ("vtkMRMLModelNode"), "" )
    self.targetModelSelector.noneEnabled = False
    self.targetModelSelector.addEnabled = False
    self.targetModelSelector.removeEnabled = False
    self.targetModelSelector.setMRMLScene( slicer.mrmlScene )
    self.targetModelSelector.setToolTip("This model be the center of rotation using 3DOF Viewpoint (e.g. tumour)")
    self.targetModelFormLayout.addRow(self.targetModelLabel,self.targetModelSelector)
    
    # "Zoom" Collapsible button
    self.zoomCollapsibleButton = ctk.ctkCollapsibleGroupBox()
    self.zoomCollapsibleButton.title = "Zoom"
    self.cameraControlFormLayout.addRow(self.zoomCollapsibleButton)

    # Layout within the collapsible button
    self.zoomFormLayout = qt.QFormLayout(self.zoomCollapsibleButton)
    
    # Camera viewing angle (perspective projection only)
    self.cameraViewAngleLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.cameraViewAngleLabel.setText("View angle (degrees): ")
    self.cameraViewAngleSlider = slicer.qMRMLSliderWidget()
    self.cameraViewAngleSlider.minimum = self.cameraViewAngleMinDeg
    self.cameraViewAngleSlider.maximum = self.cameraViewAngleMaxDeg
    self.cameraViewAngleSlider.value = self.sliderViewAngleDefaultDeg
    self.cameraViewAngleSlider.singleStep = self.sliderSingleStepValue
    self.cameraViewAngleSlider.pageStep = self.sliderPageStepValue
    self.cameraViewAngleSlider.setToolTip("Make the current viewing target look larger/smaller.")
    self.zoomFormLayout.addRow(self.cameraViewAngleLabel,self.cameraViewAngleSlider)
    
    # Camera parallel scale (parallel projection only)
    self.cameraParallelScaleLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.cameraParallelScaleLabel.setText("View scale: ")
    self.cameraParallelScaleLabel.setVisible(False)
    self.cameraParallelScaleSlider = slicer.qMRMLSliderWidget()
    self.cameraParallelScaleSlider.minimum = self.cameraParallelScaleMinDeg
    self.cameraParallelScaleSlider.maximum = self.cameraParallelScaleMaxDeg
    self.cameraParallelScaleSlider.value = self.sliderParallelScaleDefaultDeg
    self.cameraParallelScaleSlider.singleStep = self.sliderSingleStepValue
    self.cameraParallelScaleSlider.pageStep = self.sliderPageStepValue
    self.cameraParallelScaleSlider.setToolTip("Make the current viewing target look larger/smaller.")
    self.cameraParallelScaleSlider.setVisible(False)
    self.zoomFormLayout.addRow(self.cameraParallelScaleLabel,self.cameraParallelScaleSlider)
    
    # "Translation" Collapsible
    self.translationCollapsibleButton = ctk.ctkCollapsibleGroupBox()
    self.translationCollapsibleButton.title = "Translation"
    self.cameraControlFormLayout.addRow(self.translationCollapsibleButton)

    # Layout within the collapsible button
    self.translationFormLayout = qt.QFormLayout(self.translationCollapsibleButton)
    
    self.cameraXPosLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.cameraXPosLabel.text = "Left/Right (mm): "
    self.cameraXPosSlider = slicer.qMRMLSliderWidget()
    self.cameraXPosSlider.minimum = self.sliderTranslationMinMm
    self.cameraXPosSlider.maximum = self.sliderTranslationMaxMm
    self.cameraXPosSlider.value = self.sliderTranslationDefaultMm
    self.cameraXPosSlider.singleStep = self.sliderSingleStepValue
    self.cameraXPosSlider.pageStep = self.sliderPageStepValue
    self.translationFormLayout.addRow(self.cameraXPosLabel,self.cameraXPosSlider)
    
    self.cameraYPosLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.cameraYPosLabel.setText("Down/Up (mm): ")
    self.cameraYPosSlider = slicer.qMRMLSliderWidget()
    self.cameraYPosSlider.minimum = self.sliderTranslationMinMm
    self.cameraYPosSlider.maximum = self.sliderTranslationMaxMm
    self.cameraYPosSlider.value = self.sliderTranslationDefaultMm
    self.cameraYPosSlider.singleStep = self.sliderSingleStepValue
    self.cameraYPosSlider.pageStep = self.sliderPageStepValue
    self.translationFormLayout.addRow(self.cameraYPosLabel,self.cameraYPosSlider)
    
    self.cameraZPosLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.cameraZPosLabel.setText("Front/Back (mm): ")
    self.cameraZPosSlider = slicer.qMRMLSliderWidget()
    self.cameraZPosSlider.minimum = self.sliderTranslationMinMm
    self.cameraZPosSlider.maximum = self.sliderTranslationMaxMm
    self.cameraZPosSlider.value = self.sliderTranslationDefaultMm
    self.cameraZPosSlider.singleStep = self.sliderSingleStepValue
    self.cameraZPosSlider.pageStep = self.sliderPageStepValue
    self.translationFormLayout.addRow(self.cameraZPosLabel,self.cameraZPosSlider)
    
    # "Model Visibility" Collapsible
    self.modelVisibilityCollapsibleButton = ctk.ctkCollapsibleGroupBox()
    self.modelVisibilityCollapsibleButton.title = "Model Visibility"
    self.cameraControlFormLayout.addRow(self.modelVisibilityCollapsibleButton)
    
    # Layout within the collapsible button
    self.modelVisibilityFormLayout = qt.QFormLayout(self.modelVisibilityCollapsibleButton)
    
    self.modelOnlyViewpointOnLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.modelOnlyViewpointOnLabel.text = "Model visible only for Viewpoint on: "
    self.modelOnlyViewpointOnSelector = slicer.qMRMLNodeComboBox()
    self.modelOnlyViewpointOnSelector.nodeTypes = ( ("vtkMRMLModelNode"), "" )
    self.modelOnlyViewpointOnSelector.noneEnabled = True
    self.modelOnlyViewpointOnSelector.addEnabled = False
    self.modelOnlyViewpointOnSelector.removeEnabled = False
    self.modelOnlyViewpointOnSelector.setMRMLScene( slicer.mrmlScene )
    self.modelOnlyViewpointOnSelector.setToolTip("This model be visible if Viewpoint mode is enabled, and invisible otherwise")
    self.modelVisibilityFormLayout.addRow(self.modelOnlyViewpointOnLabel,self.modelOnlyViewpointOnSelector)
    
    self.modelOnlyViewpointOffLabel = qt.QLabel(qt.Qt.Horizontal,None)
    self.modelOnlyViewpointOffLabel.text = "Model visible only for Viewpoint off: "
    self.modelOnlyViewpointOffSelector = slicer.qMRMLNodeComboBox()
    self.modelOnlyViewpointOffSelector.nodeTypes = ( ("vtkMRMLModelNode"), "" )
    self.modelOnlyViewpointOffSelector.noneEnabled = True
    self.modelOnlyViewpointOffSelector.addEnabled = False
    self.modelOnlyViewpointOffSelector.removeEnabled = False
    self.modelOnlyViewpointOffSelector.setMRMLScene( slicer.mrmlScene )
    self.modelOnlyViewpointOffSelector.setToolTip("This model be visible if Viewpoint Mode is disabled, and invisible otherwise")
    self.modelVisibilityFormLayout.addRow(self.modelOnlyViewpointOffLabel,self.modelOnlyViewpointOffSelector)
    
    # Camera parallel projection checkbox
    self.cameraParallelProjectionLabel = qt.QLabel()
    self.cameraParallelProjectionLabel.setText("Parallel Projection")
    self.cameraParallelProjectionCheckbox = qt.QCheckBox()
    self.cameraParallelProjectionCheckbox.setCheckState(0)
    self.cameraParallelProjectionCheckbox.setToolTip("If checked, render with parallel projection (box-shaped view). Otherwise render with perspective projection (cone-shaped view).")
    self.cameraControlFormLayout.addRow(self.cameraParallelProjectionLabel,self.cameraParallelProjectionCheckbox)
    
    # "Toggle Tool Point of View" button
    self.enableViewpointButton = qt.QPushButton()
    self.enableViewpointButton.setToolTip("The camera will continuously update its position so that it follows the tool.")
    self.enableViewpointButton.setText(self.enableViewpointButtonTextState0)
    self.cameraControlFormLayout.addRow(self.enableViewpointButton)
    
    #Connections
    self.enableViewpointButton.connect('clicked()', self.enableViewpointButtonPressed)
    self.cameraParallelProjectionCheckbox.connect('stateChanged(int)', self.toggleCameraParallelProjectionCheckboxPressed)
    self.cameraViewAngleSlider.connect('valueChanged(double)', self.logic.SetCameraViewAngleDeg)
    self.cameraParallelScaleSlider.connect('valueChanged(double)', self.logic.SetCameraParallelScale)
    self.cameraXPosSlider.connect('valueChanged(double)', self.logic.SetCameraXPosMm)
    self.cameraYPosSlider.connect('valueChanged(double)', self.logic.SetCameraYPosMm)
    self.cameraZPosSlider.connect('valueChanged(double)', self.logic.SetCameraZPosMm)
    self.upDirectionAnteriorRadioButton.connect('clicked()', self.changeUpToAnterior)
    self.upDirectionPosteriorRadioButton.connect('clicked()', self.changeUpToPosterior)
    self.upDirectionLeftRadioButton.connect('clicked()', self.changeUpToLeft)
    self.upDirectionRightRadioButton.connect('clicked()', self.changeUpToRight)
    self.upDirectionSuperiorRadioButton.connect('clicked()', self.changeUpToSuperior)
    self.upDirectionInferiorRadioButton.connect('clicked()', self.changeUpToInferior)
    self.degreesOfFreedom3RadioButton.connect('clicked()', self.changeInterfaceTo3DOFMode)
    self.degreesOfFreedom5RadioButton.connect('clicked()', self.changeInterfaceTo5DOFMode)
    self.degreesOfFreedom6RadioButton.connect('clicked()', self.changeInterfaceTo6DOFMode)
    
    # Add vertical spacer
    self.layout.addStretch(1)
Example #8
0
    def setup(self):
        # Instantiate and connect widgets ...

        # Status text
        statusCollapsibleButton = ctk.ctkCollapsibleButton()
        statusCollapsibleButton.text = "Status"
        self.layout.addWidget(statusCollapsibleButton)
        self.statusFormLayout = qt.QFormLayout(statusCollapsibleButton)

        self.overallStatus = qt.QLabel()
        self.overallStatus.text = "Idle"
        self.statusFormLayout.addRow("New Process:", self.overallStatus)

        self.processes = list()
        #
        # Volumes
        #
        self.inputImagesCollapsibleButton = ctk.ctkCollapsibleButton()
        self.inputImagesCollapsibleButton.text = "Input Images"
        self.layout.addWidget(self.inputImagesCollapsibleButton)

        # Layout within the collapsible button
        inputImagesFormLayout = qt.QFormLayout(self.inputImagesCollapsibleButton)

        # input volume selector
        self.fixedVolumeSelector = slicer.qMRMLNodeComboBox()
        self.fixedVolumeSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.fixedVolumeSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", 0)
        self.fixedVolumeSelector.selectNodeUponCreation = True
        self.fixedVolumeSelector.addEnabled = True
        self.fixedVolumeSelector.removeEnabled = True
        self.fixedVolumeSelector.noneEnabled = False
        self.fixedVolumeSelector.showHidden = False
        self.fixedVolumeSelector.showChildNodeTypes = False
        self.fixedVolumeSelector.setMRMLScene(slicer.mrmlScene)
        self.fixedVolumeSelector.setToolTip("Pick the fixed input to the algorithm.")
        inputImagesFormLayout.addRow("Fixed Image Volume: ", self.fixedVolumeSelector)

        # Moving volume selector

        self.movingVolumeSelector = slicer.qMRMLCheckableNodeComboBox()

        # self.movingVolumeSelector = slicer.qMRMLNodeComboBox()
        self.movingVolumeSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.movingVolumeSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", 0)
        self.movingVolumeSelector.selectNodeUponCreation = True
        self.movingVolumeSelector.addEnabled = True
        self.movingVolumeSelector.removeEnabled = True
        self.movingVolumeSelector.noneEnabled = False
        self.movingVolumeSelector.showHidden = False
        self.movingVolumeSelector.showChildNodeTypes = False
        self.movingVolumeSelector.setMRMLScene(slicer.mrmlScene)
        self.movingVolumeSelector.setToolTip("Pick the moving volume to the algorithm.")
        inputImagesFormLayout.addRow("Moving Volume: ", self.movingVolumeSelector)

        #
        # Crop parameters
        #
        self.cropParametersCollapsibleButton = ctk.ctkCollapsibleButton()
        self.cropParametersCollapsibleButton.text = "Crop Parameters"
        self.layout.addWidget(self.cropParametersCollapsibleButton)
        cropParametersFormLayout = qt.QFormLayout(self.cropParametersCollapsibleButton)
        cropParametersFormLayout

        # Input ROI
        self.annotationROISelector = slicer.qMRMLNodeComboBox()
        self.annotationROISelector.nodeTypes = (("vtkMRMLAnnotationROINode"), "")
        self.annotationROISelector.editEnabled = True
        self.annotationROISelector.renameEnabled = True
        self.annotationROISelector.setMRMLScene(slicer.mrmlScene)
        self.annotationROISelector.setToolTip("Pick the fixed input to the algorithm.")
        cropParametersFormLayout.addRow("Input ROI: ", self.annotationROISelector)

        # ROI Visibility
        self.ROIVisibilityButton = qt.QToolButton()
        visibilityIcon = qt.QIcon()
        visibilityIcon.addPixmap(qt.QPixmap(":/Icons/VisibleOff.png"), qt.QIcon().Normal, qt.QIcon().Off)
        visibilityIcon.addPixmap(qt.QPixmap(":/Icons/VisibleOn.png"), qt.QIcon().Normal, qt.QIcon().On)
        self.ROIVisibilityButton.setIcon(visibilityIcon)
        self.ROIVisibilityButton.setCheckable(True)
        cropParametersFormLayout.addRow("Visibility ROI:", self.ROIVisibilityButton)

        # Cropping technique
        croppingTechniqueLayout = qt.QHBoxLayout()
        self.interpolationButton = qt.QRadioButton("Interpolated cropping")
        self.interpolationButton.setChecked(True)
        self.voxelBasedButton = qt.QRadioButton("Voxel based cropping")
        croppingTechniqueLayout.addWidget(self.interpolationButton)
        croppingTechniqueLayout.addWidget(self.voxelBasedButton)
        cropParametersFormLayout.addRow("Technique: ", croppingTechniqueLayout)

        # Interpolation options
        self.interpolationOptionsCollapsibleGroupBox = ctk.ctkCollapsibleGroupBox()
        self.interpolationOptionsCollapsibleGroupBox.title = "Interpolation options"
        cropParametersFormLayout.addRow("", self.interpolationOptionsCollapsibleGroupBox)
        interpolationOptionsLayout = qt.QFormLayout(self.interpolationOptionsCollapsibleGroupBox)
        interpolationOptionsLayout.setFieldGrowthPolicy(qt.QFormLayout().ExpandingFieldsGrow)
        interpolationOptionsLayout.setRowWrapPolicy(qt.QFormLayout().WrapLongRows)

        # Isotropic
        self.isotropicCheckBox = qt.QCheckBox()
        self.isotropicCheckBox.checked = True
        interpolationOptionsLayout.addRow("Isotropic output voxel", self.isotropicCheckBox)

        # Input spacing scaling constant
        self.inputSpacingScaling = qt.QDoubleSpinBox()
        self.inputSpacingScaling.setToolTip(
            "In not equal to 1, this will result in upsampling (<1) or downlsampling (>1) relative to the voxel spacing of the input volume."
        )
        self.inputSpacingScaling.value = 1.000000
        interpolationOptionsLayout.addRow("Input spacing scaling constant: ", self.inputSpacingScaling)

        # Interpolator technique
        interpolatorWidget = qt.QWidget()
        sizep = qt.QSizePolicy()
        sizep.setHorizontalPolicy(qt.QSizePolicy().Expanding)
        sizep.setVerticalPolicy(qt.QSizePolicy().Preferred)
        sizep.setHorizontalStretch(0)
        sizep.setVerticalStretch(0)
        interpolatorWidget.setSizePolicy(sizep)
        interpolatorLayout = qt.QGridLayout(interpolatorWidget)
        interpolationOptionsLayout.addRow("Technique: ", interpolatorWidget)
        self.iNNButton = qt.QRadioButton("Nearest Neighbor")
        self.iLinearButton = qt.QRadioButton("Linear")
        self.iWindowedSincButton = qt.QRadioButton("WindowedSinc")
        self.iBSplineButton = qt.QRadioButton("B-spline")
        self.iNNButton.setSizePolicy(qt.QSizePolicy().Minimum, qt.QSizePolicy().Preferred)
        self.iLinearButton.setSizePolicy(qt.QSizePolicy().MinimumExpanding, qt.QSizePolicy().Preferred)
        self.iWindowedSincButton.setSizePolicy(qt.QSizePolicy().Minimum, qt.QSizePolicy().Preferred)
        self.iBSplineButton.setSizePolicy(qt.QSizePolicy().MinimumExpanding, qt.QSizePolicy().Preferred)
        self.iLinearButton.setChecked(True)
        interpolatorLayout.addWidget(self.iNNButton, 0, 0)
        interpolatorLayout.addWidget(self.iLinearButton, 0, 1)
        interpolatorLayout.addWidget(self.iWindowedSincButton, 1, 0)
        interpolatorLayout.addWidget(self.iBSplineButton, 1, 1)

        #
        # Crop Button
        #
        self.cropButton = qt.QPushButton("Crop")
        self.cropButton.toolTip = "Crop the fixed volume."
        self.cropButton.enabled = False
        self.layout.addWidget(self.cropButton)

        # Align and crop
        self.alignAndCropButton = qt.QPushButton("Align and Crop")
        self.alignAndCropButton.toolTip = "Align moving volumes with fixed volume and crop all the images"
        self.alignAndCropButton.enabled = False
        self.layout.addWidget(self.alignAndCropButton)

        self.layout.addStretch(1)

        self.cropParametersNode = slicer.modulemrml.vtkMRMLCropVolumeParametersNode()

        self.onFixedVolumeSelect()
        self.onMovingVolumeSelect()
        self.onAnnotationROIChanged()
        self.onROIVisibilityChanged()

        # connections
        self.cropButton.connect("clicked(bool)", self.onCrop)
        self.alignAndCropButton.connect("clicked(bool)", self.onAlignAndCrop)
        self.fixedVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onFixedVolumeSelect)
        self.movingVolumeSelector.connect("checkedNodesChanged(void)", self.onMovingVolumeSelect)
        self.annotationROISelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onAnnotationROIChanged)
        self.ROIVisibilityButton.connect("toggled(bool)", self.onROIVisibilityChanged)
        self.voxelBasedButton.connect("clicked(bool)", self.onVoxelBasedButtonClicked)
        self.interpolationButton.connect("clicked(bool)", self.onInterpolationButtonClicked)

        # Display current fixed node
        self.displayFixedVolume()

        self.updateCropParameters()

        self.outputNodes = dict()
        self.nreg_completed = 0
  def setup(self):
    self.pointRecorderLogic = PointRecorderLogic() 
  
    ScriptedLoadableModuleWidget.setup(self)

    # Instantiate and connect widgets ...

    # Icons stuff
    self.moduleDirectoryPath = slicer.modules.pointrecorder.path.replace("PointRecorder.py","")
    self.playIcon = qt.QIcon(self.moduleDirectoryPath + '/Resources/Icons/playIcon.png')
    self.stopIcon = qt.QIcon(self.moduleDirectoryPath + '/Resources/Icons/stopIcon.png')
    self.recordIcon = qt.QIcon(self.moduleDirectoryPath + '/Resources/Icons/recordIcon.png')
    self.restartIcon = qt.QIcon(self.moduleDirectoryPath + '/Resources/Icons/restartIcon.png')
    self.saveIcon = qt.QIcon(self.moduleDirectoryPath + '/Resources/Icons/saveIcon.png')                             
    
    #
    # Parameters Area
    #
    parametersCollapsibleButton = ctk.ctkCollapsibleButton()
    parametersCollapsibleButton.text = "Parameters"
    self.layout.addWidget(parametersCollapsibleButton)

    # Layout within the dummy collapsible button
    parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton)

    #
    # input transform selector
    #
    self.inputSelector = slicer.qMRMLNodeComboBox()
    self.inputSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.inputSelector.selectNodeUponCreation = True
    self.inputSelector.addEnabled = False
    self.inputSelector.removeEnabled = False
    self.inputSelector.noneEnabled = False
    self.inputSelector.showChildNodeTypes = False
    self.inputSelector.setMRMLScene( slicer.mrmlScene )
    self.inputSelector.setToolTip( "Pick the input to the algorithm." )
    parametersFormLayout.addRow("Modified Transform: ", self.inputSelector)

        #
    # input transform selector
    #
    self.fixedSelector = slicer.qMRMLNodeComboBox()
    self.fixedSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.fixedSelector.selectNodeUponCreation = True
    self.fixedSelector.addEnabled = False
    self.fixedSelector.removeEnabled = False
    self.fixedSelector.noneEnabled = False
    self.fixedSelector.showChildNodeTypes = False
    self.fixedSelector.setMRMLScene( slicer.mrmlScene )
    self.fixedSelector.setToolTip( "Pick the input to the algorithm." )
    parametersFormLayout.addRow("Spatial Transform: ", self.fixedSelector)
    
     # Controls
    self.controlsGroupBox = ctk.ctkCollapsibleGroupBox()
    self.controlsGroupBox.setTitle("Controls")
    controlsFormLayout = qt.QFormLayout(self.controlsGroupBox)
    parametersFormLayout.addRow(self.controlsGroupBox)
    
    hBoxLayoutControls = qt.QHBoxLayout()
    controlsFormLayout.addRow(hBoxLayoutControls)

    self.recordButton = qt.QPushButton(" Record")
    self.recordButton.setIcon(self.recordIcon)
    self.recordButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    self.recordButton.enabled = False
    self.recordButton.checkable = True
    hBoxLayoutControls.addWidget(self.recordButton)

    self.saveButton = qt.QPushButton(" Save")
    self.saveButton.setIcon(self.saveIcon)
    self.saveButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    self.saveButton.enabled = False
    hBoxLayoutControls.addWidget(self.saveButton)
    
    self.resetButton = qt.QPushButton(" Reset")
    self.resetButton.setIcon(self.restartIcon)
    self.resetButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    self.resetButton.enabled = False
    hBoxLayoutControls.addWidget(self.resetButton)
    
    hBoxCheckBoxes = qt.QHBoxLayout()
    controlsFormLayout.addRow(hBoxCheckBoxes)

    self.singlePointCheckBox = qt.QCheckBox('Single Measurements')
    self.singlePointCheckBox.checked = False
    self.singlePointCheckBox.enabled = False
    hBoxCheckBoxes.addWidget(self.singlePointCheckBox)  
    
    # connections
    self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.recordButton.connect('clicked(bool)', self.onRecordClicked)
    self.resetButton.connect('clicked(bool)', self.onResetClicked)
    self.saveButton.connect('clicked(bool)', self.onSaveClicked)
    
    # Add vertical spacer
    self.layout.addStretch(1)

    # Refresh Apply button state
    self.onSelect()

    self.pointRecorderLogic.setLayout()
Example #10
0
    def setupNavigationPanel(self):
        logging.debug('setupNavigationPanel')

        self.sliderTranslationDefaultMm = 0
        self.sliderTranslationMinMm = -500
        self.sliderTranslationMaxMm = 500
        self.sliderViewAngleDefaultDeg = 30
        self.cameraViewAngleMinDeg = 5.0  # maximum magnification
        self.cameraViewAngleMaxDeg = 150.0  # minimum magnification

        self.sliderSingleStepValue = 1
        self.sliderPageStepValue = 10

        self.navigationCollapsibleButton.setProperty('collapsedHeight', 20)
        setButtonStyle(self.navigationCollapsibleButton, 2.0)
        self.navigationCollapsibleButton.text = "Navigation"
        self.sliceletPanelLayout.addWidget(self.navigationCollapsibleButton)

        self.navigationCollapsibleLayout = qt.QFormLayout(
            self.navigationCollapsibleButton)
        self.navigationCollapsibleLayout.setContentsMargins(12, 4, 4, 4)
        self.navigationCollapsibleLayout.setSpacing(4)

        self.rightCameraButton = qt.QPushButton("Setup right camera")
        self.rightCameraButton.setCheckable(True)
        setButtonStyle(self.rightCameraButton)

        self.leftCameraButton = qt.QPushButton("Setup left camera")
        self.leftCameraButton.setCheckable(True)
        setButtonStyle(self.leftCameraButton)

        hbox = qt.QHBoxLayout()
        hbox.addWidget(self.leftCameraButton)
        hbox.addWidget(self.rightCameraButton)
        self.navigationCollapsibleLayout.addRow(hbox)

        # "Camera Control" Collapsible
        self.zoomCollapsibleButton = ctk.ctkCollapsibleGroupBox()
        self.zoomCollapsibleButton.collapsed = True
        self.zoomCollapsibleButton.title = "Zoom"
        self.navigationCollapsibleLayout.addRow(self.zoomCollapsibleButton)

        # Layout within the collapsible button
        self.zoomFormLayout = qt.QFormLayout(self.zoomCollapsibleButton)

        # Camera distance to focal point slider
        self.cameraViewAngleLabel = qt.QLabel(qt.Qt.Horizontal, None)
        self.cameraViewAngleLabel.setText("Field of view [degrees]: ")
        self.cameraViewAngleSlider = slicer.qMRMLSliderWidget()
        self.cameraViewAngleSlider.minimum = self.cameraViewAngleMinDeg
        self.cameraViewAngleSlider.maximum = self.cameraViewAngleMaxDeg
        self.cameraViewAngleSlider.value = self.sliderViewAngleDefaultDeg
        self.cameraViewAngleSlider.singleStep = self.sliderSingleStepValue
        self.cameraViewAngleSlider.pageStep = self.sliderPageStepValue
        self.cameraViewAngleSlider.setDisabled(True)
        self.zoomFormLayout.addRow(self.cameraViewAngleLabel,
                                   self.cameraViewAngleSlider)

        # "Camera Control" Collapsible
        self.translationCollapsibleButton = ctk.ctkCollapsibleGroupBox()
        self.translationCollapsibleButton.title = "Translation"
        self.translationCollapsibleButton.collapsed = True
        self.navigationCollapsibleLayout.addRow(
            self.translationCollapsibleButton)

        # Layout within the collapsible button
        self.translationFormLayout = qt.QFormLayout(
            self.translationCollapsibleButton)

        self.cameraXPosLabel = qt.QLabel(qt.Qt.Horizontal, None)
        self.cameraXPosLabel.text = "Left/Right [mm]: "
        self.cameraXPosSlider = slicer.qMRMLSliderWidget()
        setButtonStyle(self.cameraXPosSlider)
        self.cameraXPosSlider.minimum = self.sliderTranslationMinMm
        self.cameraXPosSlider.maximum = self.sliderTranslationMaxMm
        self.cameraXPosSlider.value = self.sliderTranslationDefaultMm
        self.cameraXPosSlider.singleStep = self.sliderSingleStepValue
        self.cameraXPosSlider.pageStep = self.sliderPageStepValue
        self.cameraXPosSlider.setDisabled(True)
        self.translationFormLayout.addRow(self.cameraXPosLabel,
                                          self.cameraXPosSlider)

        self.cameraYPosLabel = qt.QLabel(qt.Qt.Horizontal, None)
        self.cameraYPosLabel.setText("Down/Up [mm]: ")
        self.cameraYPosSlider = slicer.qMRMLSliderWidget()
        setButtonStyle(self.cameraYPosSlider)
        self.cameraYPosSlider.minimum = self.sliderTranslationMinMm
        self.cameraYPosSlider.maximum = self.sliderTranslationMaxMm
        self.cameraYPosSlider.value = self.sliderTranslationDefaultMm
        self.cameraYPosSlider.singleStep = self.sliderSingleStepValue
        self.cameraYPosSlider.pageStep = self.sliderPageStepValue
        self.cameraYPosSlider.setDisabled(True)
        self.translationFormLayout.addRow(self.cameraYPosLabel,
                                          self.cameraYPosSlider)

        self.cameraZPosLabel = qt.QLabel(qt.Qt.Horizontal, None)
        self.cameraZPosLabel.setText("Front/Back [mm]: ")
        self.cameraZPosSlider = slicer.qMRMLSliderWidget()
        setButtonStyle(self.cameraZPosSlider)
        self.cameraZPosSlider.minimum = self.sliderTranslationMinMm
        self.cameraZPosSlider.maximum = self.sliderTranslationMaxMm
        self.cameraZPosSlider.value = self.sliderTranslationDefaultMm
        self.cameraZPosSlider.singleStep = self.sliderSingleStepValue
        self.cameraZPosSlider.pageStep = self.sliderPageStepValue
        self.cameraZPosSlider.setDisabled(True)
        self.translationFormLayout.addRow(self.cameraZPosLabel,
                                          self.cameraZPosSlider)

        # "Contour adjustment" Collapsible
        self.contourAdjustmentCollapsibleButton = ctk.ctkCollapsibleGroupBox()
        self.contourAdjustmentCollapsibleButton.title = "Contour adjustment"
        self.contourAdjustmentCollapsibleButton.collapsed = True
        self.navigationCollapsibleLayout.addRow(
            self.contourAdjustmentCollapsibleButton)

        # Layout within the collapsible button
        self.contourAdjustmentFormLayout = qt.QFormLayout(
            self.contourAdjustmentCollapsibleButton)

        self.placeTumorPointAtCauteryTipButton = qt.QPushButton(
            "Mark point at cautery tip")
        setButtonStyle(self.placeTumorPointAtCauteryTipButton)
        self.contourAdjustmentFormLayout.addRow(
            self.placeTumorPointAtCauteryTipButton)

        self.deleteLastFiducialDuringNavigationButton = qt.QPushButton(
            "Delete last")
        self.deleteLastFiducialDuringNavigationButton.setIcon(
            qt.QIcon(":/Icons/MarkupsDelete.png"))
        setButtonStyle(self.deleteLastFiducialDuringNavigationButton)
        self.deleteLastFiducialDuringNavigationButton.setEnabled(False)
        self.contourAdjustmentFormLayout.addRow(
            self.deleteLastFiducialDuringNavigationButton)
Example #11
0
  def setup(self):
    self.logic = BoneEnhancerPyLogic()

    ScriptedLoadableModuleWidget.setup(self)
    
    ############################################################ Define algorithms    
    self.example = AlgorithmParams("Example Algorithm",
              {"1st Parameter" : (1, 1, 1, 1, 0.5, "1st parameter toolTip"),
               "2nd Parameter" : (0, 1, 0, 10, 5, "2nd parameter toolTip"),
               "3rd Parameter" : (1, 1, 1, 100, 50, "3rd parameter toolTip")})
               
    self.foroughi2007 = AlgorithmParams("Foroughi2007 (with minor modifications)",
              {"Smoothing Sigma" : (1, 1, 1, 10, 5.0, "Smoothing Sigma ToolTip"),
               "Transducer Margin" : (0, 1, 0, 300, 60, "Transducer Margin ToolTip"),
               "Shadow Sigma" : (1, 1, 1, 10, 6.0, "Shadow Sigma ToolTip"),
               "Bone Threshold" : (1, 0.1, 0, 1, 0.4, "Bone Threshold ToolTip"),
               "Blurred vs. BLoG" : (1, 0.1, 0, 10, 3, "Blurred vs. BLoG ToolTip"),
               "Shadow vs. Intensity" : (1, 0.1, 0, 10, 5, "Shadow vs. Intensity ToolTip")})

    self.algorithms = (self.example, self.foroughi2007)
    
    # Set default algorithm
    self.defaultAlgorithm = self.foroughi2007
    
    ############################################################ BoneEnhancer
    boneEnhancerCollapsibleButton = ctk.ctkCollapsibleButton()
    boneEnhancerCollapsibleButton.text = "BoneEnhancer"
    self.layout.addWidget(boneEnhancerCollapsibleButton)
    boneEnhancerFormLayout = qt.QFormLayout(boneEnhancerCollapsibleButton)

    self.ultrasoundImageSelector = slicer.qMRMLNodeComboBox()
    self.ultrasoundImageSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
    self.ultrasoundImageSelector.addAttribute( "vtkMRMLScalarVolumeNode", "LabelMap", 0 )
    self.ultrasoundImageSelector.selectNodeUponCreation = True
    self.ultrasoundImageSelector.addEnabled = False
    self.ultrasoundImageSelector.removeEnabled = False
    self.ultrasoundImageSelector.noneEnabled = False
    self.ultrasoundImageSelector.showHidden = False
    self.ultrasoundImageSelector.showChildNodeTypes = False
    self.ultrasoundImageSelector.setMRMLScene( slicer.mrmlScene )
    self.ultrasoundImageSelector.setToolTip( "Pick the input to the algorithm." )
    boneEnhancerFormLayout.addRow("Ultrasound Image: ", self.ultrasoundImageSelector)

    # Select algorithm
    self.algorithmGroupBox = ctk.ctkCollapsibleGroupBox()
    self.algorithmGroupBox.setTitle("Select Algorithm")
    algorithmFormLayout = qt.QFormLayout(self.algorithmGroupBox)
    boneEnhancerFormLayout.addRow(self.algorithmGroupBox)

    for algorithm in self.algorithms:     
      algorithmFormLayout.addRow(algorithm.GetRadioButton())
      algorithm.GetRadioButton().connect("toggled(bool)", self.onRadioButtonPressed)
      
    # Parameters
    self.parametersGroupBox = ctk.ctkCollapsibleGroupBox()
    self.parametersGroupBox.setTitle("Parameters")
    self.parametersFormLayout = qt.QFormLayout(self.parametersGroupBox)
    boneEnhancerFormLayout.addRow(self.parametersGroupBox)
    
    for algorithm in self.algorithms:     
      self.parametersFormLayout.addWidget(algorithm.getSliderWidget())
      algorithm.paramChangedCallback = self.onParameterChanged
                  
    # Runtime
    self.runtimeGroupBox = ctk.ctkCollapsibleGroupBox()
    self.runtimeGroupBox.setTitle("Runtime")
    runtimeFormLayout = qt.QFormLayout(self.runtimeGroupBox)
    boneEnhancerFormLayout.addRow(self.runtimeGroupBox)
    
    self.runtimeLabel = qt.QLabel()
    self.runtimeLabel.setText("... s.")
    self.runtimeLabel.setWordWrap(True)
    self.runtimeLabel.setStyleSheet("QLabel { background-color : black; \
                                           color : #66FF00; \
                                           height : 60px; \
                                           border-style: outset; \
                                           border-width: 5px; \
                                           border-radius: 10px; \
                                           font: bold 14px; \
                                           padding: 0px;\
                                           font-family : SimSun; \
                                           qproperty-alignment: AlignCenter}")
    runtimeFormLayout.addRow(self.runtimeLabel)
    
    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.toolTip = "Run the algorithm."
    self.applyButton.enabled = False
    self.applyButton.checkable = True
    boneEnhancerFormLayout.addRow(self.applyButton)
       
    ############################################################ Connections
    self.applyButton.connect('clicked(bool)', self.onApplyButton)
    self.ultrasoundImageSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    
    self.layout.addStretch(1)    
    self.defaultAlgorithm.GetRadioButton().checked = True
    self.onSelect()
    
    self.ModuleLayoutID = -1    
    self.setModuleLayout()
    def setup(self):
        #Instantiate and Connect Widgets
        #################################################
        #HeterogeneityCAD Inputs Collapsible Button

        self.inputHeterogeneityCADCollapsibleButton = ctk.ctkCollapsibleButton(
        )
        self.inputHeterogeneityCADCollapsibleButton.text = "HeterogeneityCAD Input"
        self.layout.addWidget(self.inputHeterogeneityCADCollapsibleButton)
        self.inputHeterogeneityCADLayout = qt.QFormLayout(
            self.inputHeterogeneityCADCollapsibleButton)

        ##Input Volume as a PET/CT/MRI image or parameter map converted to a volume
        self.inputVolHetFrame = qt.QFrame(
            self.inputHeterogeneityCADCollapsibleButton)
        self.inputVolHetFrame.setLayout(qt.QHBoxLayout())
        self.inputHeterogeneityCADLayout.addRow(self.inputVolHetFrame)
        # label for selecting individual node
        self.inputVolHet = qt.QLabel("Input Node: ", self.inputVolHetFrame)
        self.inputVolHetFrame.layout().addWidget(self.inputVolHet)
        # select individual nodes
        self.inputSelectorVolHet = slicer.qMRMLNodeComboBox(
            self.inputVolHetFrame)
        self.inputSelectorVolHet.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.inputSelectorVolHet.selectNodeUponCreation = False
        self.inputSelectorVolHet.addEnabled = False
        self.inputSelectorVolHet.removeEnabled = False
        self.inputSelectorVolHet.setMRMLScene(slicer.mrmlScene)
        self.inputVolHetFrame.layout().addWidget(self.inputSelectorVolHet)
        # add Data Node button
        self.addDataNodeButton = qt.QPushButton("Add Node",
                                                self.inputVolHetFrame)
        self.addDataNodeButton.objectName = 'AddDataNodeButton'
        self.addDataNodeButton.setToolTip("Add a Node to Queue")
        self.addDataNodeButton.connect('clicked()',
                                       self.onAddDataNodeButtonClicked)
        self.inputVolHetFrame.layout().addWidget(self.addDataNodeButton)

        ## data nodes Frame
        self.dataNodesFrame = ctk.ctkCollapsibleGroupBox(
            self.inputHeterogeneityCADCollapsibleButton)
        self.dataNodesFrame.title = "Nodes List"
        self.dataNodesFrame.collapsed = False
        self.dataNodesFrame.setLayout(qt.QVBoxLayout())
        # all buttons frame
        self.allButtonsFrame = qt.QFrame(
            self.inputHeterogeneityCADCollapsibleButton)
        self.allButtonsFrame.objectName = 'AllButtonsFrameButton'
        self.allButtonsFrame.setLayout(qt.QVBoxLayout())
        self.inputHeterogeneityCADLayout.addRow(self.dataNodesFrame,
                                                self.allButtonsFrame)
        # Data Nodes view
        # Use list view here with scroll area widget.
        self.dataScrollArea = qt.QScrollArea()
        self.dataNodesListWidget = qt.QListWidget()
        self.dataNodesListWidget.name = 'dataNodesListWidget'
        self.dataScrollArea.setWidget(self.dataNodesListWidget)
        self.dataNodesListWidget.resize(350, 100)
        self.dataNodesFrame.layout().addWidget(self.dataScrollArea)
        #self.listWidget.setProperty('SH_ItemView_ActivateItemOnSingleClick', 1)
        #self.listWidget.connect('activated(QModelIndex)', self.onActivated)
        # add all Data Nodes from scene button
        self.addAllDataNodesButton = qt.QPushButton("Add All Nodes From Scene",
                                                    self.allButtonsFrame)
        self.addAllDataNodesButton.objectName = 'AddAllDataNodesButton'
        self.addAllDataNodesButton.setToolTip(
            "Add all Nodes from the Scene to Queue")
        self.addAllDataNodesButton.connect('clicked()',
                                           self.onAddAllDataNodesButtonClicked)
        self.allButtonsFrame.layout().addWidget(self.addAllDataNodesButton)
        # remove single Data Node
        self.removeDataNodeButton = qt.QPushButton("Remove Node",
                                                   self.allButtonsFrame)
        self.removeDataNodeButton.objectName = 'RemoveDataNodeButton'
        self.removeDataNodeButton.setToolTip(
            "Removes Selected Node from the Queue.")
        self.removeDataNodeButton.connect('clicked()',
                                          self.onRemoveDataNodeButtonClicked)
        self.allButtonsFrame.layout().addWidget(self.removeDataNodeButton)
        # remove all Data Nodes button
        self.removeAllDataNodesButton = qt.QPushButton("Remove All Nodes",
                                                       self.allButtonsFrame)
        self.removeAllDataNodesButton.objectName = 'RemoveAllDataNodesButton'
        self.removeAllDataNodesButton.setToolTip(
            "Removes All Nodes from the Queue.")
        self.removeAllDataNodesButton.connect(
            'clicked()', self.onRemoveAllDataNodesButtonClicked)
        self.allButtonsFrame.layout().addWidget(self.removeAllDataNodesButton)

        # Use Label Map as ROI(segmentation output or user-selected ROI)
        self.inputLabelROIFrame = qt.QFrame(
            self.inputHeterogeneityCADCollapsibleButton)
        self.inputLabelROIFrame.setLayout(qt.QHBoxLayout())
        self.inputHeterogeneityCADLayout.addRow(self.inputLabelROIFrame)
        # Enable Input Label Map as ROI
        self.inputLabelROI = qt.QLabel("Label Map ROI: ",
                                       self.inputLabelROIFrame)
        self.inputLabelROIFrame.layout().addWidget(self.inputLabelROI)
        # Select Input Label Map as ROI
        self.inputSelectorLabel = slicer.qMRMLNodeComboBox(
            self.inputLabelROIFrame)
        self.inputSelectorLabel.nodeTypes = (("vtkMRMLLabelMapVolumeNode"), "")
        self.inputSelectorLabel.selectNodeUponCreation = False
        self.inputSelectorLabel.renameEnabled = True
        self.inputSelectorLabel.removeEnabled = False
        self.inputSelectorLabel.noneEnabled = True
        self.inputSelectorLabel.addEnabled = False
        self.inputSelectorLabel.setMRMLScene(slicer.mrmlScene)
        self.inputLabelROIFrame.layout().addWidget(self.inputSelectorLabel)

        #End HeterogeneityCAD Inputs Collapsible Button
        #################################################
        #HeterogeneityCAD Features Collapsible Button

        self.HeterogeneityCADCollapsibleButton = ctk.ctkCollapsibleButton()
        self.HeterogeneityCADCollapsibleButton.text = "HeterogeneityCAD Features Selection"
        self.layout.addWidget(self.HeterogeneityCADCollapsibleButton)
        self.featuresHeterogeneityCADLayout = qt.QFormLayout(
            self.HeterogeneityCADCollapsibleButton)

        # auto-generate QTabWidget Tabs and QCheckBoxes (subclassed in FeatureWidgetHelperLib)
        self.tabsFeatureClasses = FeatureWidgetHelperLib.CheckableTabWidget()
        self.featuresHeterogeneityCADLayout.addRow(self.tabsFeatureClasses)

        gridWidth, gridHeight = 3, 9
        for featureClass in self.featureClassKeys:
            # by default, features from the following features classes are checked:
            if featureClass in [
                    "Node Information", "First-Order Statistics",
                    "Morphology and Shape", "Texture: GLCM", "Texture: GLRL"
            ]:
                check = True
            else:
                check = False
            tabFeatureClass = qt.QWidget()
            tabFeatureClass.setLayout(qt.QGridLayout())
            #featureList = (feature for feature in self.featureClassKeys[featureClass])
            gridLayoutCoordinates = ((row, col) for col in range(gridWidth)
                                     for row in range(gridHeight))
            for featureName in self.featureClassKeys[featureClass]:
                row, col = next(gridLayoutCoordinates, None)
                if featureName is None or row is None or col is None:
                    break
                featureCheckboxWidget = FeatureWidgetHelperLib.FeatureWidget()
                featureCheckboxWidget.Setup(featureName=featureName,
                                            checkStatus=check)

                tabFeatureClass.layout().addWidget(featureCheckboxWidget, row,
                                                   col)
                self.featureWidgets[featureClass].append(featureCheckboxWidget)
            self.tabsFeatureClasses.addTab(tabFeatureClass,
                                           featureClass,
                                           self.featureWidgets[featureClass],
                                           checkStatus=check)

        self.tabsFeatureClasses.setCurrentIndex(1)

        # note: try using itertools list merging with lists of GLRL diagonal
        self.heterogeneityFeatureWidgets = list(
            itertools.chain.from_iterable(self.featureWidgets.values()))
        self.classes = list(self.featureWidgets.keys())
        # or reduce(lambda x,y: x+y, self.featureWidgets.values())

        ########## Parameter options
        # add parameters for top-level feature classes
        self.tabsFeatureClasses.addParameter("Geometrical Measures",
                                             "Extrusion Parameter 1")
        self.tabsFeatureClasses.addParameter("Texture: GLCM",
                                             "GLCM Matrix Parameter 1")
        self.tabsFeatureClasses.addParameter("Texture: GLRL",
                                             "GLRL Matrix Parameter 1")

        # compile dict of feature classes with parameter names and values
        self.featureClassParametersDict = collections.OrderedDict()
        for featureClassWidget in self.tabsFeatureClasses.getFeatureClassWidgets(
        ):
            featureClassName = featureClassWidget.getName()
            self.featureClassParametersDict[
                featureClassName] = collections.OrderedDict()
            self.updateFeatureClassParameterDict(0, featureClassWidget)
            for parameterName in featureClassWidget.widgetMenu.parameters:
                featureClassWidget.getParameterEditWindow(
                    parameterName).connect(
                        'intValueChanged(int)',
                        lambda intValue, featureClassWidget=featureClassWidget:
                        self.updateFeatureClassParameterDict(
                            intValue, featureClassWidget))

        # add parameters for individual features
        for featureWidget in self.heterogeneityFeatureWidgets:
            if featureWidget.getName() == "Voxel Count":
                featureWidget.addParameter("Example Parameter 1")
                featureWidget.addParameter("Example Parameter 2")
            if featureWidget.getName() == "Gray Levels":
                featureWidget.addParameter("Example Parameter 1-GL")
                featureWidget.addParameter("Example Parameter 2-GL")

        # compile dict of features with parameter names and values
        self.featureParametersDict = collections.OrderedDict()
        for featureWidget in self.heterogeneityFeatureWidgets:
            featureName = featureWidget.getName()
            self.featureParametersDict[featureName] = collections.OrderedDict()
            self.updateFeatureParameterDict(0, featureWidget)
            for parameterName in featureWidget.widgetMenu.parameters:
                featureWidget.getParameterEditWindow(parameterName).connect(
                    'intValueChanged(int)',
                    lambda intValue, featureWidget=featureWidget: self.
                    updateFeatureParameterDict(intValue, featureWidget)
                )  #connect intvaluechanged signals to updateParamaterDict function
        ##########

        # Feature Buttons Frame and Layout
        self.featureButtonFrame = qt.QFrame(
            self.HeterogeneityCADCollapsibleButton)
        self.featureButtonFrame.setLayout(qt.QHBoxLayout())
        self.featuresHeterogeneityCADLayout.addRow(self.featureButtonFrame)

        # HeterogeneityCAD Apply Button
        self.HeterogeneityCADButton = qt.QPushButton("Apply HeterogeneityCAD",
                                                     self.featureButtonFrame)
        self.HeterogeneityCADButton.toolTip = "Analyze input volume using selected Heterogeneity Features."
        self.featureButtonFrame.layout().addWidget(self.HeterogeneityCADButton)
        self.HeterogeneityCADButton.connect(
            'clicked()', self.onHeterogeneityCADButtonClicked)

        # Save Button
        self.saveButton = qt.QPushButton("Save to File",
                                         self.featureButtonFrame)
        self.saveButton.toolTip = "Save analyses to CSV file"
        self.saveButton.enabled = False
        self.featureButtonFrame.layout().addWidget(self.saveButton)
        self.saveButton.connect('clicked()', self.onSave)

        #End HeterogeneityCAD Features Collapsible Button
        #################################################
        #Feature Summary Chart

        #Complete chart options, export list of user-selected options identified via connections to labelstatistics module
        self.chartOptions = ("Count", "Volume mm^3", "Volume cc", "Min", "Max",
                             "Mean", "StdDev")
        self.StatisticsChartCollapsibleButton = ctk.ctkCollapsibleButton()
        self.StatisticsChartCollapsibleButton.text = "HeterogeneityCAD Features Summary"
        self.layout.addWidget(self.StatisticsChartCollapsibleButton)
        self.StatisticsChartLayout = qt.QFormLayout(
            self.StatisticsChartCollapsibleButton)
        self.StatisticsChartCollapsibleButton.collapsed = False

        #Table View to display Label statistics
        self.view = qt.QTableView(self.StatisticsChartCollapsibleButton)
        self.view.sortingEnabled = True
        self.StatisticsChartLayout.addWidget(self.view)
        self.view.minimumHeight = 175
Example #13
0
    def setup(self):
        # reload button
        self.reloadButton = qt.QPushButton("Reload")
        self.reloadButton.toolTip = "Reload this module."
        self.reloadButton.name = "HeterogeneityCAD Reload"
        self.layout.addWidget(self.reloadButton)
        self.reloadButton.connect('clicked()', self.onReload)

        # Tumor Segmentation Collapsible Button
        self.TumorSegmentationCollapsibleButton = ctk.ctkCollapsibleButton()
        self.TumorSegmentationCollapsibleButton.text = "SegmentCAD Segmentation"
        self.layout.addWidget(self.TumorSegmentationCollapsibleButton)
        self.TumorSegmentationLayout = qt.QFormLayout(
            self.TumorSegmentationCollapsibleButton)

        # Select Volumes Collapsible Button
        self.selectionsCollapsibleButton = ctk.ctkCollapsibleButton()
        self.selectionsCollapsibleButton.text = "Select DCE-MRI Volumes for Segmentation"
        self.TumorSegmentationLayout.addWidget(
            self.selectionsCollapsibleButton)
        # Layout within the collapsible button
        self.volumesLayout = qt.QFormLayout(self.selectionsCollapsibleButton)

        # Use Multivolume Node as input
        self.enableMultiVolume = qt.QCheckBox(self.selectionsCollapsibleButton)
        self.enableMultiVolume.setText('Input Multi-Volume Node')
        self.enableMultiVolume.checked = True
        self.enableMultiVolume.setToolTip(
            'Use Multi-Volume Node, with volumes imported in the correct order'
        )
        self.inputSelectorMultiVolume = slicer.qMRMLNodeComboBox(
            self.selectionsCollapsibleButton)
        self.inputSelectorMultiVolume.nodeTypes = (("vtkMRMLMultiVolumeNode"),
                                                   "")
        self.inputSelectorMultiVolume.selectNodeUponCreation = False
        self.inputSelectorMultiVolume.renameEnabled = True
        self.inputSelectorMultiVolume.removeEnabled = False
        self.inputSelectorMultiVolume.noneEnabled = True
        self.inputSelectorMultiVolume.addEnabled = False
        self.inputSelectorMultiVolume.setMRMLScene(slicer.mrmlScene)
        self.inputSelectorMultiVolume.setToolTip(
            'Use Multi-Volume Node, with volumes imported in the correct order'
        )

        self.volumesLayout.addRow(self.enableMultiVolume,
                                  self.inputSelectorMultiVolume)

        self.nodeInputFrame = ctk.ctkCollapsibleGroupBox(
            self.selectionsCollapsibleButton)
        self.nodeInputFrame.title = "Input Scalar Volume Nodes"
        self.nodeInputFrame.collapsed = True
        self.nodeInputFrame.enabled = False
        self.nodeInputFrame.setLayout(qt.QFormLayout())
        self.volumesLayout.addRow(self.nodeInputFrame)

        # Select Pre Node
        self.inputPre = qt.QLabel("Pre-contrast Volume", self.nodeInputFrame)
        self.inputPre.setToolTip(
            'Select the initial pre-contrast volume node.')
        self.inputSelectorPre = slicer.qMRMLNodeComboBox(self.nodeInputFrame)
        self.inputSelectorPre.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.inputSelectorPre.selectNodeUponCreation = False
        self.inputSelectorPre.addEnabled = False
        self.inputSelectorPre.removeEnabled = False
        self.inputSelectorPre.noneEnabled = True
        self.inputSelectorPre.noneDisplay = 'Please Select Volume'
        self.inputSelectorPre.setMRMLScene(slicer.mrmlScene)
        self.inputSelectorPre.setToolTip(
            'Select the initial pre-contrast volume node.')
        #self.volumesLayout.addRow(self.inputPre, self.inputSelectorPre)
        self.nodeInputFrame.layout().addRow(self.inputPre,
                                            self.inputSelectorPre)

        # Select First Node
        self.inputFirst = qt.QLabel("First Post-contrast Volume",
                                    self.nodeInputFrame)
        self.inputFirst.setToolTip(
            'Select the first post-contrast volume node to calculate intitial enhancement and curve type.'
        )
        self.inputSelectorFirst = slicer.qMRMLNodeComboBox(self.nodeInputFrame)
        self.inputSelectorFirst.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.inputSelectorFirst.selectNodeUponCreation = False
        self.inputSelectorFirst.addEnabled = False
        self.inputSelectorFirst.removeEnabled = False
        self.inputSelectorFirst.noneEnabled = True
        self.inputSelectorFirst.noneDisplay = 'Please Select Volume'
        self.inputSelectorFirst.setMRMLScene(slicer.mrmlScene)
        self.inputSelectorFirst.setToolTip(
            'Select the first post-contrast volume node to calculate intitial enhancement and curve type.'
        )
        #self.volumesLayout.addRow(self.inputFirst, self.inputSelectorFirst)
        self.nodeInputFrame.layout().addRow(self.inputFirst,
                                            self.inputSelectorFirst)

        # Select Second Node
        self.inputSecond = qt.QLabel("Second Post-contrast Volume",
                                     self.nodeInputFrame)
        self.inputSecond.setToolTip(
            'Select a second post-contrast volume node (not required).')
        self.inputSelectorSecond = slicer.qMRMLNodeComboBox(
            self.nodeInputFrame)
        self.inputSelectorSecond.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.inputSelectorSecond.selectNodeUponCreation = False
        self.inputSelectorSecond.addEnabled = False
        self.inputSelectorSecond.removeEnabled = False
        self.inputSelectorSecond.noneEnabled = True
        self.inputSelectorSecond.noneDisplay = 'Please Select Volume'
        self.inputSelectorSecond.setMRMLScene(slicer.mrmlScene)
        self.inputSelectorSecond.setToolTip(
            'Select a second post-contrast volume node (not required).')
        #self.volumesLayout.addRow(self.inputSecond, self.inputSelectorSecond)
        self.nodeInputFrame.layout().addRow(self.inputSecond,
                                            self.inputSelectorSecond)

        # Select Third Node
        self.inputThird = qt.QLabel("Third Post-contrast Volume",
                                    self.nodeInputFrame)
        self.inputThird.setToolTip(
            'Select a third post-contrast volume node (not required).')
        self.inputSelectorThird = slicer.qMRMLNodeComboBox(self.nodeInputFrame)
        self.inputSelectorThird.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.inputSelectorThird.selectNodeUponCreation = False
        self.inputSelectorThird.addEnabled = False
        self.inputSelectorThird.removeEnabled = False
        self.inputSelectorThird.noneEnabled = True
        self.inputSelectorThird.noneDisplay = 'Please Select Volume'
        self.inputSelectorThird.setMRMLScene(slicer.mrmlScene)
        self.inputSelectorThird.setToolTip(
            'Select a third post-contrast volume node (not required).')
        #self.volumesLayout.addRow(self.inputThird, self.inputSelectorThird)
        self.nodeInputFrame.layout().addRow(self.inputThird,
                                            self.inputSelectorThird)

        # Select Fourth Node
        self.inputFourth = qt.QLabel("Fourth Post-contrast Volume",
                                     self.nodeInputFrame)
        self.inputFourth.setToolTip(
            'Select the fourth or final post-contrast volume node to calculate curve type based on the delayed curve slope.'
        )
        self.inputSelectorFourth = slicer.qMRMLNodeComboBox(
            self.nodeInputFrame)
        self.inputSelectorFourth.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.inputSelectorFourth.selectNodeUponCreation = False
        self.inputSelectorFourth.addEnabled = False
        self.inputSelectorFourth.removeEnabled = False
        self.inputSelectorFourth.noneEnabled = True
        self.inputSelectorFourth.noneDisplay = 'Please Select Volume'
        self.inputSelectorFourth.setMRMLScene(slicer.mrmlScene)
        self.inputSelectorFourth.setToolTip(
            'Select the fourth or final post-contrast volume node to calculate curve type based on the delayed curve slope.'
        )
        #self.volumesLayout.addRow(self.inputFourth, self.inputSelectorFourth)
        self.nodeInputFrame.layout().addRow(self.inputFourth,
                                            self.inputSelectorFourth)

        # Enable and Select Input Label Map as ROI
        self.enableLabel = qt.QCheckBox(self.selectionsCollapsibleButton)
        self.enableLabel.setText('Use Label Map as ROI')
        self.enableLabel.checked = True
        self.enableLabel.setToolTip(
            'Select and identify a custom label map node to define an ROI over the input volumes for faster segmentation.'
        )
        self.inputSelectorLabel = slicer.qMRMLNodeComboBox(
            self.selectionsCollapsibleButton)
        self.inputSelectorLabel.nodeTypes = (("vtkMRMLLabelMapVolumeNode"), "")
        self.inputSelectorLabel.selectNodeUponCreation = False
        self.inputSelectorLabel.renameEnabled = True
        self.inputSelectorLabel.removeEnabled = False
        self.inputSelectorLabel.noneEnabled = True
        self.inputSelectorLabel.addEnabled = False
        self.inputSelectorLabel.setMRMLScene(slicer.mrmlScene)
        self.inputSelectorLabel.setToolTip(
            'Select and identify a custom label map node to define an ROI over the input volumes for faster segmentation.'
        )
        self.volumesLayout.addRow(self.enableLabel, self.inputSelectorLabel)

        # Select output SegmentCAD Label collapsible button
        self.outlabelCollapsibleButton = ctk.ctkCollapsibleButton()
        self.outlabelCollapsibleButton.text = "Select or Create Output SegmentCAD Label Map"
        self.TumorSegmentationLayout.addWidget(self.outlabelCollapsibleButton)
        # Layout within the collapsible button
        self.outlabelLayout = qt.QFormLayout(self.outlabelCollapsibleButton)
        # Select or create output SegmentCAD Label Map
        self.outputLabel = qt.QLabel("Output SegmentCAD Label Map",
                                     self.outlabelCollapsibleButton)
        self.outputLabel.setToolTip(
            'Select or create a label map volume node as the SegmentCAD segmentation output.'
        )
        self.outputSelectorLabel = slicer.qMRMLNodeComboBox(
            self.outlabelCollapsibleButton)
        self.outputSelectorLabel.nodeTypes = (("vtkMRMLLabelMapVolumeNode"),
                                              "")
        self.outputSelectorLabel.baseName = "SegmentCAD Label Map"
        self.outputSelectorLabel.selectNodeUponCreation = True
        self.outputSelectorLabel.renameEnabled = True
        self.outputSelectorLabel.removeEnabled = True
        self.outputSelectorLabel.noneEnabled = False
        self.outputSelectorLabel.addEnabled = True
        self.outputSelectorLabel.setMRMLScene(slicer.mrmlScene)
        self.outputSelectorLabel.setToolTip(
            'Select or create a label map volume node as the SegmentCAD segmentation output.'
        )
        self.outlabelLayout.addRow(self.outputLabel, self.outputSelectorLabel)
        # SegmentCAD Label Map Legend
        self.outputLegend = qt.QLabel(
            "| Type I Persistent: Blue | Type II Plateau: Yellow | Type III Washout: Red |",
            self.outlabelCollapsibleButton)
        self.outputLegend.setToolTip(
            'SegmentCAD Label Map Legend  | Blue: Type I Persistent curve  |  Yellow: Type II Plateau curve  |  Red: Type III Washout curve  |'
        )
        self.outlabelLayout.addRow(self.outputLegend)
        # Enable Volume Rendering of the SegmentCAD label map
        self.enableVolumeRendering = qt.QCheckBox(
            self.selectionsCollapsibleButton)
        self.enableVolumeRendering.setText('Display Volume Rendering')
        self.enableVolumeRendering.checked = True
        self.enableVolumeRendering.setToolTip(
            'Display volume rendering of the SegmentCAD Label Map in the 3D View'
        )
        self.outlabelLayout.addRow(self.enableVolumeRendering)
        # Enable Label Statistics Table and Data
        self.enableStats = qt.QCheckBox(self.selectionsCollapsibleButton)
        self.enableStats.setText('Calculate SegmentCAD Label statistics')
        self.enableStats.checked = False
        self.enableStats.setToolTip(
            'Use logic from Label Statistics Module to calculate statistics for first post-contrast voxels within the SegmentCAD Label Map.'
        )
        self.outlabelLayout.addRow(self.enableStats)

        # Set Advanced Parameters Collapsible Button
        self.parametersCollapsibleButton = ctk.ctkCollapsibleButton()
        self.parametersCollapsibleButton.text = "Set Advanced Segmentation Parameters"
        self.TumorSegmentationLayout.addWidget(
            self.parametersCollapsibleButton)
        self.parametersCollapsibleButton.collapsed = True
        # Layout within the collapsible button
        self.parametersLayout = qt.QFormLayout(
            self.parametersCollapsibleButton)
        # Set Minimum Threshold of Percentage Increase to First Post-Contrast Image
        self.inputMinimumThreshold = qt.QLabel(
            "Minimum Threshold of Increase", self.parametersCollapsibleButton)
        self.inputMinimumThreshold.setToolTip(
            'Minimum Threshold of Percentage Increase (Pre- to First Post-contrast (Range: 10% to 150%)'
        )
        self.inputSelectorMinimumThreshold = qt.QDoubleSpinBox(
            self.parametersCollapsibleButton)
        self.inputSelectorMinimumThreshold.setSuffix("%")
        self.inputSelectorMinimumThreshold.singleStep = (1)
        self.inputSelectorMinimumThreshold.minimum = (10)
        self.inputSelectorMinimumThreshold.maximum = (150)
        self.inputSelectorMinimumThreshold.value = (75)
        self.inputSelectorMinimumThreshold.setToolTip(
            'Minimum Threshold of Percentage Increase (Pre- to First Post-contrast (Range: 10% to 150%)'
        )
        self.parametersLayout.addRow(self.inputMinimumThreshold,
                                     self.inputSelectorMinimumThreshold)
        # Curve 1 Type Parameters (Slopes from First to Fourth Post-Contrast Images)
        self.inputCurve1 = qt.QLabel("Type 1 (Persistent) Curve Minimum Slope",
                                     self.parametersCollapsibleButton)
        self.inputCurve1.setToolTip(
            'Minimum Slope of Delayed Curve to classify as Persistent (Range: 0.02 to 0.3)'
        )
        self.inputSelectorCurve1 = qt.QDoubleSpinBox(
            self.parametersCollapsibleButton)
        self.inputSelectorCurve1.singleStep = (0.02)
        self.inputSelectorCurve1.minimum = (0.02)
        self.inputSelectorCurve1.maximum = (0.3)
        self.inputSelectorCurve1.value = (0.20)
        self.inputSelectorCurve1.setToolTip(
            'Minimum Slope of Delayed Curve to classify as Persistent (Range: 0.02 to 0.3)'
        )
        self.parametersLayout.addRow(self.inputCurve1,
                                     self.inputSelectorCurve1)
        # Curve 3 Type Parameters (Slopes from First to Fourth Post-Contrast Images)
        self.inputCurve3 = qt.QLabel("Type 3 (Washout) Curve Maximum Slope",
                                     self.parametersCollapsibleButton)
        self.inputCurve3.setToolTip(
            'Maximum Slope of Delayed Curve to classify as Washout (Range: -0.02 to -0.3)'
        )
        self.inputSelectorCurve3 = qt.QDoubleSpinBox(
            self.parametersCollapsibleButton)
        self.inputSelectorCurve3.singleStep = (0.02)
        self.inputSelectorCurve3.setPrefix("-")
        self.inputSelectorCurve3.minimum = (0.02)
        self.inputSelectorCurve3.maximum = (0.30)
        self.inputSelectorCurve3.value = (0.20)
        self.inputSelectorCurve3.setToolTip(
            'Maximum Slope of Delayed Curve to classify as Washout (Range: -0.02 to -0.3)'
        )
        self.parametersLayout.addRow(self.inputCurve3,
                                     self.inputSelectorCurve3)
        # Apply Tumor Adaptive Segmentation button
        self.SegmentCADButton = qt.QPushButton("Apply SegmentCAD")
        self.SegmentCADButton.toolTip = "Apply SegmentCAD segmentation to selected volumes."
        self.TumorSegmentationLayout.addWidget(self.SegmentCADButton)

        # LabelStatistics Table Collapsible Button
        self.labelstatisticsCollapsibleButton = ctk.ctkCollapsibleButton()
        self.labelstatisticsCollapsibleButton.text = "SegmentCAD Label Statistics"
        self.layout.addWidget(self.labelstatisticsCollapsibleButton)
        self.labelstatisticsCollapsibleButton.collapsed = True
        # Layout within the collapsible button
        self.labelstatisticsLayout = qt.QFormLayout(
            self.labelstatisticsCollapsibleButton)
        # Table View to display Label statistics
        self.labelStatisticsTableView = qt.QTableView()
        self.labelStatisticsTableView.sortingEnabled = True
        self.labelstatisticsLayout.addWidget(self.labelStatisticsTableView)
        self.labelStatisticsTableView.minimumHeight = 200
        # Charting Statistics Button
        self.chartOptions = ("Volume", "Curve Type", "Voxel Count",
                             "Volume mm^3", "Volume cc", "Minimum Intensity",
                             "Maximum Intensity", "Mean Intensity",
                             "Standard Deviation")
        self.chartFrame = qt.QFrame()
        self.chartFrame.setLayout(qt.QHBoxLayout())
        self.labelstatisticsLayout.addWidget(self.chartFrame)
        self.chartButton = qt.QPushButton(
            "Chart Statistics", self.labelstatisticsCollapsibleButton)
        self.chartButton.toolTip = "Make a chart from the current statistics."
        self.chartFrame.layout().addWidget(self.chartButton)
        self.chartOption = qt.QComboBox(self.labelstatisticsCollapsibleButton)
        self.chartOption.addItems(self.chartOptions)
        self.chartFrame.layout().addWidget(self.chartOption)
        self.chartIgnoreZero = qt.QCheckBox(
            self.labelstatisticsCollapsibleButton)
        self.chartIgnoreZero.setText('Ignore Zero Label')
        self.chartIgnoreZero.checked = False
        self.chartIgnoreZero.setToolTip(
            'Do not include the zero index in the chart to avoid dwarfing other bars'
        )
        self.chartFrame.layout().addWidget(self.chartIgnoreZero)
        self.chartButton.enabled = False

        # Interactive Charting Settings Collapsible Button
        self.iChartingCollapsibleButton = ctk.ctkCollapsibleButton()
        self.iChartingCollapsibleButton.text = "Interactive Charting Settings"
        self.iChartingCollapsibleButton.collapsed = True
        self.layout.addWidget(self.iChartingCollapsibleButton)
        # Layout within the collapsible button
        self.iChartingLayout = qt.QFormLayout(self.iChartingCollapsibleButton)
        # iCharting toggle button
        self.iCharting = qt.QPushButton("Enable Interactive Charting")
        self.iCharting.checkable = True
        self.iCharting.setChecked(False)
        self.iCharting.enabled = False
        self.iCharting.toolTip = "Toggle the real-time charting of the %increase from baseline of the selected voxel from each input volume."
        self.iChartingLayout.addRow(self.iCharting)

        # Initialize slice observers (from DataProbe.py)
        # Keep list of pairs: [observee,tag] so they can be removed easily
        self.styleObserverTags = []
        # Keep a map of interactor styles to sliceWidgets so we can easily get sliceLogic
        self.sliceWidgetsPerStyle = {}
        self.refreshObservers()

        # Connections
        self.SegmentCADButton.connect('clicked()',
                                      self.onSegmentCADButtonClicked)
        self.enableLabel.connect('stateChanged(int)', self.onEnableLabel)
        self.enableMultiVolume.connect('stateChanged(int)',
                                       self.onEnableMultiVolume)
        self.chartButton.connect('clicked()', self.onChart)
        self.iCharting.connect('toggled(bool)',
                               self.onInteractiveChartingChanged)
Example #14
0
    def create(self):
        """create the segmentation helper box"""

        #
        # Master Frame
        #
        self.masterFrame = qt.QFrame(self.parent)
        self.masterFrame.setLayout(qt.QVBoxLayout())
        self.parent.layout().addWidget(self.masterFrame)

        #
        # the master volume selector
        #
        self.masterSelectorFrame = qt.QFrame(self.parent)
        self.masterSelectorFrame.objectName = 'MasterVolumeFrame'
        self.masterSelectorFrame.setLayout(qt.QHBoxLayout())
        self.masterFrame.layout().addWidget(self.masterSelectorFrame)

        self.masterSelectorLabel = qt.QLabel("Master Volume: ",
                                             self.masterSelectorFrame)
        self.masterSelectorLabel.setToolTip(
            "Select the master volume (background grayscale scalar volume node)"
        )
        self.masterSelectorFrame.layout().addWidget(self.masterSelectorLabel)

        self.masterSelector = slicer.qMRMLNodeComboBox(
            self.masterSelectorFrame)
        self.masterSelector.objectName = 'MasterVolumeNodeSelector'
        # TODO
        self.masterSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
        self.masterSelector.selectNodeUponCreation = False
        self.masterSelector.addEnabled = False
        self.masterSelector.removeEnabled = False
        self.masterSelector.noneEnabled = True
        self.masterSelector.showHidden = False
        self.masterSelector.showChildNodeTypes = False
        self.masterSelector.setMRMLScene(slicer.mrmlScene)
        # TODO: need to add a QLabel
        # self.masterSelector.SetLabelText( "Master Volume:" )
        self.masterSelector.setToolTip(
            "Pick the master structural volume to define the segmentation.  A label volume with the with \"%s\" appended to the name will be created if it doesn't already exist."
            % self.mergeVolumePostfix)
        self.masterSelectorFrame.layout().addWidget(self.masterSelector)

        #
        # merge label name and set button
        #
        self.mergeSelectorFrame = qt.QFrame(self.masterFrame)
        self.mergeSelectorFrame.objectName = 'MergeVolumeFrame'
        self.mergeSelectorFrame.setLayout(qt.QHBoxLayout())
        self.masterFrame.layout().addWidget(self.mergeSelectorFrame)

        mergeNameToolTip = "Composite label map containing the merged structures (be aware that merge operations will overwrite any edits applied to this volume)"
        self.mergeNameLabel = qt.QLabel("Merge Volume: ",
                                        self.mergeSelectorFrame)
        self.mergeNameLabel.setToolTip(mergeNameToolTip)
        self.mergeSelectorFrame.layout().addWidget(self.mergeNameLabel)

        self.mergeSelector = slicer.qMRMLNodeComboBox(self.mergeSelectorFrame)
        self.mergeSelector.objectName = 'MergeVolumeNodeSelector'
        self.mergeSelector.setToolTip(mergeNameToolTip)
        self.mergeSelector.nodeTypes = ["vtkMRMLLabelMapVolumeNode"]
        self.mergeSelector.addEnabled = False
        self.mergeSelector.removeEnabled = False
        self.mergeSelector.noneEnabled = False
        self.mergeSelector.showHidden = False
        self.mergeSelector.showChildNodeTypes = False
        self.mergeSelector.setMRMLScene(slicer.mrmlScene)
        self.mergeSelectorFrame.layout().addWidget(self.mergeSelector)

        self.newMergeVolumeAction = qt.QAction("Create new LabelMapVolume",
                                               self.mergeSelector)
        self.newMergeVolumeAction.connect("triggered()", self.newMerge)
        self.mergeSelector.addMenuAction(self.newMergeVolumeAction)

        #
        # Structures Frame
        #
        self.structuresFrame = ctk.ctkCollapsibleGroupBox(self.masterFrame)
        self.structuresFrame.objectName = 'PerStructureVolumesFrame'
        self.structuresFrame.title = "Per-Structure Volumes"
        self.structuresFrame.collapsed = True
        self.structuresFrame.setLayout(qt.QVBoxLayout())
        self.masterFrame.layout().addWidget(self.structuresFrame)

        self.structureListWidget = LabelStructureListWidget()
        self.structureListWidget.mergeVolumePostfix = self.mergeVolumePostfix
        self.structuresFrame.layout().addWidget(self.structureListWidget)

        #
        # signals, slots, and observers
        #

        # signals/slots on qt widgets are automatically when
        # this class destructs, but observers of the scene must be explicitly
        # removed in the destuctor

        # node selected
        self.masterSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                    self.onSelect)
        self.mergeSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                   self.onMergeSelect)

        # so buttons will initially be disabled
        self.master = None
        self.structureListWidget.updateStructures()
Example #15
0
  def setup(self):
    self.conoProbeConnectorLogic = ConoProbeConnectorLogic() 
    self.firstInitColouring = True
    
    ScriptedLoadableModuleWidget.setup(self)
  
    # Icons stuff
    self.conoProbeConnectorModuleDirectoryPath = slicer.modules.conoprobeconnector.path.replace("ConoProbeConnector.py","")
    self.playIcon = qt.QIcon(self.conoProbeConnectorModuleDirectoryPath + '/Resources/Icons/playIcon.png')
    self.stopIcon = qt.QIcon(self.conoProbeConnectorModuleDirectoryPath + '/Resources/Icons/stopIcon.png')
    self.recordIcon = qt.QIcon(self.conoProbeConnectorModuleDirectoryPath + '/Resources/Icons/recordIcon.png')
    self.restartIcon = qt.QIcon(self.conoProbeConnectorModuleDirectoryPath + '/Resources/Icons/restartIcon.png')
    self.saveIcon = qt.QIcon(self.conoProbeConnectorModuleDirectoryPath + '/Resources/Icons/saveIcon.png')                         
    
    self.errorStyleSheet = "QLabel { color : #FF0000; \
                                     font: bold 14px}"
    self.defaultStyleSheet = "QLabel { color : #000000; \
                                       font: bold 14px}"     
                                  
    ######################################################## Recorder
    recorderCollapsibleButton = ctk.ctkCollapsibleButton()
    recorderCollapsibleButton.text = "ConoProbe Connector"
    recorderCollapsibleButton.collapsed = False
    self.layout.addWidget(recorderCollapsibleButton)
    recorderFormLayout = qt.QFormLayout(recorderCollapsibleButton)
    
    # Output
    self.recorderOutputGroupBox = ctk.ctkCollapsibleGroupBox()
    self.recorderOutputGroupBox.setTitle("Output")
    recorderOutputFormLayout = qt.QFormLayout(self.recorderOutputGroupBox)
    recorderFormLayout.addRow(self.recorderOutputGroupBox)
    
    self.lensMinLabel = qt.QLabel('-')
    self.lensMinLabel.setStyleSheet(self.defaultStyleSheet)
    self.QFormLayoutLeftLabel10 = qt.QLabel('Lens Min. Dist. (mm): ')
    self.QFormLayoutLeftLabel10.setStyleSheet(self.defaultStyleSheet)
    recorderOutputFormLayout.addRow(self.QFormLayoutLeftLabel10, self.lensMinLabel) 
    
    self.distanceLabel = qt.QLabel('-')
    self.distanceLabel.setStyleSheet(self.defaultStyleSheet)
    self.QFormLayoutLeftLabel1 = qt.QLabel('Distance (mm): ')
    self.QFormLayoutLeftLabel1.setStyleSheet(self.defaultStyleSheet)
    recorderOutputFormLayout.addRow(self.QFormLayoutLeftLabel1, self.distanceLabel)  

    self.lensMaxLabel = qt.QLabel('-')
    self.lensMaxLabel.setStyleSheet(self.defaultStyleSheet)
    self.QFormLayoutLeftLabel11 = qt.QLabel('Lens Max. Dist. (mm): ')
    self.QFormLayoutLeftLabel11.setStyleSheet(self.defaultStyleSheet)
    recorderOutputFormLayout.addRow(self.QFormLayoutLeftLabel11, self.lensMaxLabel) 
    
    dummyLabel1 = qt.QLabel('')
    recorderOutputFormLayout.addRow('', dummyLabel1)
    
    self.powerLabel = qt.QLabel('-')
    self.powerLabel.setStyleSheet(self.defaultStyleSheet)
    self.QFormLayoutLeftLabel8 = qt.QLabel('Laser Power (arb. unit): ')
    self.QFormLayoutLeftLabel8.setStyleSheet(self.defaultStyleSheet)
    recorderOutputFormLayout.addRow(self.QFormLayoutLeftLabel8, self.powerLabel)  

    self.frequencyLabel = qt.QLabel('-')
    self.frequencyLabel.setStyleSheet(self.defaultStyleSheet)
    self.QFormLayoutLeftLabel9 = qt.QLabel('Laser Frequency (Hz): ')
    self.QFormLayoutLeftLabel9.setStyleSheet(self.defaultStyleSheet)
    recorderOutputFormLayout.addRow(self.QFormLayoutLeftLabel9, self.frequencyLabel)  
   
    self.nbrOfPointsRecordedLabel = qt.QLabel('0')
    self.nbrOfPointsRecordedLabel.setStyleSheet(self.defaultStyleSheet)
    self.QFormLayoutLeftLabel2 = qt.QLabel('Nbr. of Points Recorded: ')
    self.QFormLayoutLeftLabel2.setStyleSheet(self.defaultStyleSheet)
    recorderOutputFormLayout.addRow(self.QFormLayoutLeftLabel2, self.nbrOfPointsRecordedLabel)
    
    self.positionLabel = qt.QLabel('-')
    self.positionLabel.setStyleSheet(self.defaultStyleSheet)
    self.QFormLayoutLeftLabel3 = qt.QLabel('Position ([r, a, s]): ')
    self.QFormLayoutLeftLabel3.setStyleSheet(self.defaultStyleSheet)
    recorderOutputFormLayout.addRow(self.QFormLayoutLeftLabel3, self.positionLabel)   
    
    self.timeLabel = qt.QLabel('-')
    self.timeLabel.setStyleSheet(self.defaultStyleSheet)
    self.QFormLayoutLeftLabel4 = qt.QLabel('Recording Time (s): ')
    self.QFormLayoutLeftLabel4.setStyleSheet(self.defaultStyleSheet)
    recorderOutputFormLayout.addRow(self.QFormLayoutLeftLabel4, self.timeLabel)   
        
    self.snrLabel = qt.QLabel('-')
    self.snrLabel.setStyleSheet(self.defaultStyleSheet)
    self.QFormLayoutLeftLabel5 = qt.QLabel('SNR (%): ')
    self.QFormLayoutLeftLabel5.setStyleSheet(self.defaultStyleSheet)
    recorderOutputFormLayout.addRow(self.QFormLayoutLeftLabel5, self.snrLabel)    
    
    self.totalLabel = qt.QLabel('-')
    self.totalLabel.setStyleSheet(self.defaultStyleSheet)
    self.QFormLayoutLeftLabel6 = qt.QLabel('Total: ')
    self.QFormLayoutLeftLabel6.setStyleSheet(self.defaultStyleSheet)
    recorderOutputFormLayout.addRow(self.QFormLayoutLeftLabel6, self.totalLabel)    
    
    dummyLabel2 = qt.QLabel('')
    recorderOutputFormLayout.addRow('', dummyLabel2)
    
    self.infoLabel = qt.QLabel('Make sure Plus is running')
    self.infoLabel.setWordWrap(True)
    self.infoLabel.setStyleSheet(self.errorStyleSheet)
    self.QFormLayoutLeftLabel7 = qt.QLabel('INFO: ')
    self.QFormLayoutLeftLabel7.setStyleSheet(self.defaultStyleSheet)
    recorderOutputFormLayout.addRow(self.QFormLayoutLeftLabel7, self.infoLabel)

    # Live Filtering
    self.recorderFilteringGroupBox = ctk.ctkCollapsibleGroupBox()
    self.recorderFilteringGroupBox.setTitle("Live Filtering")
    recorderFilteringFormLayout = qt.QFormLayout(self.recorderFilteringGroupBox)
    recorderFormLayout.addRow(self.recorderFilteringGroupBox)
    
    self.snrFilteringSlider = ctk.ctkSliderWidget()
    self.snrFilteringSlider.setDecimals(0)
    self.snrFilteringSlider.singleStep = 1
    self.snrFilteringSlider.minimum = 0
    self.snrFilteringSlider.maximum = 100
    self.snrFilteringSlider.value = 40
    recorderFilteringFormLayout.addRow('SNR (%): ', self.snrFilteringSlider)
    
    self.distanceFilteringSlider = ctk.ctkRangeWidget()
    self.distanceFilteringSlider.minimum = 0
    self.distanceFilteringSlider.maximum = 500
    self.distanceFilteringSlider.setValues(0, 500)
    recorderFilteringFormLayout.addRow('Distance (mm): ', self.distanceFilteringSlider)
    
    # Intuitive Colouring
    self.colouringGroupBox = ctk.ctkCollapsibleGroupBox()
    self.colouringGroupBox.setTitle("Intuitive Colouring")
    colouringFormLayout = qt.QFormLayout(self.colouringGroupBox)
    recorderFormLayout.addRow(self.colouringGroupBox)
    
    hBoxLayoutColouring = qt.QHBoxLayout()
    colouringFormLayout.addRow(hBoxLayoutColouring)
    
    self.rasLabel = qt.QLabel('Direction: ')
    hBoxLayoutColouring.addWidget(self.rasLabel)
    self.rasComboBox = qt.QComboBox()
    self.rasComboBox.addItem('R')  
    self.rasComboBox.addItem('A')
    self.rasComboBox.addItem('S')               
    hBoxLayoutColouring.addWidget(self.rasComboBox)     
    
    self.minLabel = qt.QLabel('    Minimum: ')
    hBoxLayoutColouring.addWidget(self.minLabel)
    self.minSpinBox = qt.QDoubleSpinBox ()
    self.minSpinBox.setMinimum(-500)
    self.minSpinBox.setMaximum(500)
    self.minSpinBox.setSingleStep(0.1)
    self.minSpinBox.setValue(0.0)
    hBoxLayoutColouring.addWidget(self.minSpinBox)    
    
    self.maxLabel = qt.QLabel('    Maximum: ')
    hBoxLayoutColouring.addWidget(self.maxLabel)
    self.maxSpinBox = qt.QDoubleSpinBox ()
    self.maxSpinBox.setMinimum(-500)
    self.maxSpinBox.setMaximum(500)
    self.maxSpinBox.setSingleStep(0.1)
    self.maxSpinBox.setValue(0.0)
    hBoxLayoutColouring.addWidget(self.maxSpinBox)

    hBoxLayoutColouring.addStretch()
      
    # Controls
    self.controlsGroupBox = ctk.ctkCollapsibleGroupBox()
    self.controlsGroupBox.setTitle("Controls")
    controlsFormLayout = qt.QFormLayout(self.controlsGroupBox)
    recorderFormLayout.addRow(self.controlsGroupBox)
    
    hBoxLayoutControls = qt.QHBoxLayout()
    controlsFormLayout.addRow(hBoxLayoutControls)

    self.initButton = qt.QPushButton(" Init")
    self.initButton.setIcon(self.playIcon)
    self.initButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    self.initButton.enabled = True
    hBoxLayoutControls.addWidget(self.initButton)

    self.recordButton = qt.QPushButton(" Record")
    self.recordButton.setIcon(self.recordIcon)
    self.recordButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    self.recordButton.enabled = False
    self.recordButton.checkable = True
    hBoxLayoutControls.addWidget(self.recordButton)
    
    self.probeDialogButton = qt.QPushButton("ProbeDialog")
    self.probeDialogButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    self.probeDialogButton.enabled = False
    hBoxLayoutControls.addWidget(self.probeDialogButton)    

    self.saveButton = qt.QPushButton(" Save")
    self.saveButton.setIcon(self.saveIcon)
    self.saveButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    self.saveButton.enabled = False
    hBoxLayoutControls.addWidget(self.saveButton)
    
    self.resetButton = qt.QPushButton(" Reset")
    self.resetButton.setIcon(self.restartIcon)
    self.resetButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    self.resetButton.enabled = False
    hBoxLayoutControls.addWidget(self.resetButton)
    
    hBoxCheckBoxes = qt.QHBoxLayout()
    controlsFormLayout.addRow(hBoxCheckBoxes)

    self.viewpointCheckBox = qt.QCheckBox('Enable Viewpoint')
    self.viewpointCheckBox.checked = True
    self.viewpointCheckBox.enabled = False
    hBoxCheckBoxes.addWidget(self.viewpointCheckBox) 

    self.singlePointCheckBox = qt.QCheckBox('Single Measurements')
    self.singlePointCheckBox.checked = False
    self.singlePointCheckBox.enabled = False
    hBoxCheckBoxes.addWidget(self.singlePointCheckBox) 
    
    self.plusRemoteCheckBox = qt.QCheckBox('Record PLUS Data Stream')
    self.plusRemoteCheckBox.checked = False
    self.plusRemoteCheckBox.enabled = False
    hBoxCheckBoxes.addWidget(self.plusRemoteCheckBox)    
    
    # Post-Processing
    self.postProcessingGroupBox = ctk.ctkCollapsibleGroupBox()
    self.postProcessingGroupBox.setTitle("Post-Processing")
    postProcessingFormLayout = qt.QFormLayout(self.postProcessingGroupBox)
    recorderFormLayout.addRow(self.postProcessingGroupBox)    
    
    self.snrPostProcessingSlider = ctk.ctkSliderWidget()
    self.snrPostProcessingSlider.setDecimals(0)
    self.snrPostProcessingSlider.singleStep = 1
    self.snrPostProcessingSlider.minimum = 0
    self.snrPostProcessingSlider.maximum = 100
    self.snrPostProcessingSlider.value = 0
    postProcessingFormLayout.addRow('SNR (%): ', self.snrPostProcessingSlider)
    
    self.distancePostProcessingSlider = ctk.ctkRangeWidget()
    self.distancePostProcessingSlider.minimum = 0
    self.distancePostProcessingSlider.maximum = 500
    self.distancePostProcessingSlider.setValues(0, 500)
    postProcessingFormLayout.addRow('Distance (mm): ', self.distancePostProcessingSlider)
    
    hBoxLayoutPostProcessing = qt.QHBoxLayout()
    postProcessingFormLayout.addRow(hBoxLayoutPostProcessing)

    self.undoButton = qt.QPushButton("Undo")
    self.undoButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    self.undoButton.enabled = False
    hBoxLayoutPostProcessing.addWidget(self.undoButton)

    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    self.applyButton.enabled = False
    hBoxLayoutPostProcessing.addWidget(self.applyButton)
    
    ######################################################## Connections
    self.snrFilteringSlider.connect('valueChanged(double)', self.onSnrFilteringValueChanged)
    self.distanceFilteringSlider.connect('maximumValueChanged(double)', self.onDistanceFilteringMaximumValueChanged)
    self.distanceFilteringSlider.connect('minimumValueChanged(double)', self.onDistanceFilteringMinimumValueChanged)
    self.initButton.connect('clicked(bool)', self.onInitClicked)
    self.recordButton.connect('clicked(bool)', self.onRecordClicked)
    self.resetButton.connect('clicked(bool)', self.onResetClicked)
    self.probeDialogButton.connect('clicked(bool)', self.onProbeDialogClicked)
    self.saveButton.connect('clicked(bool)', self.onSaveClicked)
    self.undoButton.connect('clicked(bool)', self.onUndoClicked)
    self.applyButton.connect('clicked(bool)', self.onApplyClicked)
    self.viewpointCheckBox.connect('stateChanged(int)', self.onViewpointChecked)
    self.plusRemoteCheckBox.connect('stateChanged(int)', self.onPlusRemoteChecked)
    
    # Add vertical spacer
    self.layout.addStretch(1) 
       
    # Create Plus connector and activate it
    self.conoProbeConnectorLogic.setupPlus()
    def setup(self):
        self.dir = os.path.dirname(os.path.realpath(__file__))

        #
        # Setup
        #
        setupWindow = ctk.ctkCollapsibleButton()
        setupWindow.text = 'Setup'
        self.layout.addWidget(setupWindow)
        self.setupLayout = qt.QFormLayout(setupWindow)

        # Input box
        inputBox = ctk.ctkCollapsibleGroupBox()
        inputBox.setTitle('Input:')
        self.setupLayout.addRow(inputBox)
        self.inputBoxLayout = qt.QFormLayout(inputBox)

        # Bevel angle slider
        self.bevelAngleSlider = ctk.ctkSliderWidget()
        self.bevelAngleSlider.connect('valueChanged(double)', self.bevel_angle_changed)
        self.bevelAngleSlider.decimals = 0
        self.bevelAngleSlider.minimum = 0
        self.bevelAngleSlider.maximum = 360
        self.inputBoxLayout.addRow("Bevel Angle:", self.bevelAngleSlider)

        # R-Axis Entry Error
        self.entryErrR = qt.QLineEdit()
        self.entryErrR.setPlaceholderText("Enter length (mm)")
        self.inputBoxLayout.addRow("R-Axis Entry Error:", self.entryErrR)

        # A-Axis Entry Error
        self.entryErrA = qt.QLineEdit()
        self.entryErrA.setPlaceholderText("Enter length (mm)")
        self.inputBoxLayout.addRow("A-Axis Entry Error:", self.entryErrA)

        # S-Axis Entry Error
        self.entryErrS = qt.QLineEdit()
        self.entryErrS.setPlaceholderText("Enter length (mm)")
        self.inputBoxLayout.addRow("S-Axis Entry Error:", self.entryErrS)

        # Curve Radius
        self.curveRadius = qt.QLineEdit()
        self.curveRadius.setPlaceholderText("Enter length (mm)")
        self.inputBoxLayout.addRow("Curve Radius:", self.curveRadius)

        # Insertion Length
        self.insertionLength = qt.QLineEdit()
        self.insertionLength.setPlaceholderText("Enter length (mm)")
        self.inputBoxLayout.addRow("Insertion Length:", self.insertionLength)

        # Needle length in prostate
        self.len1 = qt.QLineEdit()
        self.len1.setPlaceholderText("Enter length (mm)")
        self.inputBoxLayout.addRow("Needle length in prostate:", self.len1)

        # Needle Length in pelvic diaphragm
        self.len2 = qt.QLineEdit()
        self.len2.setPlaceholderText("Enter length (mm)")
        self.inputBoxLayout.addRow("Needle length in pelvic diaphragm:", self.len2)

        # Needle length in bulbospongiosus
        self.len3 = qt.QLineEdit()
        self.len3.setPlaceholderText("Enter length (mm)")
        self.inputBoxLayout.addRow("Needle length in bulbospongiousus:", self.len3)

        # Needle length in ischiocavernosus
        self.len4 = qt.QLineEdit()
        self.len4.setPlaceholderText("Enter length (mm)")
        self.inputBoxLayout.addRow("Needle length in ischiocavernosus:", self.len4)

        # Needle length in unsegmented tissue
        self.len5 = qt.QLineEdit()
        self.len5.setPlaceholderText("Enter length (mm)")
        self.inputBoxLayout.addRow("Needle length in unsegmented tissue:", self.len5)

        # Calculate Error
        self.calculateError = qt.QPushButton("Calculate Error")
        self.calculateError.clicked.connect(self.run_regressions)
        self.setupLayout.addWidget(self.calculateError)

        # Disable calculation until data is entered
        self.calculateError.setEnabled(0)
        self.calculateError.setText('Enter all data first!')

        #
        # Output
        #
        outputWindow = ctk.ctkCollapsibleButton()
        outputWindow.text = 'Output'
        self.layout.addWidget(outputWindow)
        self.outputLayout = qt.QFormLayout(outputWindow)

        # Output box
        outputBoxCollapsible = ctk.ctkCollapsibleGroupBox()
        outputBoxCollapsible.setTitle('Output')
        self.outputLayout.addRow(outputBoxCollapsible)
        self.outputBox = qt.QFormLayout(outputBoxCollapsible)

        # Initial output text
        self.outputLabel = qt.QLabel("")
        self.outputBox.addRow(self.outputLabel)
        self.outputLabel.setText("The needle has a probability of 00.00% to hit the \ntarget, a probability of 00.00% "
                                 "to deflect to the right,\nand a probability of 00.00% to deflect to the top.")
        # Initial visual output
        image = qt.QPixmap(self.dir + "/NeedleDeviationPredictor GUI/empty.png")
        self.label1 = qt.QLabel("")

        # Scaling and sizing
        self.label1.setScaledContents(True)
        self.label1.setMargin(0)
        self.label1.setPixmap(image)
        qSize = qt.QSizePolicy()
        self.label1.setSizePolicy(qSize)
        self.outputBox.addRow(self.label1)

        # Vertical spacer
        self.layout.addStretch(1)

        # Check all entered values are floats
        values = [self.entryErrR, self.entryErrA, self.entryErrS, self.curveRadius,
                  self.insertionLength, self.len1, self.len2, self.len3, self.len4, self.len5]
        for value in values:
            value.textChanged.connect(self.check_inputs)
Example #17
0
  def setup(self):
    ScriptedLoadableModuleWidget.setup(self)

    ############################################################ Playground
    playgroundCollapsibleButton = ctk.ctkCollapsibleButton()
    playgroundCollapsibleButton.text = "Playground"
    playgroundCollapsibleButton.collapsed = False
    self.layout.addWidget(playgroundCollapsibleButton)
    playgroundFormLayout = qt.QFormLayout(playgroundCollapsibleButton)

    # Load for testing
    self.loadTestModelButton = qt.QPushButton("Load Test Model")
    playgroundFormLayout.addRow(self.loadTestModelButton)    
    
    # ModelTipToToolCreator
    self.modelTipToToolCreatorGroupBox = ctk.ctkCollapsibleGroupBox()
    self.modelTipToToolCreatorGroupBox.setTitle("ModelTipToToolCreator")
    self.modelTipToToolCreatorGroupBox.collapsed = True
    modelTipToToolCreatorFormLayout = qt.QFormLayout(self.modelTipToToolCreatorGroupBox)
    playgroundFormLayout.addRow(self.modelTipToToolCreatorGroupBox)
    
    self.modeldistanceToModelToolTipToToolSelector = slicer.qMRMLNodeComboBox()
    self.modeldistanceToModelToolTipToToolSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.modeldistanceToModelToolTipToToolSelector.selectNodeUponCreation = True
    self.modeldistanceToModelToolTipToToolSelector.addEnabled = True
    self.modeldistanceToModelToolTipToToolSelector.editEnabled = False
    self.modeldistanceToModelToolTipToToolSelector.removeEnabled = True
    self.modeldistanceToModelToolTipToToolSelector.renameEnabled = True
    self.modeldistanceToModelToolTipToToolSelector.noneEnabled = False
    self.modeldistanceToModelToolTipToToolSelector.showHidden = False
    self.modeldistanceToModelToolTipToToolSelector.showChildNodeTypes = False
    self.modeldistanceToModelToolTipToToolSelector.setMRMLScene( slicer.mrmlScene )
    modelTipToToolCreatorFormLayout.addRow("ModelTipToTool: ", self.modeldistanceToModelToolTipToToolSelector)
    
    self.modelTipToToolCreatorByTransformsGroupBox = ctk.ctkCollapsibleGroupBox()
    self.modelTipToToolCreatorByTransformsGroupBox.setTitle("By Transforms")
    self.modelTipToToolCreatorByTransformsGroupBox.collapsed = False
    modelTipToToolCreatorByTransformsFormLayout = qt.QFormLayout(self.modelTipToToolCreatorByTransformsGroupBox)
    modelTipToToolCreatorFormLayout.addRow(self.modelTipToToolCreatorByTransformsGroupBox)
    
    self.tooldistanceToModelToolTipToToolSelector = slicer.qMRMLNodeComboBox()
    self.tooldistanceToModelToolTipToToolSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.tooldistanceToModelToolTipToToolSelector.selectNodeUponCreation = False
    self.tooldistanceToModelToolTipToToolSelector.addEnabled = False
    self.tooldistanceToModelToolTipToToolSelector.removeEnabled = False
    self.tooldistanceToModelToolTipToToolSelector.noneEnabled = False
    self.tooldistanceToModelToolTipToToolSelector.showHidden = False
    self.tooldistanceToModelToolTipToToolSelector.showChildNodeTypes = False
    self.tooldistanceToModelToolTipToToolSelector.setMRMLScene( slicer.mrmlScene )
    modelTipToToolCreatorByTransformsFormLayout.addRow("ToolTipToTool: ", self.tooldistanceToModelToolTipToToolSelector)
 
    self.modelTipToToolTipSelector = slicer.qMRMLNodeComboBox()
    self.modelTipToToolTipSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.modelTipToToolTipSelector.selectNodeUponCreation = False
    self.modelTipToToolTipSelector.addEnabled = False
    self.modelTipToToolTipSelector.removeEnabled = False
    self.modelTipToToolTipSelector.noneEnabled = False
    self.modelTipToToolTipSelector.showHidden = False
    self.modelTipToToolTipSelector.showChildNodeTypes = False
    self.modelTipToToolTipSelector.setMRMLScene( slicer.mrmlScene )
    modelTipToToolCreatorByTransformsFormLayout.addRow("ModelTipToToolTip: ", self.modelTipToToolTipSelector)
    
    self.toolToReferenceSelector = slicer.qMRMLNodeComboBox()
    self.toolToReferenceSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.toolToReferenceSelector.selectNodeUponCreation = False
    self.toolToReferenceSelector.addEnabled = False
    self.toolToReferenceSelector.removeEnabled = False
    self.toolToReferenceSelector.noneEnabled = False
    self.toolToReferenceSelector.showHidden = False
    self.toolToReferenceSelector.showChildNodeTypes = False
    self.toolToReferenceSelector.setMRMLScene( slicer.mrmlScene )
    modelTipToToolCreatorByTransformsFormLayout.addRow("ToolToReference: ", self.toolToReferenceSelector)
    
    self.applyModelTipToReferenceCreatorByTransformsButton = qt.QPushButton("Apply")
    self.applyModelTipToReferenceCreatorByTransformsButton.enabled = False
    modelTipToToolCreatorByTransformsFormLayout.addRow(self.applyModelTipToReferenceCreatorByTransformsButton)

    self.modelTipToToolCreatorByFiducialsGroupBox = ctk.ctkCollapsibleGroupBox()
    self.modelTipToToolCreatorByFiducialsGroupBox.setTitle("By Fiducials")
    self.modelTipToToolCreatorByFiducialsGroupBox.collapsed = False
    modelTipToToolCreatorByFiducialsFormLayout = qt.QFormLayout(self.modelTipToToolCreatorByFiducialsGroupBox)
    modelTipToToolCreatorFormLayout.addRow(self.modelTipToToolCreatorByFiducialsGroupBox)
    
    self.originFiducialSelector = slicer.qMRMLNodeComboBox()
    self.originFiducialSelector.nodeTypes = ["vtkMRMLMarkupsFiducialNode"]
    self.originFiducialSelector.selectNodeUponCreation = False
    self.originFiducialSelector.addEnabled = False
    self.originFiducialSelector.removeEnabled = False
    self.originFiducialSelector.noneEnabled = False
    self.originFiducialSelector.showHidden = False
    self.originFiducialSelector.showChildNodeTypes = False
    self.originFiducialSelector.setMRMLScene( slicer.mrmlScene )
    modelTipToToolCreatorByFiducialsFormLayout.addRow("Origin Fiducial: ", self.originFiducialSelector)
    
    self.fromFiducialSelector = slicer.qMRMLNodeComboBox()
    self.fromFiducialSelector.nodeTypes = ["vtkMRMLMarkupsFiducialNode"]
    self.fromFiducialSelector.selectNodeUponCreation = False
    self.fromFiducialSelector.addEnabled = False
    self.fromFiducialSelector.removeEnabled = False
    self.fromFiducialSelector.noneEnabled = False
    self.fromFiducialSelector.showHidden = False
    self.fromFiducialSelector.showChildNodeTypes = False
    self.fromFiducialSelector.setMRMLScene( slicer.mrmlScene )
    modelTipToToolCreatorByFiducialsFormLayout.addRow("From Fiducial: ", self.fromFiducialSelector)
    
    self.toFiducialSelector = slicer.qMRMLNodeComboBox()
    self.toFiducialSelector.nodeTypes = ["vtkMRMLMarkupsFiducialNode"]
    self.toFiducialSelector.selectNodeUponCreation = False
    self.toFiducialSelector.addEnabled = False
    self.toFiducialSelector.removeEnabled = False
    self.toFiducialSelector.noneEnabled = False
    self.toFiducialSelector.showHidden = False
    self.toFiducialSelector.showChildNodeTypes = False
    self.toFiducialSelector.setMRMLScene( slicer.mrmlScene )
    modelTipToToolCreatorByFiducialsFormLayout.addRow("To Fiducial: ", self.toFiducialSelector)

    self.applyModelTipToToolCreatorByFiducialsButton = qt.QPushButton("Apply")
    self.applyModelTipToToolCreatorByFiducialsButton.enabled = False
    modelTipToToolCreatorByFiducialsFormLayout.addRow(self.applyModelTipToToolCreatorByFiducialsButton)
    
    # FirstPersonView
    self.firstPersonViewGroupBox = ctk.ctkCollapsibleGroupBox()
    self.firstPersonViewGroupBox.setTitle("FirstPersonView")
    self.firstPersonViewGroupBox.collapsed = True
    firstPersonViewFormLayout = qt.QFormLayout(self.firstPersonViewGroupBox)
    playgroundFormLayout.addRow(self.firstPersonViewGroupBox)
    
    self.stylusTipSelector = slicer.qMRMLNodeComboBox()
    self.stylusTipSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.stylusTipSelector.selectNodeUponCreation = False
    self.stylusTipSelector.addEnabled = False
    self.stylusTipSelector.removeEnabled = False
    self.stylusTipSelector.noneEnabled = False
    self.stylusTipSelector.showHidden = False
    self.stylusTipSelector.showChildNodeTypes = False
    self.stylusTipSelector.setMRMLScene( slicer.mrmlScene )
    firstPersonViewFormLayout.addRow("StylusTip: ", self.stylusTipSelector)
        
    self.movingLRS_FiducialSelector = slicer.qMRMLNodeComboBox()
    self.movingLRS_FiducialSelector.nodeTypes = ["vtkMRMLMarkupsFiducialNode"]
    self.movingLRS_FiducialSelector.selectNodeUponCreation = True
    self.movingLRS_FiducialSelector.addEnabled = True
    self.movingLRS_FiducialSelector.editEnabled = False
    self.movingLRS_FiducialSelector.removeEnabled = True
    self.movingLRS_FiducialSelector.renameEnabled = True
    self.movingLRS_FiducialSelector.noneEnabled = False
    self.movingLRS_FiducialSelector.showHidden = False
    self.movingLRS_FiducialSelector.showChildNodeTypes = False
    self.movingLRS_FiducialSelector.setMRMLScene( slicer.mrmlScene )
    firstPersonViewFormLayout.addRow("Moving LRS Fiducials List: ", self.movingLRS_FiducialSelector)
    
    self.recordFirstPersonViewPointButton = qt.QPushButton(" Record Point")
    self.recordFirstPersonViewPointButton.enabled = False
    firstPersonViewFormLayout.addRow(self.recordFirstPersonViewPointButton)

    self.createFirstPersonViewButton = qt.QPushButton("Create First Person View")
    self.createFirstPersonViewButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    self.createFirstPersonViewButton.enabled = False
    firstPersonViewFormLayout.addRow(self.createFirstPersonViewButton)
    
    # Record points
    self.pointRecorderGroupBox = ctk.ctkCollapsibleGroupBox()
    self.pointRecorderGroupBox.setTitle("PointRecorder")
    self.pointRecorderGroupBox.collapsed = True
    pointRecorderFormLayout = qt.QFormLayout(self.pointRecorderGroupBox)
    playgroundFormLayout.addRow(self.pointRecorderGroupBox)

    self.pointerTransformSelector = slicer.qMRMLNodeComboBox()
    self.pointerTransformSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.pointerTransformSelector.selectNodeUponCreation = True
    self.pointerTransformSelector.addEnabled = True
    self.pointerTransformSelector.editEnabled = False
    self.pointerTransformSelector.removeEnabled = True
    self.pointerTransformSelector.renameEnabled = True
    self.pointerTransformSelector.noneEnabled = False
    self.pointerTransformSelector.showHidden = False
    self.pointerTransformSelector.showChildNodeTypes = False
    self.pointerTransformSelector.setMRMLScene( slicer.mrmlScene )
    pointRecorderFormLayout.addRow("Pointer Transform: ", self.pointerTransformSelector)
        
    self.pointerFiducialsSelector = slicer.qMRMLNodeComboBox()
    self.pointerFiducialsSelector.nodeTypes = ["vtkMRMLMarkupsFiducialNode"]
    self.pointerFiducialsSelector.selectNodeUponCreation = True
    self.pointerFiducialsSelector.addEnabled = True
    self.pointerFiducialsSelector.editEnabled = False
    self.pointerFiducialsSelector.removeEnabled = True
    self.pointerFiducialsSelector.renameEnabled = True
    self.pointerFiducialsSelector.noneEnabled = False
    self.pointerFiducialsSelector.showHidden = False
    self.pointerFiducialsSelector.showChildNodeTypes = False
    self.pointerFiducialsSelector.setMRMLScene( slicer.mrmlScene )
    pointRecorderFormLayout.addRow("Pointer Fiducials: ", self.pointerFiducialsSelector)  

    self.pointRecorderApplyButton = qt.QPushButton("Record Point")
    self.pointRecorderApplyButton.enabled = False
    pointRecorderFormLayout.addRow(self.pointRecorderApplyButton)
    
    # Texture Mapping
    self.textureMappingGroupBox = ctk.ctkCollapsibleGroupBox()
    self.textureMappingGroupBox.setTitle("TextureMapping")
    self.textureMappingGroupBox.collapsed = True
    textureMappingFormLayout = qt.QFormLayout(self.textureMappingGroupBox)
    playgroundFormLayout.addRow(self.textureMappingGroupBox)

    self.inputTextureSelector = slicer.qMRMLNodeComboBox()
    self.inputTextureSelector.nodeTypes = ["vtkMRMLVectorVolumeNode"]
    self.inputTextureSelector.selectNodeUponCreation = True
    self.inputTextureSelector.addEnabled = False
    self.inputTextureSelector.removeEnabled = False
    self.inputTextureSelector.noneEnabled = False
    self.inputTextureSelector.showHidden = False
    self.inputTextureSelector.showChildNodeTypes = False
    self.inputTextureSelector.setMRMLScene( slicer.mrmlScene )
    textureMappingFormLayout.addRow("Input Texture: ", self.inputTextureSelector)
    
    self.inputModelSelector = slicer.qMRMLNodeComboBox()
    self.inputModelSelector.nodeTypes = ["vtkMRMLModelNode"]
    self.inputModelSelector.selectNodeUponCreation = True
    self.inputModelSelector.addEnabled = False
    self.inputModelSelector.removeEnabled = False
    self.inputModelSelector.noneEnabled = False
    self.inputModelSelector.showHidden = False
    self.inputModelSelector.showChildNodeTypes = False
    self.inputModelSelector.setMRMLScene( slicer.mrmlScene )
    textureMappingFormLayout.addRow("Input Model: ", self.inputModelSelector)

    self.textureMappingApplyButton = qt.QPushButton("Apply")
    self.textureMappingApplyButton.enabled = False
    textureMappingFormLayout.addRow(self.textureMappingApplyButton)
    
    # Fiducial registration
    self.registrationGroupBox = ctk.ctkCollapsibleGroupBox()
    self.registrationGroupBox.setTitle("Fiducial Registration")
    self.registrationGroupBox.collapsed = True
    registrationFormLayout = qt.QFormLayout(self.registrationGroupBox)
    playgroundFormLayout.addRow(self.registrationGroupBox)
    
    self.registrationOutputSelector = slicer.qMRMLNodeComboBox()
    self.registrationOutputSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.registrationOutputSelector.selectNodeUponCreation = True
    self.registrationOutputSelector.addEnabled = True
    self.registrationOutputSelector.editEnabled = False
    self.registrationOutputSelector.removeEnabled = True
    self.registrationOutputSelector.renameEnabled = True
    self.registrationOutputSelector.noneEnabled = False
    self.registrationOutputSelector.showHidden = False
    self.registrationOutputSelector.showChildNodeTypes = False
    self.registrationOutputSelector.setMRMLScene( slicer.mrmlScene )
    registrationFormLayout.addRow("Output Transform: ", self.registrationOutputSelector)
        
    self.movingFiducialsSelector = slicer.qMRMLNodeComboBox()
    self.movingFiducialsSelector.nodeTypes = ["vtkMRMLMarkupsFiducialNode"]
    self.movingFiducialsSelector.selectNodeUponCreation = True
    self.movingFiducialsSelector.addEnabled = True
    self.movingFiducialsSelector.editEnabled = False
    self.movingFiducialsSelector.removeEnabled = True
    self.movingFiducialsSelector.renameEnabled = True
    self.movingFiducialsSelector.noneEnabled = False
    self.movingFiducialsSelector.showHidden = False
    self.movingFiducialsSelector.showChildNodeTypes = False
    self.movingFiducialsSelector.setMRMLScene( slicer.mrmlScene )
    registrationFormLayout.addRow("Moving Fiducials: ", self.movingFiducialsSelector)
    
    self.fixedFiducialsSelector = slicer.qMRMLNodeComboBox()
    self.fixedFiducialsSelector.nodeTypes = ["vtkMRMLMarkupsFiducialNode"]
    self.fixedFiducialsSelector.selectNodeUponCreation = True
    self.fixedFiducialsSelector.addEnabled = True
    self.fixedFiducialsSelector.editEnabled = False
    self.fixedFiducialsSelector.removeEnabled = True
    self.fixedFiducialsSelector.renameEnabled = True
    self.fixedFiducialsSelector.noneEnabled = False
    self.fixedFiducialsSelector.showHidden = False
    self.fixedFiducialsSelector.showChildNodeTypes = False
    self.fixedFiducialsSelector.setMRMLScene( slicer.mrmlScene )
    registrationFormLayout.addRow("Fixed Fiducials: ", self.fixedFiducialsSelector)
    
    self.errorLabel = qt.QLabel('0.0')
    registrationFormLayout.addRow("RMS Error: ", self.errorLabel)
    
    self.registrationApplyButton = qt.QPushButton("Apply")
    self.registrationApplyButton.enabled = False
    registrationFormLayout.addRow(self.registrationApplyButton)
    
    # PreviousToNextCalculator
    self.previousToNextCalculatorGroupBox = ctk.ctkCollapsibleGroupBox()
    self.previousToNextCalculatorGroupBox.setTitle("PreviousToNextCalculator")
    self.previousToNextCalculatorGroupBox.collapsed = True
    previousToNextCalculatorFormLayout = qt.QFormLayout(self.previousToNextCalculatorGroupBox)
    playgroundFormLayout.addRow(self.previousToNextCalculatorGroupBox)
    
    self.previousTransformSelector = slicer.qMRMLNodeComboBox()
    self.previousTransformSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.previousTransformSelector.selectNodeUponCreation = False
    self.previousTransformSelector.addEnabled = False
    self.previousTransformSelector.removeEnabled = False
    self.previousTransformSelector.noneEnabled = False
    self.previousTransformSelector.showHidden = False
    self.previousTransformSelector.showChildNodeTypes = False
    self.previousTransformSelector.setMRMLScene( slicer.mrmlScene )
    previousToNextCalculatorFormLayout.addRow("Select Previous: ", self.previousTransformSelector)
    
    self.nextTransformSelector = slicer.qMRMLNodeComboBox()
    self.nextTransformSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.nextTransformSelector.selectNodeUponCreation = False
    self.nextTransformSelector.addEnabled = False
    self.nextTransformSelector.removeEnabled = False
    self.nextTransformSelector.noneEnabled = False
    self.nextTransformSelector.showHidden = False
    self.nextTransformSelector.showChildNodeTypes = False
    self.nextTransformSelector.setMRMLScene( slicer.mrmlScene )
    previousToNextCalculatorFormLayout.addRow("Select Next: ", self.nextTransformSelector)
    
    self.previousToNextTransformSelector = slicer.qMRMLNodeComboBox()
    self.previousToNextTransformSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.previousToNextTransformSelector.selectNodeUponCreation = True
    self.previousToNextTransformSelector.addEnabled = True
    self.previousToNextTransformSelector.editEnabled = False
    self.previousToNextTransformSelector.removeEnabled = True
    self.previousToNextTransformSelector.renameEnabled = True
    self.previousToNextTransformSelector.noneEnabled = False
    self.previousToNextTransformSelector.showHidden = False
    self.previousToNextTransformSelector.showChildNodeTypes = False
    self.previousToNextTransformSelector.setMRMLScene( slicer.mrmlScene )
    previousToNextCalculatorFormLayout.addRow("Select PreviousToNext: ", self.previousToNextTransformSelector)
    
    self.calculatePreviousToNextButton = qt.QPushButton("Calculate")
    self.calculatePreviousToNextButton.enabled = False
    previousToNextCalculatorFormLayout.addRow(self.calculatePreviousToNextButton)  
    
    # TransformPolyData
    self.transformPolyDataGroupBox = ctk.ctkCollapsibleGroupBox()
    self.transformPolyDataGroupBox.setTitle("TransformPolyData")
    self.transformPolyDataGroupBox.collapsed = True
    transformPolyDataFormLayout = qt.QFormLayout(self.transformPolyDataGroupBox)
    playgroundFormLayout.addRow(self.transformPolyDataGroupBox)
    
    self.transformPolyDataModelSelector = slicer.qMRMLNodeComboBox()
    self.transformPolyDataModelSelector.nodeTypes = ["vtkMRMLModelNode"]
    self.transformPolyDataModelSelector.selectNodeUponCreation = False
    self.transformPolyDataModelSelector.addEnabled = False
    self.transformPolyDataModelSelector.removeEnabled = False
    self.transformPolyDataModelSelector.noneEnabled = False
    self.transformPolyDataModelSelector.showHidden = False
    self.transformPolyDataModelSelector.showChildNodeTypes = False
    self.transformPolyDataModelSelector.setMRMLScene( slicer.mrmlScene )
    transformPolyDataFormLayout.addRow("Select Model: ", self.transformPolyDataModelSelector)
    
    self.transformPolyDataSelector = slicer.qMRMLNodeComboBox()
    self.transformPolyDataSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.transformPolyDataSelector.selectNodeUponCreation = True
    self.transformPolyDataSelector.addEnabled = True
    self.transformPolyDataSelector.editEnabled = False
    self.transformPolyDataSelector.removeEnabled = True
    self.transformPolyDataSelector.renameEnabled = True
    self.transformPolyDataSelector.noneEnabled = False
    self.transformPolyDataSelector.showHidden = False
    self.transformPolyDataSelector.showChildNodeTypes = False
    self.transformPolyDataSelector.setMRMLScene( slicer.mrmlScene )
    transformPolyDataFormLayout.addRow("Select Transform: ", self.transformPolyDataSelector)
    
    self.applyTransformPolyDataButton = qt.QPushButton("Apply")
    self.applyTransformPolyDataButton.enabled = False
    transformPolyDataFormLayout.addRow(self.applyTransformPolyDataButton)
    
    # FiducialToModelDistance
    self.fiducialTestingGroupBox = ctk.ctkCollapsibleGroupBox()
    self.fiducialTestingGroupBox.setTitle("FiducialToModelDistance")
    self.fiducialTestingGroupBox.collapsed = True
    fiducialTestingFormLayout = qt.QFormLayout(self.fiducialTestingGroupBox)
    playgroundFormLayout.addRow(self.fiducialTestingGroupBox)
    
    self.fiducialTestingModelSelector = slicer.qMRMLNodeComboBox()
    self.fiducialTestingModelSelector.nodeTypes = ["vtkMRMLModelNode"]
    self.fiducialTestingModelSelector.selectNodeUponCreation = False
    self.fiducialTestingModelSelector.addEnabled = False
    self.fiducialTestingModelSelector.removeEnabled = False
    self.fiducialTestingModelSelector.noneEnabled = False
    self.fiducialTestingModelSelector.showHidden = False
    self.fiducialTestingModelSelector.showChildNodeTypes = False
    self.fiducialTestingModelSelector.setMRMLScene( slicer.mrmlScene )
    fiducialTestingFormLayout.addRow("Select Model: ", self.fiducialTestingModelSelector)
    
    self.outerPointSelector = slicer.qMRMLNodeComboBox()
    self.outerPointSelector.nodeTypes = ["vtkMRMLMarkupsFiducialNode"]
    self.outerPointSelector.selectNodeUponCreation = True
    self.outerPointSelector.addEnabled = True
    self.outerPointSelector.editEnabled = False
    self.outerPointSelector.removeEnabled = True
    self.outerPointSelector.renameEnabled = True
    self.outerPointSelector.noneEnabled = False
    self.outerPointSelector.showHidden = False
    self.outerPointSelector.showChildNodeTypes = False
    self.outerPointSelector.setMRMLScene( slicer.mrmlScene )
    fiducialTestingFormLayout.addRow("Select Point: ", self.outerPointSelector)
    
    self.calculateFiducialDistanceButton = qt.QPushButton("Calculate Distance")
    self.calculateFiducialDistanceButton.enabled = False
    fiducialTestingFormLayout.addRow(self.calculateFiducialDistanceButton)  

    # CastToDouble
    self.castToDoubleGroupBox = ctk.ctkCollapsibleGroupBox()
    self.castToDoubleGroupBox.setTitle("CastToDouble")
    self.castToDoubleGroupBox.collapsed = True
    castToDoubleFormLayout = qt.QFormLayout(self.castToDoubleGroupBox)
    playgroundFormLayout.addRow(self.castToDoubleGroupBox)
    
    self.castToDoubleSelector = slicer.qMRMLNodeComboBox()
    self.castToDoubleSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
    self.castToDoubleSelector.selectNodeUponCreation = False
    self.castToDoubleSelector.addEnabled = False
    self.castToDoubleSelector.removeEnabled = False
    self.castToDoubleSelector.noneEnabled = False
    self.castToDoubleSelector.showHidden = False
    self.castToDoubleSelector.showChildNodeTypes = False
    self.castToDoubleSelector.setMRMLScene( slicer.mrmlScene )
    castToDoubleFormLayout.addRow("Select Volume: ", self.castToDoubleSelector)
    
    self.castToDoubleButton = qt.QPushButton("Apply")
    self.castToDoubleButton.enabled = False
    castToDoubleFormLayout.addRow(self.castToDoubleButton)  
    
    ############################################### Connnections
    # Load for testing
    self.loadTestModelButton.connect('clicked(bool)', self.onLoadTestModelButton)
    # FirstPersonView
    self.stylusTipSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.recordFirstPersonViewPointButton.connect('clicked(bool)', self.onRecordFirstPersonViewPointButton)
    self.createFirstPersonViewButton.connect('clicked(bool)', self.onCreateFirstPersonViewButton)
    self.movingLRS_FiducialSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    # ModelTipToReferenceCreator
    self.modeldistanceToModelToolTipToToolSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.applyModelTipToReferenceCreatorByTransformsButton.connect('clicked(bool)', self.onApplyModelTipToReferenceCreatorByTransformsButton)
    self.applyModelTipToToolCreatorByFiducialsButton.connect('clicked(bool)', self.onApplymodelTipToToolCreatorByFiducialsButton)
    self.tooldistanceToModelToolTipToToolSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.toolToReferenceSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.modelTipToToolTipSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)    
    self.originFiducialSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.fromFiducialSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.toFiducialSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    # Record points
    self.pointerTransformSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.pointerFiducialsSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.pointRecorderApplyButton.connect('clicked(bool)', self.onPointRecorderApplyButton)
    # Texture Mapping
    self.textureMappingApplyButton.connect('clicked(bool)', self.onTextureMappingApplyButton)
    self.inputModelSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.inputTextureSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    # Fiducial registration
    self.registrationApplyButton.connect('clicked(bool)', self.onRegistrationApplyButton)
    self.registrationOutputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.movingFiducialsSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.fixedFiducialsSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    # PreviousToNextCalculator
    self.calculatePreviousToNextButton.connect('clicked(bool)', self.onCalculatePreviousToNextClicked)
    self.previousTransformSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.nextTransformSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.previousToNextTransformSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    # TransformPolyData
    self.applyTransformPolyDataButton.connect('clicked(bool)', self.onApplyTransformPolyDataClicked)
    self.transformPolyDataSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)   
    self.transformPolyDataModelSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)   
    # FiducialToModelDistance
    self.outerPointSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.fiducialTestingModelSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.calculateFiducialDistanceButton.connect('clicked(bool)', self.onCalculateFiducialDistanceClicked)
    # CastToDouble
    self.castToDoubleSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.castToDoubleButton.connect('clicked(bool)', self.onCastToDoubleClicked)
    
    # Add vertical spacer
    self.layout.addStretch(1)

    # Refresh Apply button state
    self.onSelect()
  def setup(self):
    self.logic = BoneEnhancerPyLogic()

    ScriptedLoadableModuleWidget.setup(self)
    
    # Add default algorithm parameters to Slicer.ini
    self.settings = slicer.app.userSettings() 
    self.settings.beginGroup(self.moduleName + '/Foroughi2007')
    if not self.settings.allKeys(): # If no keys     
      self.settings.setValue('SmoothingSigma', 5.0)
      self.settings.setValue('TransducerMargin', 60)
      self.settings.setValue('ShadowSigma', 6.0)
      self.settings.setValue('BoneThreshold', 0.4)
      self.settings.setValue('BlurredVsBLoG', 3)
      self.settings.setValue('ShadowVsIntensity', 5)      
    smoothingSigma = float(self.settings.value('SmoothingSigma'))
    transducerMargin = float(self.settings.value('TransducerMargin'))
    shadowSigma = float(self.settings.value('ShadowSigma'))
    boneThreshold = float(self.settings.value('BoneThreshold'))
    blurredVsBLoG = float(self.settings.value('BlurredVsBLoG'))
    shadowVsIntensity = float(self.settings.value('ShadowVsIntensity'))
    self.settings.endGroup()
    
    ############################################################# Define algorithms    
    self.foroughi2007 = AlgorithmParams("Foroughi2007 (with minor modifications)",
          {"Smoothing Sigma" : (1, 1, 1, 10, smoothingSigma, "Smoothing Sigma ToolTip"),
           "Transducer Margin" : (0, 1, 0, 300, transducerMargin, "Transducer Margin ToolTip"),
           "Shadow Sigma" : (1, 1, 1, 10, shadowSigma, "Shadow Sigma ToolTip"),
           "Bone Threshold" : (1, 0.1, 0, 1, boneThreshold, "Bone Threshold ToolTip"),
           "Blurred vs. BLoG" : (1, 0.1, 0, 10, blurredVsBLoG, "Blurred vs. BLoG ToolTip"),
           "Shadow vs. Intensity" : (1, 0.1, 0, 10, shadowVsIntensity, "Shadow vs. Intensity ToolTip")})            
    self.algorithms = [self.foroughi2007]
    
    # Set default algorithm
    self.defaultAlgorithm = self.foroughi2007
    
    ############################################################ BoneEnhancer
    boneEnhancerCollapsibleButton = ctk.ctkCollapsibleButton()
    boneEnhancerCollapsibleButton.text = "BoneEnhancer"
    self.layout.addWidget(boneEnhancerCollapsibleButton)
    boneEnhancerFormLayout = qt.QFormLayout(boneEnhancerCollapsibleButton)

    self.ultrasoundImageSelector = slicer.qMRMLNodeComboBox()
    self.ultrasoundImageSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
    self.ultrasoundImageSelector.selectNodeUponCreation = True
    self.ultrasoundImageSelector.addEnabled = False
    self.ultrasoundImageSelector.removeEnabled = False
    self.ultrasoundImageSelector.noneEnabled = False
    self.ultrasoundImageSelector.showHidden = False
    self.ultrasoundImageSelector.showChildNodeTypes = False
    self.ultrasoundImageSelector.setMRMLScene( slicer.mrmlScene )
    self.ultrasoundImageSelector.setToolTip( "Pick the input to the algorithm." )
    boneEnhancerFormLayout.addRow("Ultrasound Image: ", self.ultrasoundImageSelector)

    # Select algorithm
    self.algorithmGroupBox = ctk.ctkCollapsibleGroupBox()
    self.algorithmGroupBox.setTitle("Select Algorithm")
    algorithmFormLayout = qt.QFormLayout(self.algorithmGroupBox)
    boneEnhancerFormLayout.addRow(self.algorithmGroupBox)

    for algorithm in self.algorithms:     
      algorithmFormLayout.addRow(algorithm.GetRadioButton())
      algorithm.GetRadioButton().connect("toggled(bool)", self.onRadioButtonPressed)
      
    # Parameters
    self.parametersGroupBox = ctk.ctkCollapsibleGroupBox()
    self.parametersGroupBox.setTitle("Parameters")
    self.parametersFormLayout = qt.QFormLayout(self.parametersGroupBox)
    boneEnhancerFormLayout.addRow(self.parametersGroupBox)
    
    for algorithm in self.algorithms:     
      self.parametersFormLayout.addWidget(algorithm.getSliderWidget())
      algorithm.paramChangedCallback = self.onParameterChanged
                  
    # Runtime
    self.runtimeGroupBox = ctk.ctkCollapsibleGroupBox()
    self.runtimeGroupBox.setTitle("Runtime")
    runtimeFormLayout = qt.QFormLayout(self.runtimeGroupBox)
    boneEnhancerFormLayout.addRow(self.runtimeGroupBox)
    
    self.runtimeLabel = qt.QLabel()
    self.runtimeLabel.setText("... s.")
    self.runtimeLabel.setWordWrap(True)
    self.runtimeLabel.setStyleSheet("QLabel { background-color : black; \
                                           color : #66FF00; \
                                           height : 60px; \
                                           border-style: outset; \
                                           border-width: 5px; \
                                           border-radius: 10px; \
                                           font: bold 14px; \
                                           padding: 0px;\
                                           font-family : SimSun; \
                                           qproperty-alignment: AlignCenter}")
    runtimeFormLayout.addRow(self.runtimeLabel)
    
    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.toolTip = "Run the algorithm."
    self.applyButton.enabled = False
    self.applyButton.checkable = True
    boneEnhancerFormLayout.addRow(self.applyButton)
       
    ############################################################ Connections
    self.applyButton.connect('clicked(bool)', self.onApplyButton)
    self.ultrasoundImageSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    
    self.layout.addStretch(1)    
    self.defaultAlgorithm.GetRadioButton().checked = True
    self.onSelect()
Example #19
0
    def create(self):
        """create the segmentation helper box"""

        #
        # Master Frame
        #
        self.masterFrame = qt.QFrame(self.parent)
        self.masterFrame.setLayout(qt.QVBoxLayout())
        self.parent.layout().addWidget(self.masterFrame)

        #
        # the master volume selector
        #
        self.masterSelectorFrame = qt.QFrame(self.parent)
        self.masterSelectorFrame.setLayout(qt.QHBoxLayout())
        self.masterFrame.layout().addWidget(self.masterSelectorFrame)

        self.masterSelectorLabel = qt.QLabel("Master Volume: ",
                                             self.masterSelectorFrame)
        self.masterSelectorLabel.setToolTip(
            "Select the master volume (background grayscale scalar volume node)"
        )
        self.masterSelectorFrame.layout().addWidget(self.masterSelectorLabel)

        self.masterSelector = slicer.qMRMLNodeComboBox(
            self.masterSelectorFrame)
        # TODO
        self.masterSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.masterSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap",
                                         0)
        self.masterSelector.selectNodeUponCreation = False
        self.masterSelector.addEnabled = False
        self.masterSelector.removeEnabled = False
        self.masterSelector.noneEnabled = True
        self.masterSelector.showHidden = False
        self.masterSelector.showChildNodeTypes = False
        self.masterSelector.setMRMLScene(slicer.mrmlScene)
        # TODO: need to add a QLabel
        # self.masterSelector.SetLabelText( "Master Volume:" )
        self.masterSelector.setToolTip(
            "Pick the master structural volume to define the segmentation.  A label volume with the with \"-label\" appended to the name will be created if it doesn't already exist."
        )
        self.masterSelectorFrame.layout().addWidget(self.masterSelector)

        #
        # merge label name and set button
        #
        self.mergeFrame = qt.QFrame(self.masterFrame)
        self.mergeFrame.setLayout(qt.QHBoxLayout())
        self.masterFrame.layout().addWidget(self.mergeFrame)

        mergeNameToolTip = "Composite label map containing the merged structures (be aware that merge operations will overwrite any edits applied to this volume)"
        self.mergeNameLabel = qt.QLabel("Merge Volume: ", self.mergeFrame)
        self.mergeNameLabel.setToolTip(mergeNameToolTip)
        self.mergeFrame.layout().addWidget(self.mergeNameLabel)

        self.mergeName = qt.QLabel("", self.mergeFrame)
        self.mergeName.setToolTip(mergeNameToolTip)
        self.mergeFrame.layout().addWidget(self.mergeName)

        self.setMergeButton = qt.QPushButton("Set...", self.mergeFrame)
        self.setMergeButton.setToolTip(
            "Set the merge volume to use with this master.")
        self.mergeFrame.layout().addWidget(self.setMergeButton)

        #
        # Structures Frame
        #

        self.structuresFrame = ctk.ctkCollapsibleGroupBox(self.masterFrame)
        self.structuresFrame.title = "Per-Structure Volumes"
        self.structuresFrame.collapsed = True
        self.structuresFrame.setLayout(qt.QVBoxLayout())
        self.masterFrame.layout().addWidget(self.structuresFrame)

        # buttons frame

        self.structureButtonsFrame = qt.QFrame(self.structuresFrame)
        self.structureButtonsFrame.setLayout(qt.QHBoxLayout())
        self.structuresFrame.layout().addWidget(self.structureButtonsFrame)

        # add button

        self.addStructureButton = qt.QPushButton("Add Structure",
                                                 self.structureButtonsFrame)
        self.addStructureButton.setToolTip(
            "Add a label volume for a structure to edit")
        self.structureButtonsFrame.layout().addWidget(self.addStructureButton)

        # split button

        self.splitButton = qt.QPushButton("Split Merge Volume",
                                          self.structuresFrame)
        self.splitButton.setToolTip(
            "Split distinct labels from merge volume into new volumes")
        self.structureButtonsFrame.layout().addWidget(self.splitButton)

        # structures view

        self.structuresView = qt.QTreeView()
        self.structuresView.sortingEnabled = True
        self.structuresFrame.layout().addWidget(self.structuresView)

        # all buttons frame

        self.allButtonsFrame = qt.QFrame(self.structuresFrame)
        self.allButtonsFrame.setLayout(qt.QHBoxLayout())
        self.structuresFrame.layout().addWidget(self.allButtonsFrame)

        # delete structures button

        self.deleteStructuresButton = qt.QPushButton("Delete Structures",
                                                     self.allButtonsFrame)
        self.deleteStructuresButton.setToolTip(
            "Delete all the structure volumes from the scene.\n\nNote: to delete individual structure volumes, use the Data Module."
        )
        self.allButtonsFrame.layout().addWidget(self.deleteStructuresButton)

        # merge button

        self.mergeButton = qt.QPushButton("Merge All", self.allButtonsFrame)
        self.mergeButton.setToolTip("Merge all structures into Merge Volume")
        self.allButtonsFrame.layout().addWidget(self.mergeButton)

        # merge and build button

        self.mergeAndBuildButton = qt.QPushButton("Merge And Build",
                                                  self.allButtonsFrame)
        self.mergeAndBuildButton.setToolTip(
            "Merge all structures into Merge Volume and build models from all structures"
        )
        self.allButtonsFrame.layout().addWidget(self.mergeAndBuildButton)
        # options frame

        self.optionsFrame = qt.QFrame(self.structuresFrame)
        self.optionsFrame.setLayout(qt.QHBoxLayout())
        self.structuresFrame.layout().addWidget(self.optionsFrame)

        # replace models button

        self.replaceModels = qt.QCheckBox("Replace Models", self.optionsFrame)
        self.replaceModels.setToolTip(
            "Replace any existing models when building")
        self.replaceModels.setChecked(1)
        self.optionsFrame.layout().addWidget(self.replaceModels)

        #
        # signals, slots, and observers
        #

        # signals/slots on qt widgets are automatically when
        # this class destructs, but observers of the scene must be explicitly
        # removed in the destuctor

        # node selected
        self.masterSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                    self.onSelect)
        # buttons pressed
        self.addStructureButton.connect("clicked()", self.addStructure)
        self.deleteStructuresButton.connect("clicked()", self.deleteStructures)
        # selection changed event
        self.structuresView.connect("clicked(QModelIndex)",
                                    self.onStructuresClicked)
        # invoked event
        self.splitButton.connect("clicked()", self.split)
        self.mergeButton.connect("clicked()", self.mergeStructures)
        self.mergeAndBuildButton.connect("clicked()", self.onMergeAndBuild)
        self.setMergeButton.connect("clicked()", self.labelSelectDialog)

        # new scene, node added or removed events
        # TODO: allow observers on speific events: 66000, 66001, 66002
        tag = slicer.mrmlScene.AddObserver("ModifiedEvent",
                                           self.updateStructures)
        self.observerTags.append((slicer.mrmlScene, tag))

        # so buttons will initially be disabled
        self.master = None
        self.updateStructures()
  def setup(self):
    ScriptedLoadableModuleWidget.setup(self)
    pointSetProcessingCollapsibleButton = ctk.ctkCollapsibleButton()
    pointSetProcessingCollapsibleButton.text = "Surface Reconstruction from Unorganized Points"
    self.layout.addWidget(pointSetProcessingCollapsibleButton)
    pointSetProcessingFormLayout = qt.QFormLayout(pointSetProcessingCollapsibleButton)

    # Input
    self.inputSelector = slicer.qMRMLNodeComboBox()
    self.inputSelector.nodeTypes = ( ("vtkMRMLModelNode"), "" )
    self.inputSelector.selectNodeUponCreation = True
    self.inputSelector.addEnabled = False
    self.inputSelector.removeEnabled = False
    self.inputSelector.noneEnabled = False
    self.inputSelector.showHidden = False
    self.inputSelector.showChildNodeTypes = False
    self.inputSelector.setMRMLScene( slicer.mrmlScene )
    self.inputSelector.setToolTip( "Pick the input to the algorithm." )
    pointSetProcessingFormLayout.addRow("Input Model: ", self.inputSelector)
    
    self.nbrOfPointsLabel = qt.QLabel('Number of Points in Input Model: - ')
    pointSetProcessingFormLayout.addRow(self.nbrOfPointsLabel)

    self.inputPointSizeSlider = ctk.ctkSliderWidget()
    self.inputPointSizeSlider.setDecimals(0)
    self.inputPointSizeSlider.singleStep = 1
    self.inputPointSizeSlider.minimum = 1
    self.inputPointSizeSlider.maximum = 10
    self.inputPointSizeSlider.value = 1
    pointSetProcessingFormLayout.addRow('Input Model Point Size: ', self.inputPointSizeSlider)
    
    # Runtime
    self.runtimeGroupBox = qt.QGroupBox('Runtime')    
    runtimeFormLayout = qt.QFormLayout(self.runtimeGroupBox)
    pointSetProcessingFormLayout.addRow(self.runtimeGroupBox)
    
    self.runtimeLabel = qt.QLabel()
    self.runtimeLabel.setText("... s.")
    self.runtimeLabel.setWordWrap(True)
    self.runtimeLabel.setStyleSheet("QLabel { background-color : black; \
                                           color : #66FF00; \
                                           height : 60px; \
                                           border-style: outset; \
                                           border-width: 5px; \
                                           border-radius: 10px; \
                                           font: bold 14px; \
                                           padding: 0px;\
                                           font-family : SimSun; \
                                           qproperty-alignment: AlignCenter}")
    runtimeFormLayout.addRow(self.runtimeLabel)    
    
    # Downsample
    self.downSampleGroupBox = ctk.ctkCollapsibleGroupBox()
    self.downSampleGroupBox.setTitle("Downsample Input Model")
    downSampleFormLayout = qt.QFormLayout(self.downSampleGroupBox)
    pointSetProcessingFormLayout.addRow(self.downSampleGroupBox)    
    
    self.toleranceCleanSlider = ctk.ctkSliderWidget()
    self.toleranceCleanSlider.setDecimals(2)
    self.toleranceCleanSlider.singleStep = 0.01
    self.toleranceCleanSlider.minimum = 0.0
    self.toleranceCleanSlider.maximum = 1.0
    self.toleranceCleanSlider.value = 0.01
    self.toleranceCleanSlider.setToolTip('')
    self.toleranceCleanSlider.enabled = True
    downSampleFormLayout.addRow('Tolerance: ', self.toleranceCleanSlider)
    
    self.vtkCleanPolyDataButton = qt.QPushButton("Apply")
    self.vtkCleanPolyDataButton.enabled = False
    self.vtkCleanPolyDataButton.checkable = True
    downSampleFormLayout.addRow(self.vtkCleanPolyDataButton)    

    # Outlier Removal
    self.outlierRemovalGroupBox = ctk.ctkCollapsibleGroupBox()
    self.outlierRemovalGroupBox.setTitle("Outlier Removal")
    outlierRemovalFormLayout = qt.QFormLayout(self.outlierRemovalGroupBox)
    pointSetProcessingFormLayout.addRow(self.outlierRemovalGroupBox)
    
    self.percentToRemoveSlider = ctk.ctkSliderWidget()
    self.percentToRemoveSlider.setDecimals(2)
    self.percentToRemoveSlider.singleStep = 0.01
    self.percentToRemoveSlider.minimum = 0.0
    self.percentToRemoveSlider.maximum = 1.0
    self.percentToRemoveSlider.value = 0.01
    self.percentToRemoveSlider.setToolTip('')
    self.percentToRemoveSlider.enabled = True
    outlierRemovalFormLayout.addRow('Percent to Remove: ', self.percentToRemoveSlider)
    
    self.vtkPointSetOutlierRemovalButton = qt.QPushButton("Apply")
    self.vtkPointSetOutlierRemovalButton.enabled = False
    self.vtkPointSetOutlierRemovalButton.checkable = True
    outlierRemovalFormLayout.addRow(self.vtkPointSetOutlierRemovalButton)  
        
    # Compute Normals
    self.normalsGroupBox = ctk.ctkCollapsibleGroupBox()
    self.normalsGroupBox.setTitle("Compute Normals")
    normalsFormLayout = qt.QFormLayout(self.normalsGroupBox)
    pointSetProcessingFormLayout.addRow(self.normalsGroupBox)
    
    self.normalsTabWidget = qt.QTabWidget()
    normalsFormLayout.addRow(self.normalsTabWidget)

    # vtkPointSetNormalEstimationAndOrientation
    self.vtkPointSetNormalEstimationWidget = qt.QWidget()
    vtkPointSetNormalEstimationFormLayout = qt.QFormLayout(self.vtkPointSetNormalEstimationWidget)
    normalsFormLayout.addRow(self.vtkPointSetNormalEstimationWidget)
    self.normalsTabWidget.addTab(self.vtkPointSetNormalEstimationWidget, "vtkPointSetNormalEstimationAndOrientation")    
        
    self.modeTypeComboBox = qt.QComboBox()
    self.modeTypeComboBox.addItem('Fixed')  
    self.modeTypeComboBox.addItem('Radius')
    self.modeTypeComboBox.setCurrentIndex(1)
    self.modeTypeComboBox.setToolTip('')    
    vtkPointSetNormalEstimationFormLayout.addRow('Mode Type: ', self.modeTypeComboBox)
    
    self.numberOfNeighborsSlider = ctk.ctkSliderWidget()
    self.numberOfNeighborsSlider.setDecimals(0)
    self.numberOfNeighborsSlider.singleStep = 1
    self.numberOfNeighborsSlider.minimum = 1
    self.numberOfNeighborsSlider.maximum = 20
    self.numberOfNeighborsSlider.value = 4
    self.numberOfNeighborsSlider.setToolTip('')
    self.numberOfNeighborsSlider.enabled = False
    vtkPointSetNormalEstimationFormLayout.addRow('Fixed Neighbors: ', self.numberOfNeighborsSlider)
    
    self.radiusSlider = ctk.ctkSliderWidget()
    self.radiusSlider.setDecimals(2)
    self.radiusSlider.singleStep = 0.01
    self.radiusSlider.minimum = 0
    self.radiusSlider.maximum = 50
    self.radiusSlider.value = 1.0
    self.radiusSlider.setToolTip('')
    vtkPointSetNormalEstimationFormLayout.addRow('Radius: ', self.radiusSlider)
    
    self.graphTypeComboBox = qt.QComboBox()
    self.graphTypeComboBox.addItem('Riemann')  
    self.graphTypeComboBox.addItem('KNN')
    self.graphTypeComboBox.setCurrentIndex(1)
    self.graphTypeComboBox.setToolTip('')    
    vtkPointSetNormalEstimationFormLayout.addRow('Graph Type: ', self.graphTypeComboBox)
    
    self.knnSlider = ctk.ctkSliderWidget()
    self.knnSlider.setDecimals(0)
    self.knnSlider.singleStep = 1
    self.knnSlider.minimum = 1
    self.knnSlider.maximum = 100
    self.knnSlider.value = 5
    self.knnSlider.setToolTip('')
    vtkPointSetNormalEstimationFormLayout.addRow('K-Nearest Neighbors: ', self.knnSlider)
    
    self.vtkPointSetNormalEstimationButton = qt.QPushButton("Apply")
    self.vtkPointSetNormalEstimationButton.enabled = False
    self.vtkPointSetNormalEstimationButton.checkable = True
    vtkPointSetNormalEstimationFormLayout.addRow(self.vtkPointSetNormalEstimationButton)    

    # vtkPolyDataNormals
    self.vtkPolyDataNormalsWidget = qt.QWidget()
    vtkPolyDataNormalsFormLayout = qt.QFormLayout(self.vtkPolyDataNormalsWidget)
    normalsFormLayout.addRow(self.vtkPolyDataNormalsWidget)
    self.normalsTabWidget.addTab(self.vtkPolyDataNormalsWidget, "vtkPolyDataNormals")    
    
    self.featureAngleSlider = ctk.ctkSliderWidget()
    self.featureAngleSlider.setDecimals(2)
    self.featureAngleSlider.singleStep = 0.01
    self.featureAngleSlider.minimum = 0
    self.featureAngleSlider.maximum = 360
    self.featureAngleSlider.value = 0.1
    self.featureAngleSlider.setToolTip('')
    vtkPolyDataNormalsFormLayout.addRow('Feature Angle: ', self.featureAngleSlider)    
    
    self.splittingComboBox = qt.QComboBox()
    self.splittingComboBox.addItem('False')
    self.splittingComboBox.addItem('True')  
    self.splittingComboBox.setCurrentIndex(1)
    self.splittingComboBox.setToolTip('')    
    vtkPolyDataNormalsFormLayout.addRow('Splitting: ', self.splittingComboBox)
    
    self.consistencyComboBox = qt.QComboBox()
    self.consistencyComboBox.addItem('False')
    self.consistencyComboBox.addItem('True')  
    self.consistencyComboBox.setCurrentIndex(0)
    self.consistencyComboBox.setToolTip('')    
    vtkPolyDataNormalsFormLayout.addRow('Consistency: ', self.consistencyComboBox)
    
    self.autoOrientNormalsComboBox = qt.QComboBox()
    self.autoOrientNormalsComboBox.addItem('False')
    self.autoOrientNormalsComboBox.addItem('True') 
    self.autoOrientNormalsComboBox.setCurrentIndex(0)    
    self.autoOrientNormalsComboBox.setToolTip('')    
    vtkPolyDataNormalsFormLayout.addRow('Auto-Orient Normals: ', self.autoOrientNormalsComboBox)
    
    self.computePointNormalsComboBox = qt.QComboBox()
    self.computePointNormalsComboBox.addItem('False')
    self.computePointNormalsComboBox.addItem('True') 
    self.computePointNormalsComboBox.setCurrentIndex(1)    
    self.computePointNormalsComboBox.setToolTip('')    
    vtkPolyDataNormalsFormLayout.addRow('Compute Point Normals: ', self.computePointNormalsComboBox)
    
    self.computeCellNormalsComboBox = qt.QComboBox()
    self.computeCellNormalsComboBox.addItem('False')
    self.computeCellNormalsComboBox.addItem('True')
    self.computeCellNormalsComboBox.setCurrentIndex(0)    
    self.computeCellNormalsComboBox.setToolTip('')    
    vtkPolyDataNormalsFormLayout.addRow('Compute Cell Normals: ', self.computeCellNormalsComboBox)
    
    self.flipNormalsComboBox = qt.QComboBox()
    self.flipNormalsComboBox.addItem('False')
    self.flipNormalsComboBox.addItem('True')  
    self.flipNormalsComboBox.setCurrentIndex(0)
    self.flipNormalsComboBox.setToolTip('')    
    vtkPolyDataNormalsFormLayout.addRow('Flip Normals: ', self.flipNormalsComboBox)
    
    self.nonManifoldTraversalComboBox = qt.QComboBox()
    self.nonManifoldTraversalComboBox.addItem('False')
    self.nonManifoldTraversalComboBox.addItem('True') 
    self.nonManifoldTraversalComboBox.setCurrentIndex(1)    
    self.nonManifoldTraversalComboBox.setToolTip('')    
    vtkPolyDataNormalsFormLayout.addRow('Non-Manifold Traversal: ', self.nonManifoldTraversalComboBox)
    
    self.vtkPolyDataNormalsButton = qt.QPushButton("Apply")
    self.vtkPolyDataNormalsButton.enabled = False
    self.vtkPolyDataNormalsButton.checkable = True
    vtkPolyDataNormalsFormLayout.addRow(self.vtkPolyDataNormalsButton)  
    
    self.normalsVisibleCheckBox = qt.QCheckBox('Arrows Visibility: ')
    self.normalsVisibleCheckBox.checked = True
    self.normalsVisibleCheckBox.enabled = True
    self.normalsVisibleCheckBox.setLayoutDirection(1)
    normalsFormLayout.addRow(self.normalsVisibleCheckBox)
    
    # Compute Surface
    self.surfaceGroupBox = ctk.ctkCollapsibleGroupBox()
    self.surfaceGroupBox.setTitle("Compute Surface")
    surfaceFormLayout = qt.QFormLayout(self.surfaceGroupBox)
    pointSetProcessingFormLayout.addRow(self.surfaceGroupBox)

    self.surfaceTabWidget = qt.QTabWidget()
    surfaceFormLayout.addRow(self.surfaceTabWidget)
    
    # vtkPoissionReconstruction    
    self.vtkPoissionReconstructionWidget = qt.QWidget()
    vtkPoissionReconstructionFormLayout = qt.QFormLayout(self.vtkPoissionReconstructionWidget)
    surfaceFormLayout.addRow(self.vtkPoissionReconstructionWidget)
    self.surfaceTabWidget.addTab(self.vtkPoissionReconstructionWidget, "vtkPoissionReconstruction")   
    
    self.depthSlider = ctk.ctkSliderWidget()
    self.depthSlider.setDecimals(0)
    self.depthSlider.singleStep = 1
    self.depthSlider.minimum = 1
    self.depthSlider.maximum = 14
    self.depthSlider.value = 8
    self.depthSlider.setToolTip('This integer controls the reconstruction depth; the maximum depth of the tree that will be used for surface reconstruction. Running at depth d corresponds to solving on a voxel grid whose resolution is no larger than 2^d x 2^d x 2^d. Note that since the reconstructor adapts the octree to the sampling density, the specified reconstruction depth is only an upper bound.')
    vtkPoissionReconstructionFormLayout.addRow('Depth: ', self.depthSlider)
    
    self.scaleSlider = ctk.ctkSliderWidget()
    self.scaleSlider.setDecimals(2)
    self.scaleSlider.singleStep = 0.01
    self.scaleSlider.minimum = 0
    self.scaleSlider.maximum = 10
    self.scaleSlider.value = 1.25
    self.scaleSlider.setToolTip('This floating point value specifies the ratio between the diameter of the cube used for reconstruction and the diameter of the samples bounding cube.')
    vtkPoissionReconstructionFormLayout.addRow('Scale: ', self.scaleSlider)    
    
    self.solverDivideSlider = ctk.ctkSliderWidget()
    self.solverDivideSlider.setDecimals(0)
    self.solverDivideSlider.singleStep = 1
    self.solverDivideSlider.minimum = 1
    self.solverDivideSlider.maximum = 20
    self.solverDivideSlider.value = 8
    self.solverDivideSlider.setToolTip('Solver subdivision depth; This integer argument specifies the depth at which a block Gauss-Seidel solver is used to solve the Laplacian equation. Using this parameter helps reduce the memory overhead at the cost of a small increase in reconstruction time. (In practice, we have found that for reconstructions of depth 9 or higher a subdivide depth of 7 or 8 can greatly reduce the memory usage.)')
    vtkPoissionReconstructionFormLayout.addRow('Solver Divide: ', self.solverDivideSlider)   
    
    self.isoDivideSlider = ctk.ctkSliderWidget()
    self.isoDivideSlider.setDecimals(0)
    self.isoDivideSlider.singleStep = 1
    self.isoDivideSlider.minimum = 1
    self.isoDivideSlider.maximum = 20
    self.isoDivideSlider.value = 8
    self.isoDivideSlider.setToolTip('Iso-surface extraction subdivision depth; This integer argument specifies the depth at which a block isosurface extractor should be used to extract the iso-surface. Using this parameter helps reduce the memory overhead at the cost of a small increase in extraction time. (In practice, we have found that for reconstructions of depth 9 or higher a subdivide depth of 7 or 8 can greatly reduce the memory usage.)')
    vtkPoissionReconstructionFormLayout.addRow('Iso Divide: ', self.isoDivideSlider)   
 
    self.samplesPerNodeSlider = ctk.ctkSliderWidget()
    self.samplesPerNodeSlider.setDecimals(2)
    self.samplesPerNodeSlider.singleStep = 0.1
    self.samplesPerNodeSlider.minimum = 1
    self.samplesPerNodeSlider.maximum = 30
    self.samplesPerNodeSlider.value = 1.0
    self.samplesPerNodeSlider.setToolTip('Minimum number of samples; This floating point value specifies the minimum number of sample points that should fall within an octree node as the octree construction is adapted to sampling density. For noise-free samples, small values in the range [1.0 - 5.0] can be used. For more noisy samples, larger values in the range [15.0 - 20.0] may be needed to provide a smoother, noise-reduced, reconstruction.')
    vtkPoissionReconstructionFormLayout.addRow('Samples per Node: ', self.samplesPerNodeSlider)   
    
    self.confidenceComboBox = qt.QComboBox()
    self.confidenceComboBox.addItem('False')
    self.confidenceComboBox.addItem('True')  
    self.confidenceComboBox.setToolTip('Enabling tells the reconstructor to use the size of the normals as confidence information. When the flag is not enabled, all normals are normalized to have unit-length prior to reconstruction.')    
    vtkPoissionReconstructionFormLayout.addRow('Confidence: ', self.confidenceComboBox)
   
    self.verboseComboBox = qt.QComboBox()
    self.verboseComboBox.addItem('False')
    self.verboseComboBox.addItem('True')  
    self.verboseComboBox.setToolTip('Enabling this flag provides a more verbose description of the running times and memory usages of individual components of the surface reconstructor.')    
    vtkPoissionReconstructionFormLayout.addRow('Verbose: ', self.verboseComboBox)
    
    self.vtkPoissionReconstructionButton = qt.QPushButton("Apply")
    self.vtkPoissionReconstructionButton.enabled = False
    self.vtkPoissionReconstructionButton.checkable = True
    vtkPoissionReconstructionFormLayout.addRow(self.vtkPoissionReconstructionButton)    

    # vtkDelaunay3D
    self.vtkDelaunay3DWidget = qt.QWidget()
    vtkDelaunay3DFormLayout = qt.QFormLayout(self.vtkDelaunay3DWidget)
    surfaceFormLayout.addRow(self.vtkDelaunay3DWidget)
    self.surfaceTabWidget.addTab(self.vtkDelaunay3DWidget, "vtkDelaunay3D") 
    
    self.alphaSlider = ctk.ctkSliderWidget()
    self.alphaSlider.setDecimals(1)
    self.alphaSlider.singleStep = 0.1
    self.alphaSlider.minimum = 0.0
    self.alphaSlider.maximum = 100.0
    self.alphaSlider.value = 0.0
    self.alphaSlider.setToolTip('')
    vtkDelaunay3DFormLayout.addRow('Alpha: ', self.alphaSlider)   
    
    self.toleranceSlider = ctk.ctkSliderWidget()
    self.toleranceSlider.setDecimals(2)
    self.toleranceSlider.singleStep = 0.01
    self.toleranceSlider.minimum = 0.0
    self.toleranceSlider.maximum = 1.0
    self.toleranceSlider.value = 0.0
    self.toleranceSlider.setToolTip('')
    vtkDelaunay3DFormLayout.addRow('Tolerance: ', self.toleranceSlider)   
    
    self.offsetSlider = ctk.ctkSliderWidget()
    self.offsetSlider.setDecimals(1)
    self.offsetSlider.singleStep = 0.1
    self.offsetSlider.minimum = 0.0
    self.offsetSlider.maximum = 10.0
    self.offsetSlider.value = 2.5
    self.offsetSlider.setToolTip('')
    vtkDelaunay3DFormLayout.addRow('Offset: ', self.offsetSlider)   
    
    self.boundingComboBox = qt.QComboBox()
    self.boundingComboBox.addItem('False')
    self.boundingComboBox.addItem('True')  
    self.boundingComboBox.setCurrentIndex(0)    
    self.boundingComboBox.setToolTip('')    
    vtkDelaunay3DFormLayout.addRow('Bounding Triangulations: ', self.boundingComboBox)
    
    self.vtkDelaunay3DButton = qt.QPushButton("Apply")
    self.vtkDelaunay3DButton.enabled = False
    self.vtkDelaunay3DButton.checkable = True
    vtkDelaunay3DFormLayout.addRow(self.vtkDelaunay3DButton)    
    
    self.surfaceVisibleCheckBox = qt.QCheckBox('Surface Visibility: ')
    self.surfaceVisibleCheckBox.checked = True
    self.surfaceVisibleCheckBox.enabled = True
    self.surfaceVisibleCheckBox.setLayoutDirection(1)
    surfaceFormLayout.addRow(self.surfaceVisibleCheckBox)
    
    # connections
    self.vtkCleanPolyDataButton.connect('clicked(bool)', self.vtkCleanPolyDataClicked)
    self.vtkPointSetOutlierRemovalButton.connect('clicked(bool)', self.vtkPointSetOutlierRemovalClicked)
    self.vtkPointSetNormalEstimationButton.connect('clicked(bool)', self.vtkPointSetNormalEstimationClicked)
    self.vtkPolyDataNormalsButton.connect('clicked(bool)', self.vtkPolyDataNormalsClicked)
    self.vtkPoissionReconstructionButton.connect('clicked(bool)', self.vtkPoissionReconstructionClicked)
    self.vtkDelaunay3DButton.connect('clicked(bool)', self.vtkDelaunay3DClicked)
    self.inputSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onSelect)
    self.graphTypeComboBox.connect('currentIndexChanged(const QString &)', self.onGraphTypeChanged)
    self.modeTypeComboBox.connect('currentIndexChanged(const QString &)', self.onModeChanged)
    self.surfaceVisibleCheckBox.connect('stateChanged(int)', self.onSurfaceVisible)
    self.normalsVisibleCheckBox.connect('stateChanged(int)', self.onNormalsVisible)
    self.inputPointSizeSlider.connect('valueChanged (double)', self.onInputPointSliderModified)
            
    # Add vertical spacer
    self.layout.addStretch(1)

    # Refresh 
    self.onSelect()
        
    lm=slicer.app.layoutManager()
    lm.setLayout(4) # One 3D-view    
Example #21
0
  def setup(self):
    # # Instantiate and connect widgets 
    # ---------------------------- Window Settings -----------------------------
    initializationCollapsibleButton = ctk.ctkCollapsibleButton()
    initializationCollapsibleButton.text = "Window Initialization"
    self.layout.addWidget(initializationCollapsibleButton)    
    initializationLayout = qt.QFormLayout(initializationCollapsibleButton)
    
    self.stereoCheckBox = qt.QCheckBox()
    initializationLayout.addRow("Stereoscopic mode:", self.stereoCheckBox)        
    
    self.startButton = qt.QPushButton("Create Windows")
    initializationLayout.addRow(self.startButton)
    
    self.showButton = qt.QPushButton("Show Windows")
    initializationLayout.addRow(self.showButton)
    
    self.hideButton = qt.QPushButton("Hide Windows")
    initializationLayout.addRow(self.hideButton)
    
    # ---------------------------- Stereo Settings -----------------------------
    stereoCollapsibleButton = ctk.ctkCollapsibleButton()
    stereoCollapsibleButton.text = "Stereoscopic Settings"
    self.layout.addWidget(stereoCollapsibleButton)
    stereoSettingsLayout = qt.QFormLayout(stereoCollapsibleButton)        
    
    self.upViewAngleButton = qt.QPushButton("Increase View Angle")
    stereoSettingsLayout.addWidget(self.upViewAngleButton)
    
    self.downViewAngleButton = qt.QPushButton("Decrease View Angle")
    stereoSettingsLayout.addWidget(self.downViewAngleButton)
    
    # ------------------- Transform and Tracking Settings ----------------------
    trackingCollapsibleButton = ctk.ctkCollapsibleButton()
    trackingCollapsibleButton.text = "Update Settings"
    self.layout.addWidget(trackingCollapsibleButton)
    trackingSettingsLayout = qt.QFormLayout(trackingCollapsibleButton)    
    
    self.followNodeSelector = slicer.qMRMLNodeComboBox()
    self.followNodeSelector.nodeTypes = ["vtkMRMLMarkupsFiducialNode", "vtkMRMLLinearTransformNode"]
    self.followNodeSelector.selectNodeUponCreation = False
    self.followNodeSelector.noneEnabled = False
    self.followNodeSelector.addEnabled = True
    self.followNodeSelector.showHidden = False
    self.followNodeSelector.setMRMLScene( slicer.mrmlScene )
    self.followNodeSelector.setToolTip( "Pick Fiducial Node or Linear Transform to follow" )
    trackingSettingsLayout.addRow("Path node (transform or fiducial)", self.followNodeSelector)
    
    self.oculusNodeSelector = slicer.qMRMLNodeComboBox()
    self.oculusNodeSelector.nodeTypes = ["vtkMRMLLinearTransformNode"]
    self.oculusNodeSelector.selectNodeUponCreation = False
    self.oculusNodeSelector.noneEnabled = False
    self.oculusNodeSelector.addEnabled = True
    self.oculusNodeSelector.showHidden = False
    self.oculusNodeSelector.setMRMLScene( slicer.mrmlScene )
    self.oculusNodeSelector.setToolTip( "Pick Transform for Oculus Rift" )
    trackingSettingsLayout.addRow("Oculus Transform", self.oculusNodeSelector)

    self.updateTrackingButton = qt.QPushButton("Update Tracking")
    trackingSettingsLayout.addWidget(self.updateTrackingButton)
    
    # ---------------------------- Update Export Image Settings -----------------------------
    updatesCollapsibleButton = ctk.ctkCollapsibleButton()
    updatesCollapsibleButton.text = "Update Settings"
    self.layout.addWidget(updatesCollapsibleButton)
    updateSettingsLayout = qt.QFormLayout(updatesCollapsibleButton)
    
    self.createButton = qt.QPushButton("Create Image")
    updateSettingsLayout.addWidget(self.createButton)
    
    self.startRepeatButton = qt.QPushButton("Continually Create Images")
    updateSettingsLayout.addWidget(self.startRepeatButton)

    self.stopRepeatButton = qt.QPushButton("Stop Creating Images")
    updateSettingsLayout.addWidget(self.stopRepeatButton)
    
    # ---------------------------- Lighting Settings -----------------------------
    lightingCollapsibleButton = ctk.ctkCollapsibleButton()
    lightingCollapsibleButton.text = "Lighting Settings"
    self.layout.addWidget(lightingCollapsibleButton)
    lightingSettingsLayout = qt.QFormLayout(lightingCollapsibleButton)
    
    #       ----- Manual Lighting Control ------
    manualLightingGroupBox = ctk.ctkCollapsibleGroupBox()
    lightingSettingsLayout.addWidget(manualLightingGroupBox)
    manualLightingLayout = qt.QFormLayout(manualLightingGroupBox)
    
    self.lightSliderX = ctk.ctkSliderWidget()
    self.lightSliderX.maximum = 500
    self.lightSliderX.minimum = -500
    self.lightSliderX.value = 0
    self.lightSliderX.tracking = True
    manualLightingLayout.addRow("X", self.lightSliderX)
    
    self.lightSliderY = ctk.ctkSliderWidget()
    self.lightSliderY.maximum = 500
    self.lightSliderY.minimum = -500
    self.lightSliderY.value = 0
    self.lightSliderY.tracking = True
    manualLightingLayout.addRow("Y", self.lightSliderY)

    self.lightSliderZ = ctk.ctkSliderWidget()
    self.lightSliderZ.maximum = 500
    self.lightSliderZ.minimum = -500
    self.lightSliderZ.value = 300
    self.lightSliderZ.tracking = True
    manualLightingLayout.addRow("Z", self.lightSliderZ)    
    
    # # Connections
    self.startButton.connect('clicked(bool)', self.createWindows)
    self.showButton.connect('clicked(bool)', self.showWindows)
    self.hideButton.connect('clicked(bool)', self.hideWindows)
    
    self.upViewAngleButton.connect('clicked(bool)', self.upViewAngle)
    self.downViewAngleButton.connect('clicked(bool)', self.downViewAngle)    
    
    self.createButton.connect('clicked(bool)', self.createWindowImages)
    self.startRepeatButton.connect('clicked(bool)', self.startCreatingImages)
    self.stopRepeatButton.connect('clicked(bool)', self.stopCreatingImages)
    
    self.followNodeSelector.connect('currentNodeChanged(bool)', self.setFollowNode)
    self.updateTrackingButton.connect('clicked(bool)', self.updateTracking)   
    
    self.lightSliderX.connect('valueChanged(double)', self.onLightSliderChanged)
    self.lightSliderY.connect('valueChanged(double)', self.onLightSliderChanged)
    self.lightSliderZ.connect('valueChanged(double)', self.onLightSliderChanged)
    

    self.timer = qt.QTimer()
    self.timer.timeout.connect(self.createWindowImages)
    
    self.layout.addStretch(1)
Example #22
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)
        # Instantiate and connect widgets ...

        self.logic = NeedleTrackingLogic(None)
        self.logic.setWidget(self)

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

        reloadCollapsibleButton.collapsed = True

        # 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 = "Reload"
        reloadFormLayout.addWidget(self.reloadButton)
        self.reloadButton.connect('clicked()', self.onReload)
        #
        #--------------------------------------------------

        self.nCath = 1  # Number of catheters

        #--------------------------------------------------
        # GUI components

        #
        # Connection Area
        #
        connectionCollapsibleButton = ctk.ctkCollapsibleButton()
        connectionCollapsibleButton.text = "Connection (OpenIGTLink)"
        self.layout.addWidget(connectionCollapsibleButton)

        # Layout within the dummy collapsible button
        connectionFormLayout = qt.QFormLayout(connectionCollapsibleButton)

        #--------------------------------------------------
        # Connector Selector
        #--------------------------------------------------

        self.igtlConnector1 = NeedleTrackingIGTLConnector("Connector 1")
        self.igtlConnector1.port = 18944
        self.igtlConnector1.buildGUI(connectionFormLayout)

        #--------------------------------------------------
        # Catheter
        #--------------------------------------------------

        catheterCollapsibleButton = ctk.ctkCollapsibleButton()
        catheterCollapsibleButton.text = "Tracking Node"
        self.layout.addWidget(catheterCollapsibleButton)

        catheterFormLayout = qt.QFormLayout(catheterCollapsibleButton)

        #--------------------------------------------------
        # Tracking node selector

        trackingNodeGroupBox = ctk.ctkCollapsibleGroupBox()
        trackingNodeGroupBox.title = "Tracking Node"
        catheterFormLayout.addWidget(trackingNodeGroupBox)
        trackingNodeFormLayout = qt.QFormLayout(trackingNodeGroupBox)

        self.trackingDataSelector = slicer.qMRMLNodeComboBox()
        self.trackingDataSelector.nodeTypes = ((
            "vtkMRMLIGTLTrackingDataBundleNode"), "")
        self.trackingDataSelector.selectNodeUponCreation = True
        self.trackingDataSelector.addEnabled = True
        self.trackingDataSelector.removeEnabled = False
        self.trackingDataSelector.noneEnabled = False
        self.trackingDataSelector.showHidden = True
        self.trackingDataSelector.showChildNodeTypes = False
        self.trackingDataSelector.setMRMLScene(slicer.mrmlScene)
        self.trackingDataSelector.setToolTip("Incoming tracking data")
        trackingNodeFormLayout.addRow("TrackingData: ",
                                      self.trackingDataSelector)

        #
        # check box to trigger transform conversion
        #
        self.activeTrackingCheckBox = qt.QCheckBox()
        self.activeTrackingCheckBox.checked = 0
        self.activeTrackingCheckBox.enabled = 1
        self.activeTrackingCheckBox.setToolTip("Activate Tracking")
        trackingNodeFormLayout.addRow("Active: ", self.activeTrackingCheckBox)

        #--------------------------------------------------
        # Catheter Configuration

        configGroupBox = ctk.ctkCollapsibleGroupBox()
        configGroupBox.title = "Catheter Configuration"
        configGroupBox.collapsed = True

        catheterFormLayout.addWidget(configGroupBox)
        configFormLayout = qt.QFormLayout(configGroupBox)

        self.tipLengthSliderWidget = [None] * self.nCath
        self.catheterDiameterSliderWidget = [None] * self.nCath
        self.catheterOpacitySliderWidget = [None] * self.nCath

        for cath in range(self.nCath):

            #
            # Tip Length (legnth between the catheter tip and the first coil)
            #
            self.tipLengthSliderWidget[cath] = ctk.ctkSliderWidget()
            self.tipLengthSliderWidget[cath].singleStep = 0.5
            self.tipLengthSliderWidget[cath].minimum = 0.0
            self.tipLengthSliderWidget[cath].maximum = 100.0
            self.tipLengthSliderWidget[cath].value = 10.0
            self.tipLengthSliderWidget[cath].setToolTip(
                "Set the length of the catheter tip.")
            configFormLayout.addRow("Cath %d Tip Length (mm): " % cath,
                                    self.tipLengthSliderWidget[cath])

            #
            # Catheter #1 Catheter diameter
            #
            self.catheterDiameterSliderWidget[cath] = ctk.ctkSliderWidget()
            self.catheterDiameterSliderWidget[cath].singleStep = 0.1
            self.catheterDiameterSliderWidget[cath].minimum = 0.1
            self.catheterDiameterSliderWidget[cath].maximum = 10.0
            self.catheterDiameterSliderWidget[cath].value = 1.0
            self.catheterDiameterSliderWidget[cath].setToolTip(
                "Set the diameter of the catheter")
            configFormLayout.addRow("Cath %d Diameter (mm): " % cath,
                                    self.catheterDiameterSliderWidget[cath])

            #
            # Catheter #1 Catheter opacity
            #
            self.catheterOpacitySliderWidget[cath] = ctk.ctkSliderWidget()
            self.catheterOpacitySliderWidget[cath].singleStep = 0.1
            self.catheterOpacitySliderWidget[cath].minimum = 0.0
            self.catheterOpacitySliderWidget[cath].maximum = 1.0
            self.catheterOpacitySliderWidget[cath].value = 1.0
            self.catheterOpacitySliderWidget[cath].setToolTip(
                "Set the opacity of the catheter")
            configFormLayout.addRow("Cath %d Opacity: " % cath,
                                    self.catheterOpacitySliderWidget[cath])

        #
        # Check box to show/hide coil labels
        #
        self.showCoilLabelCheckBox = qt.QCheckBox()
        self.showCoilLabelCheckBox.checked = 0
        self.showCoilLabelCheckBox.setToolTip("Show/hide coil labels")
        configFormLayout.addRow("Show Coil Labels: ",
                                self.showCoilLabelCheckBox)

        #--------------------------------------------------
        # Coordinate System
        #
        coordinateGroupBox = ctk.ctkCollapsibleGroupBox()
        coordinateGroupBox.title = "Coordinate System"
        coordinateGroupBox.collapsed = True

        catheterFormLayout.addWidget(coordinateGroupBox)
        coordinateLayout = qt.QFormLayout(coordinateGroupBox)

        self.coordinateRPlusRadioButton = qt.QRadioButton("+X")
        self.coordinateRMinusRadioButton = qt.QRadioButton("-X")
        self.coordinateRPlusRadioButton.checked = 1
        self.coordinateRBoxLayout = qt.QHBoxLayout()
        self.coordinateRBoxLayout.addWidget(self.coordinateRPlusRadioButton)
        self.coordinateRBoxLayout.addWidget(self.coordinateRMinusRadioButton)
        self.coordinateRGroup = qt.QButtonGroup()
        self.coordinateRGroup.addButton(self.coordinateRPlusRadioButton)
        self.coordinateRGroup.addButton(self.coordinateRMinusRadioButton)
        coordinateLayout.addRow("Right:", self.coordinateRBoxLayout)

        self.coordinateAPlusRadioButton = qt.QRadioButton("+Y")
        self.coordinateAMinusRadioButton = qt.QRadioButton("-Y")
        self.coordinateAPlusRadioButton.checked = 1
        self.coordinateABoxLayout = qt.QHBoxLayout()
        self.coordinateABoxLayout.addWidget(self.coordinateAPlusRadioButton)
        self.coordinateABoxLayout.addWidget(self.coordinateAMinusRadioButton)
        self.coordinateAGroup = qt.QButtonGroup()
        self.coordinateAGroup.addButton(self.coordinateAPlusRadioButton)
        self.coordinateAGroup.addButton(self.coordinateAMinusRadioButton)
        coordinateLayout.addRow("Anterior:", self.coordinateABoxLayout)

        self.coordinateSPlusRadioButton = qt.QRadioButton("+Z")
        self.coordinateSMinusRadioButton = qt.QRadioButton("-Z")
        self.coordinateSPlusRadioButton.checked = 1
        self.coordinateSBoxLayout = qt.QHBoxLayout()
        self.coordinateSBoxLayout.addWidget(self.coordinateSPlusRadioButton)
        self.coordinateSBoxLayout.addWidget(self.coordinateSMinusRadioButton)
        self.coordinateSGroup = qt.QButtonGroup()
        self.coordinateSGroup.addButton(self.coordinateSPlusRadioButton)
        self.coordinateSGroup.addButton(self.coordinateSMinusRadioButton)
        coordinateLayout.addRow("Superior:", self.coordinateSBoxLayout)

        #--------------------------------------------------
        # Reslice
        #
        resliceCollapsibleButton = ctk.ctkCollapsibleButton()
        resliceCollapsibleButton.text = "Image Reslice"
        self.layout.addWidget(resliceCollapsibleButton)

        #resliceLayout = qt.QFormLayout(resliceCollapsibleButton)

        self.reslice = NeedleTrackingReslice("Image Reslice")
        self.reslice.nCath = self.nCath
        self.reslice.buildGUI(resliceCollapsibleButton)

        #--------------------------------------------------
        # Connections
        #--------------------------------------------------
        self.trackingDataSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                          self.onTrackingDataSelected)
        self.activeTrackingCheckBox.connect('toggled(bool)',
                                            self.onActiveTracking)

        for cath in range(self.nCath):
            self.tipLengthSliderWidget[cath].connect(
                "valueChanged(double)",
                functools.partial(self.onTipLengthChanged, cath))
            self.catheterDiameterSliderWidget[cath].connect(
                "valueChanged(double)",
                functools.partial(self.onCatheterDiameterChanged, cath))
            self.catheterOpacitySliderWidget[cath].connect(
                "valueChanged(double)",
                functools.partial(self.onCatheterOpacityChanged, cath))

        self.showCoilLabelCheckBox.connect('toggled(bool)',
                                           self.onCoilLabelChecked)

        self.coordinateRPlusRadioButton.connect('clicked(bool)',
                                                self.onSelectCoordinate)
        self.coordinateRMinusRadioButton.connect('clicked(bool)',
                                                 self.onSelectCoordinate)
        self.coordinateAPlusRadioButton.connect('clicked(bool)',
                                                self.onSelectCoordinate)
        self.coordinateAMinusRadioButton.connect('clicked(bool)',
                                                 self.onSelectCoordinate)
        self.coordinateSPlusRadioButton.connect('clicked(bool)',
                                                self.onSelectCoordinate)
        self.coordinateSMinusRadioButton.connect('clicked(bool)',
                                                 self.onSelectCoordinate)

        # Add vertical spacer
        self.layout.addStretch(1)
Example #23
0
    def initMainPanel(self):
        # Create main collapsible Button
        self.mainCollapsibleBtn = ctk.ctkCollapsibleButton()
        self.mainCollapsibleBtn.setStyleSheet(
            "ctkCollapsibleButton { background-color: DarkSeaGreen  }")
        self.mainCollapsibleBtn.text = "Remeshing Tools Selection"
        #self.mainCollapsibleBtn.collapsible = True
        self.layout.addWidget(self.mainCollapsibleBtn)
        self.mainFormLayout = qt.QFormLayout(self.mainCollapsibleBtn)

        # Create input Segmentation Selector
        self.inputSelectorCoBx = slicer.qMRMLNodeComboBox()
        self.inputSelectorCoBx.nodeTypes = ["vtkMRMLModelNode"]
        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 an .stl file as the input segmentation")
        self.mainFormLayout.addRow("Input segmentation: ",
                                   self.inputSelectorCoBx)

        # Create button to show mesh of InputNode
        self.showMeshBtn = qt.QPushButton("Show Mesh")
        self.showMeshBtn.setFixedHeight(20)
        self.showMeshBtn.setFixedWidth(100)
        self.showMeshBtn.setStyleSheet(
            "QPushButton{ background-color: DarkSeaGreen  }")
        self.showMeshBtn.toolTip = (
            'How to use:'
            ' Click the Show Mesh Button to show mesh of Input Segmentation ')
        self.showMeshBtn.connect('clicked(bool)', self.onShowBtnClick)
        self.mainFormLayout.addRow("Input Segmentation: ", self.showMeshBtn)

        # Create button to set visibility to 1 of inputNode
        self.showBtn = qt.QPushButton("Show Input")
        self.showBtn.setFixedHeight(20)
        self.showBtn.setFixedWidth(100)
        self.showBtn.setStyleSheet(
            "QPushButton{ background-color: DarkSeaGreen  }")
        self.showBtn.toolTip = (
            'How to use:'
            ' Click the Show Mesh Button to show Input Segmentation ')
        self.showBtn.connect('clicked(bool)', self.onInputBtnClick)
        self.mainFormLayout.addRow("Input Segmentation: ", self.showBtn)

        # ---------------------------------------INSTANT MESHING--------------------------------------------
        # Create collapsible Button for Instant-Meshing options
        self.instantCollapsibleBtn = ctk.ctkCollapsibleButton()
        self.instantCollapsibleBtn.text = "Instant-Meshing"
        self.layout.addWidget(self.instantCollapsibleBtn)
        self.instantFormLayout = qt.QFormLayout(self.instantCollapsibleBtn)
        self.instantCollapsibleBtn.connect('clicked(bool)',
                                           self.onInstantClick)

        # Create button to run the Instant-Meshing tool
        self.imBtn = qt.QPushButton("Run")
        self.imBtn.setFixedHeight(40)
        self.imBtn.setFixedWidth(100)
        self.imBtn.setStyleSheet(
            "QPushButton{ background-color: DarkSeaGreen  }")
        self.imBtn.toolTip = (
            'How to use:'
            ' Click the Run Button to start instant-meshing ')
        self.imBtn.connect('clicked(bool)', self.onImBtnClick)
        self.instantFormLayout.addRow(self.imBtn, self.imtimeLbl)

        # Create check box to display normals
        self.checkshowNormals = qt.QCheckBox()
        self.checkshowNormals.checked = False
        self.checkshowNormals.toolTip = ('If activated:' ' shows normals ')
        self.checkshowNormals.stateChanged.connect(
            self.onCheckShowNormalsChkBx)
        self.instantFormLayout.addRow(
            "                                         Show normals: ",
            self.checkshowNormals)

        # ---------------------------------------ADVANCED USER OPTIONS--------------------------------------------
        # Create group box for advanced user options
        self.instantCollapsiblegroupBtn = ctk.ctkCollapsibleGroupBox()
        self.instantCollapsiblegroupBtn.title = "Advanced Options"
        self.layout.addWidget(self.instantCollapsiblegroupBtn)
        self.instantCollapsiblegroupBtn.collapsed = True
        self.instantFormLayout.addRow(self.instantCollapsiblegroupBtn)
        self.instantCGBFormLayout = qt.QFormLayout(
            self.instantCollapsiblegroupBtn)

        # Create radio buttons for triangle or quad meshing
        self.checkTR = qt.QRadioButton()
        self.checkTR.text = "Triangles (6/6)"
        self.checkTR.checked = True  # use triangle meshing by default
        self.instantCGBFormLayout.addRow(
            "Orientation and Position Symmetry Type: ", self.checkTR)

        self.checkQD1 = qt.QRadioButton()
        self.checkQD1.text = "Quads (2/4)"
        self.instantCGBFormLayout.addRow(
            "                                        ", self.checkQD1)

        self.checkQD2 = qt.QRadioButton()
        self.checkQD2.text = "Quads (4/4)"
        self.instantCGBFormLayout.addRow(
            "                                        ", self.checkQD2)

        # Create check boxes for boolean values
        self.checkintrinsic = qt.QCheckBox()
        self.checkintrinsic.checked = False  # use extrinsic by default
        self.checkintrinsic.toolTip = (
            'If activated:'
            ' Measures smoothness directly on the surface instead of natural alignment to surface features '
        )
        self.checkintrinsic.stateChanged.connect(self.oncheckint)
        self.instantCGBFormLayout.addRow("Intrinsic: ", self.checkintrinsic)

        self.checkdominant = qt.QCheckBox()
        self.checkdominant.checked = False
        self.checkdominant.toolTip = (
            'If activated:'
            ' Generates a tri/quad dominant mesh instead of a pure tri/quad mesh '
        )
        self.checkdominant.stateChanged.connect(self.oncheckdom)
        self.instantCGBFormLayout.addRow("Dominant: ", self.checkdominant)

        self.checkdetermin = qt.QCheckBox()
        self.checkdetermin.checked = False
        self.checkdetermin.toolTip = (
            'If activated:'
            ' Prefers (slower) deterministic algorithms ')
        self.checkdetermin.stateChanged.connect(self.oncheckdet)
        self.instantCGBFormLayout.addRow("Deterministic: ", self.checkdetermin)

        # Create slider widget to adjust face count (triangle), prior vertex count (to change back, change -f in cmd to -v)
        self.vertSlider = ctk.ctkSliderWidget()
        self.vertSlider.minimum = 1000
        self.vertSlider.maximum = 10000
        self.vertSlider.setFixedWidth(400)
        self.vertSlider.value = 2800
        self.vertSlider.toolTip = ('What it changes:'
                                   ' Desired face count of the output mesh ')
        self.instantCGBFormLayout.addRow("Triangle count: ", self.vertSlider)

        # Create slider widget to adjust smoothing & ray tracing reprojection steps
        self.smoothraySlider = ctk.ctkSliderWidget()
        self.smoothraySlider.minimum = 0
        self.smoothraySlider.maximum = 10
        self.smoothraySlider.setFixedWidth(400)
        self.smoothraySlider.value = 2
        self.smoothraySlider.toolTip = (
            'What it changes:'
            ' Number of smoothing & ray tracing reprojection steps (default: 2) '
        )
        self.instantCGBFormLayout.addRow("Smoothing Steps: ",
                                         self.smoothraySlider)

        # Create slider widget to adjust Point cloud mode
        self.knnSlider = ctk.ctkSliderWidget()
        self.knnSlider.minimum = 5
        self.knnSlider.maximum = 20
        self.knnSlider.setFixedWidth(400)
        self.knnSlider.value = 10
        self.knnSlider.toolTip = (
            'Point cloud mode:'
            ' Number of adjacent points to consider (default: 10) ')
        self.instantCGBFormLayout.addRow("Adjacent Points: ", self.knnSlider)

        # Create slider widget to adjust Dihedral angle threshold
        self.angleSlider = ctk.ctkSliderWidget()
        self.angleSlider.minimum = -1
        self.angleSlider.maximum = 90
        self.angleSlider.setFixedWidth(400)
        self.angleSlider.value = -1
        self.angleSlider.toolTip = (
            'What it changes:'
            ' Dihedral angle threshold for creases, -1 means sharp creases ')
        self.instantCGBFormLayout.addRow("Crease Angle: ", self.angleSlider)

        # ---------------------------------------ROBUST QUAD/HEX-DOMINANT MESHING--------------------------------------------
        # Create collapsible Button for robust quad/hex-dominant meshing options
        self.quadhexCollapsibleBtn = ctk.ctkCollapsibleButton()
        self.quadhexCollapsibleBtn.text = "Robust Quad/Hex-dominant Meshing"
        self.layout.addWidget(self.quadhexCollapsibleBtn)
        self.quadhexCollapsibleBtn.collapsed = True
        self.quadhexFormLayout = qt.QFormLayout(self.quadhexCollapsibleBtn)
        self.quadhexCollapsibleBtn.connect('clicked(bool)',
                                           self.onQuadHexClick)

        # Create button to run the tool
        self.rmBtn = qt.QPushButton("Run")
        self.rmBtn.setFixedHeight(40)
        self.rmBtn.setFixedWidth(100)
        self.rmBtn.setStyleSheet(
            "QPushButton{ background-color: DarkSeaGreen  }")
        self.rmBtn.toolTip = (
            'How to use:'
            ' Click the Run Button to start robust quad/hex-dominant meshing ')
        self.rmBtn.connect('clicked(bool)', self.onRmBtnClick)
        self.quadhexFormLayout.addRow(self.rmBtn, self.qhtimeLbl)

        # ---------------------------------------ADVANCED USER OPTIONS--------------------------------------------
        # Create group box for advanced user options
        self.robustCollapsiblegroupBtn = ctk.ctkCollapsibleGroupBox()
        self.robustCollapsiblegroupBtn.title = "Advanced Options"
        self.layout.addWidget(self.robustCollapsiblegroupBtn)
        self.robustCollapsiblegroupBtn.collapsed = True
        self.quadhexFormLayout.addRow(self.robustCollapsiblegroupBtn)
        self.robustCGBFormLayout = qt.QFormLayout(
            self.robustCollapsiblegroupBtn)

        # Create radio buttons to adjust dimension
        self.checkdim2 = qt.QRadioButton()
        self.checkdim2.checked = True  # use dimension 2 by default
        self.checkdim2.text = "2"
        self.robustCGBFormLayout.addRow("Dimension: ", self.checkdim2)

        # Create slider widget to adjust scale
        self.scaleSlider = ctk.ctkSliderWidget()
        self.scaleSlider.minimum = 2
        self.scaleSlider.maximum = 10
        self.scaleSlider.setFixedWidth(400)
        self.scaleSlider.value = 3
        self.robustCGBFormLayout.addRow("Scale: ", self.scaleSlider)

        # Create slider widget to adjust smooth iterator
        self.smoothSlider = ctk.ctkSliderWidget()
        self.smoothSlider.minimum = 5
        self.smoothSlider.maximum = 20
        self.smoothSlider.setFixedWidth(400)
        self.smoothSlider.value = 10
        self.robustCGBFormLayout.addRow("Smoothing iteration count: ",
                                        self.smoothSlider)
Example #24
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)
        pointSetProcessingCollapsibleButton = ctk.ctkCollapsibleButton()
        pointSetProcessingCollapsibleButton.text = "Surface Reconstruction from Unorganized Points"
        self.layout.addWidget(pointSetProcessingCollapsibleButton)
        pointSetProcessingFormLayout = qt.QFormLayout(
            pointSetProcessingCollapsibleButton)

        # Input
        self.inputSelector = slicer.qMRMLNodeComboBox()
        self.inputSelector.nodeTypes = (("vtkMRMLModelNode"), "")
        self.inputSelector.selectNodeUponCreation = True
        self.inputSelector.addEnabled = False
        self.inputSelector.removeEnabled = False
        self.inputSelector.noneEnabled = False
        self.inputSelector.showHidden = False
        self.inputSelector.showChildNodeTypes = False
        self.inputSelector.setMRMLScene(slicer.mrmlScene)
        self.inputSelector.setToolTip("Pick the input to the algorithm.")
        pointSetProcessingFormLayout.addRow("Input Model: ",
                                            self.inputSelector)

        self.nbrOfPointsLabel = qt.QLabel(
            'Number of Points in Input Model: - ')
        pointSetProcessingFormLayout.addRow(self.nbrOfPointsLabel)

        self.inputPointSizeSlider = ctk.ctkSliderWidget()
        self.inputPointSizeSlider.setDecimals(0)
        self.inputPointSizeSlider.singleStep = 1
        self.inputPointSizeSlider.minimum = 1
        self.inputPointSizeSlider.maximum = 10
        self.inputPointSizeSlider.value = 1
        pointSetProcessingFormLayout.addRow('Input Model Point Size: ',
                                            self.inputPointSizeSlider)

        # Runtime
        self.runtimeGroupBox = qt.QGroupBox('Runtime')
        runtimeFormLayout = qt.QFormLayout(self.runtimeGroupBox)
        pointSetProcessingFormLayout.addRow(self.runtimeGroupBox)

        self.runtimeLabel = qt.QLabel()
        self.runtimeLabel.setText("... s.")
        self.runtimeLabel.setWordWrap(True)
        self.runtimeLabel.setStyleSheet("QLabel { background-color : black; \
                                           color : #66FF00; \
                                           height : 60px; \
                                           border-style: outset; \
                                           border-width: 5px; \
                                           border-radius: 10px; \
                                           font: bold 14px; \
                                           padding: 0px;\
                                           font-family : SimSun; \
                                           qproperty-alignment: AlignCenter}")
        runtimeFormLayout.addRow(self.runtimeLabel)

        # Downsample
        self.downSampleGroupBox = ctk.ctkCollapsibleGroupBox()
        self.downSampleGroupBox.setTitle("Downsample Input Model")
        downSampleFormLayout = qt.QFormLayout(self.downSampleGroupBox)
        pointSetProcessingFormLayout.addRow(self.downSampleGroupBox)

        self.toleranceCleanSlider = ctk.ctkSliderWidget()
        self.toleranceCleanSlider.setDecimals(2)
        self.toleranceCleanSlider.singleStep = 0.01
        self.toleranceCleanSlider.minimum = 0.0
        self.toleranceCleanSlider.maximum = 1.0
        self.toleranceCleanSlider.value = 0.01
        self.toleranceCleanSlider.setToolTip('')
        self.toleranceCleanSlider.enabled = True
        downSampleFormLayout.addRow('Tolerance: ', self.toleranceCleanSlider)

        self.vtkCleanPolyDataButton = qt.QPushButton("Apply")
        self.vtkCleanPolyDataButton.enabled = False
        self.vtkCleanPolyDataButton.checkable = True
        downSampleFormLayout.addRow(self.vtkCleanPolyDataButton)

        # Outlier Removal
        self.outlierRemovalGroupBox = ctk.ctkCollapsibleGroupBox()
        self.outlierRemovalGroupBox.setTitle("Outlier Removal")
        outlierRemovalFormLayout = qt.QFormLayout(self.outlierRemovalGroupBox)
        pointSetProcessingFormLayout.addRow(self.outlierRemovalGroupBox)

        self.percentToRemoveSlider = ctk.ctkSliderWidget()
        self.percentToRemoveSlider.setDecimals(2)
        self.percentToRemoveSlider.singleStep = 0.01
        self.percentToRemoveSlider.minimum = 0.0
        self.percentToRemoveSlider.maximum = 1.0
        self.percentToRemoveSlider.value = 0.01
        self.percentToRemoveSlider.setToolTip('')
        self.percentToRemoveSlider.enabled = True
        outlierRemovalFormLayout.addRow('Percent to Remove: ',
                                        self.percentToRemoveSlider)

        self.vtkPointSetOutlierRemovalButton = qt.QPushButton("Apply")
        self.vtkPointSetOutlierRemovalButton.enabled = False
        self.vtkPointSetOutlierRemovalButton.checkable = True
        outlierRemovalFormLayout.addRow(self.vtkPointSetOutlierRemovalButton)

        # Compute Normals
        self.normalsGroupBox = ctk.ctkCollapsibleGroupBox()
        self.normalsGroupBox.setTitle("Compute Normals")
        normalsFormLayout = qt.QFormLayout(self.normalsGroupBox)
        pointSetProcessingFormLayout.addRow(self.normalsGroupBox)

        self.normalsTabWidget = qt.QTabWidget()
        normalsFormLayout.addRow(self.normalsTabWidget)

        # vtkPointSetNormalEstimationAndOrientation
        self.vtkPointSetNormalEstimationWidget = qt.QWidget()
        vtkPointSetNormalEstimationFormLayout = qt.QFormLayout(
            self.vtkPointSetNormalEstimationWidget)
        normalsFormLayout.addRow(self.vtkPointSetNormalEstimationWidget)
        self.normalsTabWidget.addTab(
            self.vtkPointSetNormalEstimationWidget,
            "vtkPointSetNormalEstimationAndOrientation")

        self.modeTypeComboBox = qt.QComboBox()
        self.modeTypeComboBox.addItem('Fixed')
        self.modeTypeComboBox.addItem('Radius')
        self.modeTypeComboBox.setCurrentIndex(1)
        self.modeTypeComboBox.setToolTip('')
        vtkPointSetNormalEstimationFormLayout.addRow('Mode Type: ',
                                                     self.modeTypeComboBox)

        self.numberOfNeighborsSlider = ctk.ctkSliderWidget()
        self.numberOfNeighborsSlider.setDecimals(0)
        self.numberOfNeighborsSlider.singleStep = 1
        self.numberOfNeighborsSlider.minimum = 1
        self.numberOfNeighborsSlider.maximum = 20
        self.numberOfNeighborsSlider.value = 4
        self.numberOfNeighborsSlider.setToolTip('')
        self.numberOfNeighborsSlider.enabled = False
        vtkPointSetNormalEstimationFormLayout.addRow(
            'Fixed Neighbors: ', self.numberOfNeighborsSlider)

        self.radiusSlider = ctk.ctkSliderWidget()
        self.radiusSlider.setDecimals(2)
        self.radiusSlider.singleStep = 0.01
        self.radiusSlider.minimum = 0
        self.radiusSlider.maximum = 50
        self.radiusSlider.value = 1.0
        self.radiusSlider.setToolTip('')
        vtkPointSetNormalEstimationFormLayout.addRow('Radius: ',
                                                     self.radiusSlider)

        self.graphTypeComboBox = qt.QComboBox()
        self.graphTypeComboBox.addItem('Riemann')
        self.graphTypeComboBox.addItem('KNN')
        self.graphTypeComboBox.setCurrentIndex(1)
        self.graphTypeComboBox.setToolTip('')
        vtkPointSetNormalEstimationFormLayout.addRow('Graph Type: ',
                                                     self.graphTypeComboBox)

        self.knnSlider = ctk.ctkSliderWidget()
        self.knnSlider.setDecimals(0)
        self.knnSlider.singleStep = 1
        self.knnSlider.minimum = 1
        self.knnSlider.maximum = 100
        self.knnSlider.value = 5
        self.knnSlider.setToolTip('')
        vtkPointSetNormalEstimationFormLayout.addRow('K-Nearest Neighbors: ',
                                                     self.knnSlider)

        self.vtkPointSetNormalEstimationButton = qt.QPushButton("Apply")
        self.vtkPointSetNormalEstimationButton.enabled = False
        self.vtkPointSetNormalEstimationButton.checkable = True
        vtkPointSetNormalEstimationFormLayout.addRow(
            self.vtkPointSetNormalEstimationButton)

        # vtkPolyDataNormals
        self.vtkPolyDataNormalsWidget = qt.QWidget()
        vtkPolyDataNormalsFormLayout = qt.QFormLayout(
            self.vtkPolyDataNormalsWidget)
        normalsFormLayout.addRow(self.vtkPolyDataNormalsWidget)
        self.normalsTabWidget.addTab(self.vtkPolyDataNormalsWidget,
                                     "vtkPolyDataNormals")

        self.featureAngleSlider = ctk.ctkSliderWidget()
        self.featureAngleSlider.setDecimals(2)
        self.featureAngleSlider.singleStep = 0.01
        self.featureAngleSlider.minimum = 0
        self.featureAngleSlider.maximum = 360
        self.featureAngleSlider.value = 0.1
        self.featureAngleSlider.setToolTip('')
        vtkPolyDataNormalsFormLayout.addRow('Feature Angle: ',
                                            self.featureAngleSlider)

        self.splittingComboBox = qt.QComboBox()
        self.splittingComboBox.addItem('False')
        self.splittingComboBox.addItem('True')
        self.splittingComboBox.setCurrentIndex(1)
        self.splittingComboBox.setToolTip('')
        vtkPolyDataNormalsFormLayout.addRow('Splitting: ',
                                            self.splittingComboBox)

        self.consistencyComboBox = qt.QComboBox()
        self.consistencyComboBox.addItem('False')
        self.consistencyComboBox.addItem('True')
        self.consistencyComboBox.setCurrentIndex(0)
        self.consistencyComboBox.setToolTip('')
        vtkPolyDataNormalsFormLayout.addRow('Consistency: ',
                                            self.consistencyComboBox)

        self.autoOrientNormalsComboBox = qt.QComboBox()
        self.autoOrientNormalsComboBox.addItem('False')
        self.autoOrientNormalsComboBox.addItem('True')
        self.autoOrientNormalsComboBox.setCurrentIndex(0)
        self.autoOrientNormalsComboBox.setToolTip('')
        vtkPolyDataNormalsFormLayout.addRow('Auto-Orient Normals: ',
                                            self.autoOrientNormalsComboBox)

        self.computePointNormalsComboBox = qt.QComboBox()
        self.computePointNormalsComboBox.addItem('False')
        self.computePointNormalsComboBox.addItem('True')
        self.computePointNormalsComboBox.setCurrentIndex(1)
        self.computePointNormalsComboBox.setToolTip('')
        vtkPolyDataNormalsFormLayout.addRow('Compute Point Normals: ',
                                            self.computePointNormalsComboBox)

        self.computeCellNormalsComboBox = qt.QComboBox()
        self.computeCellNormalsComboBox.addItem('False')
        self.computeCellNormalsComboBox.addItem('True')
        self.computeCellNormalsComboBox.setCurrentIndex(0)
        self.computeCellNormalsComboBox.setToolTip('')
        vtkPolyDataNormalsFormLayout.addRow('Compute Cell Normals: ',
                                            self.computeCellNormalsComboBox)

        self.flipNormalsComboBox = qt.QComboBox()
        self.flipNormalsComboBox.addItem('False')
        self.flipNormalsComboBox.addItem('True')
        self.flipNormalsComboBox.setCurrentIndex(0)
        self.flipNormalsComboBox.setToolTip('')
        vtkPolyDataNormalsFormLayout.addRow('Flip Normals: ',
                                            self.flipNormalsComboBox)

        self.nonManifoldTraversalComboBox = qt.QComboBox()
        self.nonManifoldTraversalComboBox.addItem('False')
        self.nonManifoldTraversalComboBox.addItem('True')
        self.nonManifoldTraversalComboBox.setCurrentIndex(1)
        self.nonManifoldTraversalComboBox.setToolTip('')
        vtkPolyDataNormalsFormLayout.addRow('Non-Manifold Traversal: ',
                                            self.nonManifoldTraversalComboBox)

        self.vtkPolyDataNormalsButton = qt.QPushButton("Apply")
        self.vtkPolyDataNormalsButton.enabled = False
        self.vtkPolyDataNormalsButton.checkable = True
        vtkPolyDataNormalsFormLayout.addRow(self.vtkPolyDataNormalsButton)

        self.normalsVisibleCheckBox = qt.QCheckBox('Arrows Visibility: ')
        self.normalsVisibleCheckBox.checked = True
        self.normalsVisibleCheckBox.enabled = True
        self.normalsVisibleCheckBox.setLayoutDirection(1)
        normalsFormLayout.addRow(self.normalsVisibleCheckBox)

        # Compute Surface
        self.surfaceGroupBox = ctk.ctkCollapsibleGroupBox()
        self.surfaceGroupBox.setTitle("Compute Surface")
        surfaceFormLayout = qt.QFormLayout(self.surfaceGroupBox)
        pointSetProcessingFormLayout.addRow(self.surfaceGroupBox)

        self.surfaceTabWidget = qt.QTabWidget()
        surfaceFormLayout.addRow(self.surfaceTabWidget)

        # vtkPoissionReconstruction
        self.vtkPoissionReconstructionWidget = qt.QWidget()
        vtkPoissionReconstructionFormLayout = qt.QFormLayout(
            self.vtkPoissionReconstructionWidget)
        surfaceFormLayout.addRow(self.vtkPoissionReconstructionWidget)
        self.surfaceTabWidget.addTab(self.vtkPoissionReconstructionWidget,
                                     "vtkPoissionReconstruction")

        self.depthSlider = ctk.ctkSliderWidget()
        self.depthSlider.setDecimals(0)
        self.depthSlider.singleStep = 1
        self.depthSlider.minimum = 1
        self.depthSlider.maximum = 14
        self.depthSlider.value = 8
        self.depthSlider.setToolTip(
            'This integer controls the reconstruction depth; the maximum depth of the tree that will be used for surface reconstruction. Running at depth d corresponds to solving on a voxel grid whose resolution is no larger than 2^d x 2^d x 2^d. Note that since the reconstructor adapts the octree to the sampling density, the specified reconstruction depth is only an upper bound.'
        )
        vtkPoissionReconstructionFormLayout.addRow('Depth: ', self.depthSlider)

        self.scaleSlider = ctk.ctkSliderWidget()
        self.scaleSlider.setDecimals(2)
        self.scaleSlider.singleStep = 0.01
        self.scaleSlider.minimum = 0
        self.scaleSlider.maximum = 10
        self.scaleSlider.value = 1.25
        self.scaleSlider.setToolTip(
            'This floating point value specifies the ratio between the diameter of the cube used for reconstruction and the diameter of the samples bounding cube.'
        )
        vtkPoissionReconstructionFormLayout.addRow('Scale: ', self.scaleSlider)

        self.solverDivideSlider = ctk.ctkSliderWidget()
        self.solverDivideSlider.setDecimals(0)
        self.solverDivideSlider.singleStep = 1
        self.solverDivideSlider.minimum = 1
        self.solverDivideSlider.maximum = 20
        self.solverDivideSlider.value = 8
        self.solverDivideSlider.setToolTip(
            'Solver subdivision depth; This integer argument specifies the depth at which a block Gauss-Seidel solver is used to solve the Laplacian equation. Using this parameter helps reduce the memory overhead at the cost of a small increase in reconstruction time. (In practice, we have found that for reconstructions of depth 9 or higher a subdivide depth of 7 or 8 can greatly reduce the memory usage.)'
        )
        vtkPoissionReconstructionFormLayout.addRow('Solver Divide: ',
                                                   self.solverDivideSlider)

        self.isoDivideSlider = ctk.ctkSliderWidget()
        self.isoDivideSlider.setDecimals(0)
        self.isoDivideSlider.singleStep = 1
        self.isoDivideSlider.minimum = 1
        self.isoDivideSlider.maximum = 20
        self.isoDivideSlider.value = 8
        self.isoDivideSlider.setToolTip(
            'Iso-surface extraction subdivision depth; This integer argument specifies the depth at which a block isosurface extractor should be used to extract the iso-surface. Using this parameter helps reduce the memory overhead at the cost of a small increase in extraction time. (In practice, we have found that for reconstructions of depth 9 or higher a subdivide depth of 7 or 8 can greatly reduce the memory usage.)'
        )
        vtkPoissionReconstructionFormLayout.addRow('Iso Divide: ',
                                                   self.isoDivideSlider)

        self.samplesPerNodeSlider = ctk.ctkSliderWidget()
        self.samplesPerNodeSlider.setDecimals(2)
        self.samplesPerNodeSlider.singleStep = 0.1
        self.samplesPerNodeSlider.minimum = 1
        self.samplesPerNodeSlider.maximum = 30
        self.samplesPerNodeSlider.value = 1.0
        self.samplesPerNodeSlider.setToolTip(
            'Minimum number of samples; This floating point value specifies the minimum number of sample points that should fall within an octree node as the octree construction is adapted to sampling density. For noise-free samples, small values in the range [1.0 - 5.0] can be used. For more noisy samples, larger values in the range [15.0 - 20.0] may be needed to provide a smoother, noise-reduced, reconstruction.'
        )
        vtkPoissionReconstructionFormLayout.addRow('Samples per Node: ',
                                                   self.samplesPerNodeSlider)

        self.confidenceComboBox = qt.QComboBox()
        self.confidenceComboBox.addItem('False')
        self.confidenceComboBox.addItem('True')
        self.confidenceComboBox.setToolTip(
            'Enabling tells the reconstructor to use the size of the normals as confidence information. When the flag is not enabled, all normals are normalized to have unit-length prior to reconstruction.'
        )
        vtkPoissionReconstructionFormLayout.addRow('Confidence: ',
                                                   self.confidenceComboBox)

        self.verboseComboBox = qt.QComboBox()
        self.verboseComboBox.addItem('False')
        self.verboseComboBox.addItem('True')
        self.verboseComboBox.setToolTip(
            'Enabling this flag provides a more verbose description of the running times and memory usages of individual components of the surface reconstructor.'
        )
        vtkPoissionReconstructionFormLayout.addRow('Verbose: ',
                                                   self.verboseComboBox)

        self.vtkPoissionReconstructionButton = qt.QPushButton("Apply")
        self.vtkPoissionReconstructionButton.enabled = False
        self.vtkPoissionReconstructionButton.checkable = True
        vtkPoissionReconstructionFormLayout.addRow(
            self.vtkPoissionReconstructionButton)

        # vtkDelaunay3D
        self.vtkDelaunay3DWidget = qt.QWidget()
        vtkDelaunay3DFormLayout = qt.QFormLayout(self.vtkDelaunay3DWidget)
        surfaceFormLayout.addRow(self.vtkDelaunay3DWidget)
        self.surfaceTabWidget.addTab(self.vtkDelaunay3DWidget, "vtkDelaunay3D")

        self.alphaSlider = ctk.ctkSliderWidget()
        self.alphaSlider.setDecimals(1)
        self.alphaSlider.singleStep = 0.1
        self.alphaSlider.minimum = 0.0
        self.alphaSlider.maximum = 100.0
        self.alphaSlider.value = 0.0
        self.alphaSlider.setToolTip('')
        vtkDelaunay3DFormLayout.addRow('Alpha: ', self.alphaSlider)

        self.toleranceSlider = ctk.ctkSliderWidget()
        self.toleranceSlider.setDecimals(2)
        self.toleranceSlider.singleStep = 0.01
        self.toleranceSlider.minimum = 0.0
        self.toleranceSlider.maximum = 1.0
        self.toleranceSlider.value = 0.0
        self.toleranceSlider.setToolTip('')
        vtkDelaunay3DFormLayout.addRow('Tolerance: ', self.toleranceSlider)

        self.offsetSlider = ctk.ctkSliderWidget()
        self.offsetSlider.setDecimals(1)
        self.offsetSlider.singleStep = 0.1
        self.offsetSlider.minimum = 0.0
        self.offsetSlider.maximum = 10.0
        self.offsetSlider.value = 2.5
        self.offsetSlider.setToolTip('')
        vtkDelaunay3DFormLayout.addRow('Offset: ', self.offsetSlider)

        self.boundingComboBox = qt.QComboBox()
        self.boundingComboBox.addItem('False')
        self.boundingComboBox.addItem('True')
        self.boundingComboBox.setCurrentIndex(0)
        self.boundingComboBox.setToolTip('')
        vtkDelaunay3DFormLayout.addRow('Bounding Triangulations: ',
                                       self.boundingComboBox)

        self.vtkDelaunay3DButton = qt.QPushButton("Apply")
        self.vtkDelaunay3DButton.enabled = False
        self.vtkDelaunay3DButton.checkable = True
        vtkDelaunay3DFormLayout.addRow(self.vtkDelaunay3DButton)

        self.surfaceVisibleCheckBox = qt.QCheckBox('Surface Visibility: ')
        self.surfaceVisibleCheckBox.checked = True
        self.surfaceVisibleCheckBox.enabled = True
        self.surfaceVisibleCheckBox.setLayoutDirection(1)
        surfaceFormLayout.addRow(self.surfaceVisibleCheckBox)

        # connections
        self.vtkCleanPolyDataButton.connect('clicked(bool)',
                                            self.vtkCleanPolyDataClicked)
        self.vtkPointSetOutlierRemovalButton.connect(
            'clicked(bool)', self.vtkPointSetOutlierRemovalClicked)
        self.vtkPointSetNormalEstimationButton.connect(
            'clicked(bool)', self.vtkPointSetNormalEstimationClicked)
        self.vtkPolyDataNormalsButton.connect('clicked(bool)',
                                              self.vtkPolyDataNormalsClicked)
        self.vtkPoissionReconstructionButton.connect(
            'clicked(bool)', self.vtkPoissionReconstructionClicked)
        self.vtkDelaunay3DButton.connect('clicked(bool)',
                                         self.vtkDelaunay3DClicked)
        self.inputSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                   self.onSelect)
        self.graphTypeComboBox.connect('currentIndexChanged(const QString &)',
                                       self.onGraphTypeChanged)
        self.modeTypeComboBox.connect('currentIndexChanged(const QString &)',
                                      self.onModeChanged)
        self.surfaceVisibleCheckBox.connect('stateChanged(int)',
                                            self.onSurfaceVisible)
        self.normalsVisibleCheckBox.connect('stateChanged(int)',
                                            self.onNormalsVisible)
        self.inputPointSizeSlider.connect('valueChanged (double)',
                                          self.onInputPointSliderModified)

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

        # Refresh
        self.onSelect()

        lm = slicer.app.layoutManager()
        lm.setLayout(4)  # One 3D-view
Example #25
0
 def setup(self):
   # reload button
   self.reloadButton = qt.QPushButton("Reload")
   self.reloadButton.toolTip = "Reload this module."
   self.reloadButton.name = "HeterogeneityCAD Reload"
   self.layout.addWidget(self.reloadButton)
   self.reloadButton.connect('clicked()', self.onReload)
   
   
   # Tumor Segmentation Collapsible Button
   self.TumorSegmentationCollapsibleButton = ctk.ctkCollapsibleButton()
   self.TumorSegmentationCollapsibleButton.text = "SegmentCAD Segmentation"
   self.layout.addWidget(self.TumorSegmentationCollapsibleButton)
   self.TumorSegmentationLayout = qt.QFormLayout(self.TumorSegmentationCollapsibleButton)
      
   # Select Volumes Collapsible Button
   self.selectionsCollapsibleButton = ctk.ctkCollapsibleButton()
   self.selectionsCollapsibleButton.text = "Select DCE-MRI Volumes for Segmentation"
   self.TumorSegmentationLayout.addWidget(self.selectionsCollapsibleButton)
   # Layout within the collapsible button
   self.volumesLayout = qt.QFormLayout(self.selectionsCollapsibleButton)
   
   # Use Multivolume Node as input
   self.enableMultiVolume = qt.QCheckBox(self.selectionsCollapsibleButton)
   self.enableMultiVolume.setText('Input Multi-Volume Node')
   self.enableMultiVolume.checked = True
   self.enableMultiVolume.setToolTip('Use Multi-Volume Node, with volumes imported in the correct order')
   self.inputSelectorMultiVolume = slicer.qMRMLNodeComboBox(self.selectionsCollapsibleButton)
   self.inputSelectorMultiVolume.nodeTypes = ( ("vtkMRMLMultiVolumeNode"), "" )
   self.inputSelectorMultiVolume.selectNodeUponCreation = False
   self.inputSelectorMultiVolume.renameEnabled = True
   self.inputSelectorMultiVolume.removeEnabled = False
   self.inputSelectorMultiVolume.noneEnabled = True
   self.inputSelectorMultiVolume.addEnabled = False
   self.inputSelectorMultiVolume.setMRMLScene(slicer.mrmlScene)
   self.inputSelectorMultiVolume.setToolTip('Use Multi-Volume Node, with volumes imported in the correct order')
      
   self.volumesLayout.addRow (self.enableMultiVolume, self.inputSelectorMultiVolume)
   
   self.nodeInputFrame = ctk.ctkCollapsibleGroupBox(self.selectionsCollapsibleButton)
   self.nodeInputFrame.title = "Input Scalar Volume Nodes"
   self.nodeInputFrame.collapsed = True
   self.nodeInputFrame.enabled = False
   self.nodeInputFrame.setLayout(qt.QFormLayout())
   self.volumesLayout.addRow(self.nodeInputFrame)
   
   # Select Pre Node
   self.inputPre = qt.QLabel("Pre-contrast Volume", self.nodeInputFrame)
   self.inputPre.setToolTip('Select the initial pre-contrast volume node.')
   self.inputSelectorPre = slicer.qMRMLNodeComboBox(self.nodeInputFrame)
   self.inputSelectorPre.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
   self.inputSelectorPre.addAttribute(("vtkMRMLScalarVolumeNode"), "LabelMap", "0")
   self.inputSelectorPre.selectNodeUponCreation = False
   self.inputSelectorPre.addEnabled = False
   self.inputSelectorPre.removeEnabled = False
   self.inputSelectorPre.noneEnabled = True
   self.inputSelectorPre.noneDisplay = 'Please Select Volume'
   self.inputSelectorPre.setMRMLScene(slicer.mrmlScene)
   self.inputSelectorPre.setToolTip('Select the initial pre-contrast volume node.')
   #self.volumesLayout.addRow(self.inputPre, self.inputSelectorPre)
   self.nodeInputFrame.layout().addRow(self.inputPre, self.inputSelectorPre)
   
   # Select First Node
   self.inputFirst = qt.QLabel("First Post-contrast Volume", self.nodeInputFrame)
   self.inputFirst.setToolTip('Select the first post-contrast volume node to calculate intitial enhancement and curve type.')
   self.inputSelectorFirst = slicer.qMRMLNodeComboBox(self.nodeInputFrame)
   self.inputSelectorFirst.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
   self.inputSelectorFirst.addAttribute(("vtkMRMLScalarVolumeNode"), "LabelMap", "0")
   self.inputSelectorFirst.selectNodeUponCreation = False
   self.inputSelectorFirst.addEnabled = False
   self.inputSelectorFirst.removeEnabled = False
   self.inputSelectorFirst.noneEnabled = True
   self.inputSelectorFirst.noneDisplay = 'Please Select Volume'
   self.inputSelectorFirst.setMRMLScene(slicer.mrmlScene)
   self.inputSelectorFirst.setToolTip('Select the first post-contrast volume node to calculate intitial enhancement and curve type.')
   #self.volumesLayout.addRow(self.inputFirst, self.inputSelectorFirst)
   self.nodeInputFrame.layout().addRow(self.inputFirst, self.inputSelectorFirst)
   
   # Select Second Node
   self.inputSecond = qt.QLabel("Second Post-contrast Volume", self.nodeInputFrame)
   self.inputSecond.setToolTip('Select a second post-contrast volume node (not required).')
   self.inputSelectorSecond = slicer.qMRMLNodeComboBox(self.nodeInputFrame)
   self.inputSelectorSecond.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
   self.inputSelectorSecond.addAttribute(("vtkMRMLScalarVolumeNode"), "LabelMap", "0")
   self.inputSelectorSecond.selectNodeUponCreation = False
   self.inputSelectorSecond.addEnabled = False
   self.inputSelectorSecond.removeEnabled = False
   self.inputSelectorSecond.noneEnabled = True
   self.inputSelectorSecond.noneDisplay = 'Please Select Volume'
   self.inputSelectorSecond.setMRMLScene(slicer.mrmlScene)
   self.inputSelectorSecond.setToolTip('Select a second post-contrast volume node (not required).')
   #self.volumesLayout.addRow(self.inputSecond, self.inputSelectorSecond)
   self.nodeInputFrame.layout().addRow(self.inputSecond, self.inputSelectorSecond)
   
   # Select Third Node 
   self.inputThird = qt.QLabel("Third Post-contrast Volume", self.nodeInputFrame)
   self.inputThird.setToolTip('Select a third post-contrast volume node (not required).')
   self.inputSelectorThird = slicer.qMRMLNodeComboBox(self.nodeInputFrame)
   self.inputSelectorThird.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
   self.inputSelectorThird.addAttribute( ("vtkMRMLScalarVolumeNode"), "LabelMap", "0")
   self.inputSelectorThird.selectNodeUponCreation = False
   self.inputSelectorThird.addEnabled = False
   self.inputSelectorThird.removeEnabled = False
   self.inputSelectorThird.noneEnabled = True
   self.inputSelectorThird.noneDisplay = 'Please Select Volume'
   self.inputSelectorThird.setMRMLScene(slicer.mrmlScene)
   self.inputSelectorThird.setToolTip('Select a third post-contrast volume node (not required).')
   #self.volumesLayout.addRow(self.inputThird, self.inputSelectorThird)
   self.nodeInputFrame.layout().addRow(self.inputThird, self.inputSelectorThird)
   
   # Select Fourth Node  
   self.inputFourth = qt.QLabel("Fourth Post-contrast Volume", self.nodeInputFrame)
   self.inputFourth.setToolTip('Select the fourth or final post-contrast volume node to calculate curve type based on the delayed curve slope.')
   self.inputSelectorFourth = slicer.qMRMLNodeComboBox(self.nodeInputFrame)
   self.inputSelectorFourth.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
   self.inputSelectorFourth.addAttribute( ("vtkMRMLScalarVolumeNode"), "LabelMap", "0")
   self.inputSelectorFourth.selectNodeUponCreation = False
   self.inputSelectorFourth.addEnabled = False
   self.inputSelectorFourth.removeEnabled = False
   self.inputSelectorFourth.noneEnabled = True
   self.inputSelectorFourth.noneDisplay = 'Please Select Volume'
   self.inputSelectorFourth.setMRMLScene(slicer.mrmlScene)
   self.inputSelectorFourth.setToolTip('Select the fourth or final post-contrast volume node to calculate curve type based on the delayed curve slope.')
   #self.volumesLayout.addRow(self.inputFourth, self.inputSelectorFourth)
   self.nodeInputFrame.layout().addRow(self.inputFourth, self.inputSelectorFourth)
   
   # Enable and Select Input Label Map as ROI
   self.enableLabel = qt.QCheckBox(self.selectionsCollapsibleButton)
   self.enableLabel.setText('Use Label Map as ROI')
   self.enableLabel.checked = True
   self.enableLabel.setToolTip('Select and identify a custom label map node to define an ROI over the input volumes for faster segmentation.')
   self.inputSelectorLabel = slicer.qMRMLNodeComboBox(self.selectionsCollapsibleButton)
   self.inputSelectorLabel.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
   self.inputSelectorLabel.addAttribute( ("vtkMRMLScalarVolumeNode"), "LabelMap", "1")
   self.inputSelectorLabel.selectNodeUponCreation = False
   self.inputSelectorLabel.renameEnabled = True
   self.inputSelectorLabel.removeEnabled = False
   self.inputSelectorLabel.noneEnabled = True
   self.inputSelectorLabel.addEnabled = False
   self.inputSelectorLabel.setMRMLScene(slicer.mrmlScene)
   self.inputSelectorLabel.setToolTip('Select and identify a custom label map node to define an ROI over the input volumes for faster segmentation.')
   self.volumesLayout.addRow (self.enableLabel, self.inputSelectorLabel)
   
   # Select output SegmentCAD Label collapsible button
   self.outlabelCollapsibleButton = ctk.ctkCollapsibleButton()
   self.outlabelCollapsibleButton.text = "Select or Create Output SegmentCAD Label Map"
   self.TumorSegmentationLayout.addWidget(self.outlabelCollapsibleButton)
   # Layout within the collapsible button
   self.outlabelLayout = qt.QFormLayout(self.outlabelCollapsibleButton)
   # Select or create output SegmentCAD Label Map
   self.outputLabel = qt.QLabel("Output SegmentCAD Label Map", self.outlabelCollapsibleButton)
   self.outputLabel.setToolTip('Select or create a label map volume node as the SegmentCAD segmentation output.')
   self.outputSelectorLabel = slicer.qMRMLNodeComboBox(self.outlabelCollapsibleButton)
   self.outputSelectorLabel.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
   self.outputSelectorLabel.addAttribute( ("vtkMRMLScalarVolumeNode"), "LabelMap", "1")
   self.outputSelectorLabel.baseName = "SegmentCAD Label Map"
   self.outputSelectorLabel.selectNodeUponCreation = True
   self.outputSelectorLabel.renameEnabled = True
   self.outputSelectorLabel.removeEnabled = True
   self.outputSelectorLabel.noneEnabled = False
   self.outputSelectorLabel.addEnabled = True
   self.outputSelectorLabel.setMRMLScene(slicer.mrmlScene)
   self.outputSelectorLabel.setToolTip('Select or create a label map volume node as the SegmentCAD segmentation output.')
   self.outlabelLayout.addRow(self.outputLabel, self.outputSelectorLabel)
   # SegmentCAD Label Map Legend
   self.outputLegend = qt.QLabel("| Type I Persistent: Blue | Type II Plateau: Yellow | Type III Washout: Red |", self.outlabelCollapsibleButton)
   self.outputLegend.setToolTip('SegmentCAD Label Map Legend  | Blue: Type I Persistent curve  |  Yellow: Type II Plateau curve  |  Red: Type III Washout curve  |')
   self.outlabelLayout.addRow(self.outputLegend)
   # Enable Volume Rendering of the SegmentCAD label map
   self.enableVolumeRendering = qt.QCheckBox(self.selectionsCollapsibleButton)
   self.enableVolumeRendering.setText('Display Volume Rendering')
   self.enableVolumeRendering.checked = True
   self.enableVolumeRendering.setToolTip('Display volume rendering of the SegmentCAD Label Map in the 3D View')
   self.outlabelLayout.addRow (self.enableVolumeRendering)
   # Enable Label Statistics Table and Data 
   self.enableStats = qt.QCheckBox(self.selectionsCollapsibleButton)
   self.enableStats.setText('Calculate SegmentCAD Label statistics')
   self.enableStats.checked = False
   self.enableStats.setToolTip('Use logic from Label Statistics Module to calculate statistics for first post-contrast voxels within the SegmentCAD Label Map.')
   self.outlabelLayout.addRow (self.enableStats)
 
   # Set Advanced Parameters Collapsible Button
   self.parametersCollapsibleButton = ctk.ctkCollapsibleButton()
   self.parametersCollapsibleButton.text = "Set Advanced Segmentation Parameters"
   self.TumorSegmentationLayout.addWidget(self.parametersCollapsibleButton)
   self.parametersCollapsibleButton.collapsed = True
   # Layout within the collapsible button
   self.parametersLayout = qt.QFormLayout(self.parametersCollapsibleButton)
   # Set Minimum Threshold of Percentage Increase to First Post-Contrast Image
   self.inputMinimumThreshold = qt.QLabel("Minimum Threshold of Increase", self.parametersCollapsibleButton)
   self.inputMinimumThreshold.setToolTip('Minimum Threshold of Percentage Increase (Pre- to First Post-contrast (Range: 10% to 150%)')
   self.inputSelectorMinimumThreshold = qt.QDoubleSpinBox(self.parametersCollapsibleButton)
   self.inputSelectorMinimumThreshold.setSuffix("%")
   self.inputSelectorMinimumThreshold.singleStep = (1)
   self.inputSelectorMinimumThreshold.minimum = (10)
   self.inputSelectorMinimumThreshold.maximum = (150)
   self.inputSelectorMinimumThreshold.value = (75)
   self.inputSelectorMinimumThreshold.setToolTip('Minimum Threshold of Percentage Increase (Pre- to First Post-contrast (Range: 10% to 150%)')
   self.parametersLayout.addRow(self.inputMinimumThreshold, self.inputSelectorMinimumThreshold)
   # Curve 1 Type Parameters (Slopes from First to Fourth Post-Contrast Images)
   self.inputCurve1 = qt.QLabel("Type 1 (Persistent) Curve Minimum Slope", self.parametersCollapsibleButton)
   self.inputCurve1.setToolTip('Minimum Slope of Delayed Curve to classify as Persistent (Range: 0.02 to 0.3)')
   self.inputSelectorCurve1 = qt.QDoubleSpinBox(self.parametersCollapsibleButton)
   self.inputSelectorCurve1.singleStep = (0.02)
   self.inputSelectorCurve1.minimum = (0.02)
   self.inputSelectorCurve1.maximum = (0.3)
   self.inputSelectorCurve1.value = (0.20)
   self.inputSelectorCurve1.setToolTip('Minimum Slope of Delayed Curve to classify as Persistent (Range: 0.02 to 0.3)')
   self.parametersLayout.addRow(self.inputCurve1, self.inputSelectorCurve1)
   # Curve 3 Type Parameters (Slopes from First to Fourth Post-Contrast Images)
   self.inputCurve3 = qt.QLabel("Type 3 (Washout) Curve Maximum Slope", self.parametersCollapsibleButton)
   self.inputCurve3.setToolTip('Maximum Slope of Delayed Curve to classify as Washout (Range: -0.02 to -0.3)')
   self.inputSelectorCurve3 = qt.QDoubleSpinBox(self.parametersCollapsibleButton)
   self.inputSelectorCurve3.singleStep = (0.02)
   self.inputSelectorCurve3.setPrefix("-")
   self.inputSelectorCurve3.minimum = (0.02)
   self.inputSelectorCurve3.maximum = (0.30)
   self.inputSelectorCurve3.value = (0.20)
   self.inputSelectorCurve3.setToolTip('Maximum Slope of Delayed Curve to classify as Washout (Range: -0.02 to -0.3)')
   self.parametersLayout.addRow(self.inputCurve3, self.inputSelectorCurve3)
   # Apply Tumor Adaptive Segmentation button
   self.SegmentCADButton = qt.QPushButton("Apply SegmentCAD")
   self.SegmentCADButton.toolTip = "Apply SegmentCAD segmentation to selected volumes."
   self.TumorSegmentationLayout.addWidget(self.SegmentCADButton)
   
   # LabelStatistics Table Collapsible Button
   self.labelstatisticsCollapsibleButton = ctk.ctkCollapsibleButton()
   self.labelstatisticsCollapsibleButton.text = "SegmentCAD Label Statistics"
   self.layout.addWidget(self.labelstatisticsCollapsibleButton)
   self.labelstatisticsCollapsibleButton.collapsed = True
   # Layout within the collapsible button
   self.labelstatisticsLayout = qt.QFormLayout(self.labelstatisticsCollapsibleButton)
   # Table View to display Label statistics
   self.labelStatisticsTableView = qt.QTableView()
   self.labelStatisticsTableView.sortingEnabled = True
   self.labelstatisticsLayout.addWidget(self.labelStatisticsTableView)
   self.labelStatisticsTableView.minimumHeight = 200
   # Charting Statistics Button
   self.chartOptions = ("Volume", "Curve Type", "Voxel Count", "Volume mm^3", "Volume cc", "Minimum Intensity", "Maximum Intensity", "Mean Intensity", "Standard Deviation")
   self.chartFrame = qt.QFrame()
   self.chartFrame.setLayout(qt.QHBoxLayout())
   self.labelstatisticsLayout.addWidget(self.chartFrame)
   self.chartButton = qt.QPushButton("Chart Statistics", self.labelstatisticsCollapsibleButton)
   self.chartButton.toolTip = "Make a chart from the current statistics."
   self.chartFrame.layout().addWidget(self.chartButton)
   self.chartOption = qt.QComboBox(self.labelstatisticsCollapsibleButton)
   self.chartOption.addItems(self.chartOptions)
   self.chartFrame.layout().addWidget(self.chartOption)
   self.chartIgnoreZero = qt.QCheckBox(self.labelstatisticsCollapsibleButton)
   self.chartIgnoreZero.setText('Ignore Zero Label')
   self.chartIgnoreZero.checked = False
   self.chartIgnoreZero.setToolTip('Do not include the zero index in the chart to avoid dwarfing other bars')
   self.chartFrame.layout().addWidget(self.chartIgnoreZero)
   self.chartButton.enabled = False
   
   # Interactive Charting Settings Collapsible Button
   self.iChartingCollapsibleButton = ctk.ctkCollapsibleButton()
   self.iChartingCollapsibleButton.text = "Interactive Charting Settings"
   self.iChartingCollapsibleButton.collapsed = True
   self.layout.addWidget(self.iChartingCollapsibleButton)
   # Layout within the collapsible button
   self.iChartingLayout = qt.QFormLayout(self.iChartingCollapsibleButton)
   # iCharting toggle button
   self.iCharting = qt.QPushButton("Enable Interactive Charting")
   self.iCharting.checkable = True
   self.iCharting.setChecked(False)
   self.iCharting.enabled = False
   self.iCharting.toolTip = "Toggle the real-time charting of the %increase from baseline of the selected voxel from each input volume."
   self.iChartingLayout.addRow(self.iCharting)
   
   # Initialize slice observers (from DataProbe.py)
   # Keep list of pairs: [observee,tag] so they can be removed easily
   self.styleObserverTags = []
   # Keep a map of interactor styles to sliceWidgets so we can easily get sliceLogic
   self.sliceWidgetsPerStyle = {}
   self.refreshObservers()
   
   # Connections
   self.SegmentCADButton.connect('clicked()', self.onSegmentCADButtonClicked)
   self.enableLabel.connect('stateChanged(int)', self.onEnableLabel)
   self.enableMultiVolume.connect('stateChanged(int)', self.onEnableMultiVolume)
   self.chartButton.connect('clicked()', self.onChart)
   self.iCharting.connect('toggled(bool)', self.onInteractiveChartingChanged)
  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 = "DICOMAnnotations 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)

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

    # Layout within the dummy collapsible button
    parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton)

    #
    # DICOM Annotations Checkbox
    #
    self.dicomAnnotationsCheckBox = qt.QCheckBox('DICOM Slice Annotations')
    parametersFormLayout.addRow(self.dicomAnnotationsCheckBox)

    #
    # Corner Annotations Activation Checkboxes
    #
    self.cornerActivationsGroupBox = ctk.ctkCollapsibleGroupBox()
    self.cornerActivationsGroupBox.setTitle('Active Corners')
    self.cornerActivationsGroupBox.enabled = False
    parametersFormLayout.addRow(self.cornerActivationsGroupBox)
    cornerActionHBoxLayout = qt.QHBoxLayout(self.cornerActivationsGroupBox)

    self.cornerActivationCheckbox = []

    for i in xrange(4):
      self.cornerActivationCheckbox.append(qt.QCheckBox())
      self.cornerActivationCheckbox[i].checked = True
      cornerActionHBoxLayout.addWidget(self.cornerActivationCheckbox[i])
      self.cornerActivationCheckbox[i].connect('clicked()', self.updateSliceViewFromGUI)

    self.cornerActivationCheckbox[0].setText('Top Left')
    self.cornerActivationCheckbox[1].setText('Top Right')
    self.cornerActivationCheckbox[2].setText('Bottom Left')
    self.cornerActivationCheckbox[3].setText('Bottom Right')

    #
    # Corner Annotations Font Properties
    #
    self.fontPropertiesGroupBox = ctk.ctkCollapsibleGroupBox()
    self.fontPropertiesGroupBox.setTitle('Font Properties')
    self.fontPropertiesGroupBox.enabled = False
    parametersFormLayout.addRow(self.fontPropertiesGroupBox)
    fontPropertiesHBoxLayout = qt.QHBoxLayout(self.fontPropertiesGroupBox)

    fontFamilyLabel = qt.QLabel('Font Family: ')
    fontPropertiesHBoxLayout.addWidget(fontFamilyLabel)
    self.timesFontRadioButton = qt.QRadioButton('Times')
    fontPropertiesHBoxLayout.addWidget(self.timesFontRadioButton)
    self.timesFontRadioButton.connect('clicked()', self.updateSliceViewFromGUI)
    self.timesFontRadioButton.checked = True
    self.arialFontRadioButton = qt.QRadioButton('Arial')
    self.arialFontRadioButton.connect('clicked()', self.updateSliceViewFromGUI)
    fontPropertiesHBoxLayout.addWidget(self.arialFontRadioButton)

    fontSizeLabel = qt.QLabel('Font Size: ')
    fontPropertiesHBoxLayout.addWidget(fontSizeLabel)
    self.fontSizeSpinBox = qt.QSpinBox()
    self.fontSizeSpinBox.setMinimum(10)
    self.fontSizeSpinBox.setMaximum(20)
    self.fontSizeSpinBox.value = 14
    fontPropertiesHBoxLayout.addWidget(self.fontSizeSpinBox)
    self.fontSizeSpinBox.connect('valueChanged(int)', self.updateSliceViewFromGUI)

    # connections

    # Add vertical spacer
    self.layout.addStretch(1)
    self.dicomAnnotationsCheckBox.connect('clicked()', self.updateSliceViewFromGUI)