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()
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
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))
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) )
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)
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()
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): 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
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)
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()
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)
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()
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
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)
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)
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)
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
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)