def create(self): super(FastGrowCutEffectOptions, self).create() self.helpLabel = qt.QLabel( "Run the Fast GrowCut segmentation on the current label/seed image.\n Background and foreground seeds will be used as starting points to fill in the rest of the volume.", self.frame) self.frame.layout().addWidget(self.helpLabel) #create a "Start Bot" button self.botButton = qt.QPushButton(self.frame) self.frame.layout().addWidget(self.botButton) self.botButton.connect('clicked()', self.onStartBot) self.locRadFrame = qt.QFrame(self.frame) self.locRadFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.locRadFrame) self.widgets.append(self.locRadFrame) #HelpButton(self.frame, "TO USE: \n Start the interactive segmenter and initialize the segmentation with any other editor tool. \n KEYS: \n Press the following keys to interact: \n C: copy label slice \n V: paste label slice \n Q: evolve contour in 2D \n E: evolve contour in 3D \n A: toggle between draw/erase modes" ) HelpButton( self.frame, "TO USE: \n Start the Fast GrowCut segmenter and initialize the segmentation with any other editor tool. \n KEYS: \n Press the following keys to interact: \n G: start Fast GrowCut \n S: toggle between seed image and segmentation result \n R: reset fast GrowCut \n" ) self.frame.layout().addStretch(1) # Add vertical spacer if hasattr(slicer.modules, 'FGCEditorBot'): slicer.util.showStatusMessage( slicer.modules.FGCEditorBot.logic.currentMessage) self.botButton.text = "Stop FastGrowCut Segmenter" if self.locRadFrame: self.locRadFrame.hide() else: self.botButton.text = "Start FastGrowCut Segmenter" if self.locRadFrame: self.locRadFrame.show()
def create(self): super(FastMarchingEffectOptions, self).create() self.defaultMaxPercent = 30 self.percentLabel = qt.QLabel( 'Expected structure volume as % of image volume:', self.frame) self.percentLabel.setToolTip( 'Segmentation will grow from the seed label until this value is reached' ) self.frame.layout().addWidget(self.percentLabel) self.widgets.append(self.percentLabel) self.percentMax = ctk.ctkSliderWidget(self.frame) self.percentMax.minimum = 0 self.percentMax.maximum = 100 self.percentMax.singleStep = 1 self.percentMax.value = self.defaultMaxPercent self.percentMax.setToolTip( 'Approximate volume of the structure to be segmented relative to the total volume of the image' ) self.frame.layout().addWidget(self.percentMax) self.widgets.append(self.percentMax) self.percentMax.connect('valueChanged(double)', self.percentMaxChanged) self.march = qt.QPushButton("March", self.frame) self.march.setToolTip( "Perform the Marching operation into the current label map") self.frame.layout().addWidget(self.march) self.widgets.append(self.march) self.percentVolume = qt.QLabel('Maximum volume of the structure: ') self.percentVolume.setToolTip('Total maximum volume') self.frame.layout().addWidget(self.percentVolume) self.widgets.append(self.percentVolume) self.marcher = ctk.ctkSliderWidget(self.frame) self.marcher.minimum = 0 self.marcher.maximum = 1 self.marcher.singleStep = 0.01 self.marcher.enabled = False self.frame.layout().addWidget(self.marcher) self.widgets.append(self.marcher) self.marcher.connect('valueChanged(double)', self.onMarcherChanged) HelpButton( self.frame, "To use FastMarching effect, first mark the areas that belong to the structure of interest to initialize the algorithm. Define the expected volume of the structure you are trying to segment, and hit March.\nAfter computation is complete, use the Marcher slider to go over the segmentation history." ) self.march.connect('clicked()', self.onMarch) # Add vertical spacer self.frame.layout().addStretch(1) self.percentMaxChanged(self.percentMax.value)
def create(self): super(EditorExtensionTemplateOptions,self).create() self.apply = qt.QPushButton("Apply", self.frame) self.apply.setToolTip("Apply the extension operation") self.frame.layout().addWidget(self.apply) self.widgets.append(self.apply) HelpButton(self.frame, "This is a sample with no real functionality.") self.apply.connect('clicked()', self.onApply) # Add vertical spacer self.frame.layout().addStretch(1)
def create(self): super(TemplateKeyEffectOptions,self).create() self.apply = qt.QPushButton("Apply", self.frame) self.apply.objectName = self.__class__.__name__ + 'Apply' self.apply.setToolTip("Apply the extension operation") self.frame.layout().addWidget(self.apply) self.widgets.append(self.apply) HelpButton(self.frame, "This is a sample with no real functionality.") self.connections.append( (self.apply, 'clicked()', self.onApply) ) # Add vertical spacer self.frame.layout().addStretch(1)
def create(self): super(WandEffectOptions,self).create() self.toleranceFrame = qt.QFrame(self.frame) self.toleranceFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.toleranceFrame) self.widgets.append(self.toleranceFrame) self.toleranceLabel = qt.QLabel("Tolerance:", self.toleranceFrame) self.toleranceLabel.setToolTip("Set the tolerance of the wand in terms of background pixel values") self.toleranceFrame.layout().addWidget(self.toleranceLabel) self.widgets.append(self.toleranceLabel) self.toleranceSpinBox = qt.QDoubleSpinBox(self.toleranceFrame) self.toleranceSpinBox.setToolTip("Set the tolerance of the wand in terms of background pixel values") self.toleranceSpinBox.minimum = 0 self.toleranceSpinBox.maximum = 1000 self.toleranceSpinBox.suffix = "" self.toleranceFrame.layout().addWidget(self.toleranceSpinBox) self.widgets.append(self.toleranceSpinBox) self.maxPixelsFrame = qt.QFrame(self.frame) self.maxPixelsFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.maxPixelsFrame) self.widgets.append(self.maxPixelsFrame) self.maxPixelsLabel = qt.QLabel("Max Pixels per click:", self.maxPixelsFrame) self.maxPixelsLabel.setToolTip("Set the maxPixels for each click") self.maxPixelsFrame.layout().addWidget(self.maxPixelsLabel) self.widgets.append(self.maxPixelsLabel) self.maxPixelsSpinBox = qt.QDoubleSpinBox(self.maxPixelsFrame) self.maxPixelsSpinBox.setToolTip("Set the maxPixels for each click") self.maxPixelsSpinBox.minimum = 1 self.maxPixelsSpinBox.maximum = 100000 self.maxPixelsSpinBox.suffix = "" self.maxPixelsFrame.layout().addWidget(self.maxPixelsSpinBox) self.widgets.append(self.maxPixelsSpinBox) HelpButton(self.frame, "Use this tool to label all voxels that are within a tolerance of where you click") # don't connect the signals and slots directly - instead, add these # to the list of connections so that gui callbacks can be cleanly # disabled while the gui is being updated. This allows several gui # elements to be interlinked with signal/slots but still get updated # as a unit to the new value of the mrml node. self.connections.append( (self.toleranceSpinBox, 'valueChanged(double)', self.onToleranceSpinBoxChanged) ) self.connections.append( (self.maxPixelsSpinBox, 'valueChanged(double)', self.onMaxPixelsSpinBoxChanged) ) # Add vertical spacer self.frame.layout().addStretch(1)
def create(self): super(GrowCutCLOptions,self).create() self.deviceTypeComboBox = qt.QComboBox() self.deviceTypeComboBox.addItem('CPU') self.deviceTypeComboBox.addItem('GPU') self.deviceTypeComboBox.connect('currentIndexChanged(int)', self.onDeviceTypeChanged) self.frame.layout().addWidget(self.deviceTypeComboBox) self.botButton = qt.QPushButton(self.frame) if hasattr(slicer.modules, 'editorBot'): self.botButton.text = "Stop Bot" else: self.botButton.text = "Start Bot" self.frame.layout().addWidget(self.botButton) self.acceptButton = qt.QPushButton(self.frame) self.acceptButton.text = "Accept Steered Label" self.frame.layout().addWidget(self.acceptButton) HelpButton(self.frame, "This is an interactive segmentation tool that is actively calculating a region-growing method as you provide additional input. Starting the Bot will cause the segmentation to grow using your current labels as input.") self.botButton.connect('clicked()', self.onStartBot) self.acceptButton.connect('clicked()', self.onAccept) # Add vertical spacer self.frame.layout().addStretch(1) # TODO: the functionality for the steered volume should migrate to # the edit helper class when functionality is finalized. backgroundVolume = self.editUtil.getBackgroundVolume() labelVolume = self.editUtil.getLabelVolume() steeredName = backgroundVolume.GetName() + '-steered' steeredVolume = slicer.util.getNode(steeredName) if not steeredVolume: volumesLogic = slicer.modules.volumes.logic() steeredVolume = volumesLogic.CloneVolume( slicer.mrmlScene, labelVolume, steeredName) compositeNodes = slicer.util.getNodes('vtkMRMLSliceCompositeNode*') for compositeNode in compositeNodes.values(): compositeNode.SetForegroundVolumeID(steeredVolume.GetID()) compositeNode.SetForegroundOpacity(0.5)
def create(self): super(ShortCutOptions, self).create() self.helpLabel = qt.QLabel("Run the Quick TCGA Segmenter on the current label/seed image.", self.frame) self.frame.layout().addWidget(self.helpLabel) # Create a "Start Bot" button: "Start Quick TCGA Segmenter" self.botButton = qt.QPushButton(self.frame) self.frame.layout().addWidget(self.botButton) self.botButton.connect('clicked()', self.onStartBot) self.locRadFrame = qt.QFrame(self.frame) self.locRadFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.locRadFrame) self.widgets.append(self.locRadFrame) # Skip for now: # self.nucleus_segmentation_parameters() HelpButton(self.frame, ( "TO USE: \n Start the ShortCut segmenter and initialize the segmentation with any other editor tool like PaintEffect. Press the following keys to interact:" + "\n KEYS for Global Segmentation: " + "\n S: start Global segmentation \n E: toggle between seed image and segmentation result" + " \n R: reset seed/label image for Global Segmentation " + "\n F: toggle between selected ROI(Region of Interest) and segmentation result" + "\n Space key to go back to Slicer mode" "\n \nKEYS for ShortCut" "\n C: start ShortCut to refine the segmentation inside ROI" + "\n N: run ShortCut" + "\n R: reset ShortCut parameters" "\n Q: quit ShortCut" + "\n Mouse: LEFT for foreground, RIGHT for background")) self.frame.layout().addStretch(1) # Add vertical spacer if hasattr(slicer.modules, 'TCGAEditorBot'): slicer.util.showStatusMessage(slicer.modules.TCGAEditorBot.logic.currentMessage) self.botButton.text = "Stop Quick TCGA Segmenter" if self.locRadFrame: self.locRadFrame.hide() else: self.botButton.text = "Start Quick TCGA Segmenter" if self.locRadFrame: self.locRadFrame.show()
def create(self): super(IsobrushEffectOptions, self).create() self.apply = qt.QPushButton("Apply", self.frame) self.apply.objectName = self.__class__.__name__ + 'Apply' self.apply.setToolTip("Apply the extension operation") self.frame.layout().addWidget(self.apply) self.widgets.append(self.apply) self.connections.append((self.apply, 'clicked()', self.onApply)) if self.developerMode: self.reload = qt.QPushButton("Reload", self.frame) self.reload.objectName = self.__class__.__name__ + 'Apply' self.reload.setToolTip("Reload this effect") self.frame.layout().addWidget(self.reload) self.widgets.append(self.reload) self.connections.append((self.reload, 'clicked()', self.onReload)) HelpButton(self.frame, "This is a fancy paint brush.") # Add vertical spacer self.frame.layout().addStretch(1)
def create(self): super(QuickTCGAEffectOptions, self).create() self.helpLabel = qt.QLabel( "Press Y to run automatic segmentation on the current image using given parameters.", self.frame) self.frame.layout().addWidget(self.helpLabel) #create a "Start Bot" button self.botButton = qt.QPushButton(self.frame) self.frame.layout().addWidget(self.botButton) self.botButton.connect('clicked()', self.onStartBot) self.locRadFrame = qt.QFrame(self.frame) self.locRadFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.locRadFrame) self.widgets.append(self.locRadFrame) # Nucleus segmentation parameters (Yi Gao's algorithm) nucleusSegCollapsibleButton = ctk.ctkCollapsibleButton() nucleusSegCollapsibleButton.text = "Nucleus Segmentation Parameters (Yi Gao)" nucleusSegCollapsibleButton.collapsed = True self.frame.layout().addWidget(nucleusSegCollapsibleButton) self.structuresView = slicer.util.findChildren( slicer.modules.SlicerPathologyWidget.editorWidget.volumes, 'StructuresView')[0] self.structuresView.connect("activated(QModelIndex)", self.onStructureClickedOrAdded) # Layout within the parameter button nucleusSegFormLayout = qt.QFormLayout(nucleusSegCollapsibleButton) self.frameOtsuSlider = ctk.ctkSliderWidget() self.frameOtsuSlider.connect('valueChanged(double)', self.OtsuSliderValueChanged) self.frameOtsuSlider.decimals = 0 self.frameOtsuSlider.minimum = 0 self.frameOtsuSlider.maximum = 10 self.frameOtsuSlider.value = 1.0 nucleusSegFormLayout.addRow("Otsu Threshold:", self.frameOtsuSlider) self.frameCurvatureWeightSlider = ctk.ctkSliderWidget() self.frameCurvatureWeightSlider.connect( 'valueChanged(double)', self.CurvatureWeightSliderValueChanged) self.frameCurvatureWeightSlider.decimals = 0 self.frameCurvatureWeightSlider.minimum = 0 self.frameCurvatureWeightSlider.maximum = 10 self.frameCurvatureWeightSlider.value = 8 nucleusSegFormLayout.addRow("Curvature Weight:", self.frameCurvatureWeightSlider) self.frameSizeThldSlider = ctk.ctkSliderWidget() self.frameSizeThldSlider.connect('valueChanged(double)', self.SizeThldSliderValueChanged) self.frameSizeThldSlider.decimals = 0 self.frameSizeThldSlider.minimum = 1 self.frameSizeThldSlider.maximum = 100 self.frameSizeThldSlider.value = 3 nucleusSegFormLayout.addRow("Size Threshold:", self.frameSizeThldSlider) self.frameSizeUpperThldSlider = ctk.ctkSliderWidget() self.frameSizeUpperThldSlider.connect( 'valueChanged(double)', self.SizeUpperThldSliderValueChanged) self.frameSizeUpperThldSlider.decimals = 0 self.frameSizeUpperThldSlider.minimum = 100 self.frameSizeUpperThldSlider.maximum = 500 self.frameSizeUpperThldSlider.value = 300 nucleusSegFormLayout.addRow("Size Upper Threshold:", self.frameSizeUpperThldSlider) self.frameMPPSlider = ctk.ctkSliderWidget() self.frameMPPSlider.connect('valueChanged(double)', self.MPPSliderValueChanged) self.frameMPPSlider.decimals = 0 self.frameMPPSlider.minimum = 0 self.frameMPPSlider.maximum = 100 self.frameMPPSlider.value = 25 nucleusSegFormLayout.addRow("Size Upper Threshold:", self.frameMPPSlider) HelpButton(self.frame, ( "TO USE: \n Start the QuickTCGA segmenter and initialize the segmentation with any other editor tool like PaintEffect. Press the following keys to interact:" + "\n KEYS for Global Segmentation: " + "\n S: start Global segmentation \n E: toggle between seed image and segmentation result" + " \n R: reset seed/label image for Global Segmentation " + "\n F: toggle between selected ROI(Region of Interest) and segmentation result" + "\n Space key to go back to Slicer mode" "\n \nKEYS for ShortCut" "\n C: start ShortCut to refine the segmentation inside ROI" + "\n N: run ShortCut" + "\n R: reset ShortCut parameters" "\n Q: quit ShortCut" + "\n Mouse: LEFT for foreground, RIGHT for background")) self.frame.layout().addStretch(1) # Add vertical spacer if hasattr(slicer.modules, 'TCGAEditorBot'): slicer.util.showStatusMessage( slicer.modules.TCGAEditorBot.logic.currentMessage) self.botButton.text = "Stop Quick TCGA Segmenter" if self.locRadFrame: self.locRadFrame.hide() else: self.botButton.text = "Start Quick TCGA Segmenter" if self.locRadFrame: self.locRadFrame.show()
def create(self): super(WatershedFromMarkerEffectOptions,self).create() if not HAVE_SIMPLEITK: self.warningLabel = qt.QLabel() self.warningLabel.text = "WatershedFromMarker is not available because\nSimpleITK is not available in this build" self.widgets.append(self.warningLabel) self.frame.layout().addWidget(self.warningLabel) return labelVolume = self.editUtil.getLabelVolume() if labelVolume and labelVolume.GetImageData(): spacing = labelVolume.GetSpacing() self.minimumSigma = 0.1 * min(spacing) self.maximumSigma = 100 * self.minimumSigma else: self.minimumSigma = 0.1 self.maximumSigma = 10 self.sigmaFrame = qt.QFrame(self.frame) self.sigmaFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.sigmaFrame) self.widgets.append(self.sigmaFrame) tip = "Increasing this value smooths the segmentation and reduces leaks. This is the sigma used for edge detection." self.sigmaLabel = qt.QLabel("Object Scale: ", self.frame) self.sigmaLabel.setToolTip(tip) self.sigmaFrame.layout().addWidget(self.sigmaLabel) self.widgets.append(self.sigmaLabel) self.sigmaSlider = qt.QSlider( qt.Qt.Horizontal, self.frame ) self.sigmaFrame.layout().addWidget(self.sigmaSlider) self.sigmaFrame.setToolTip(tip) self.widgets.append(self.sigmaSlider) self.sigmaSpinBox = qt.QDoubleSpinBox(self.frame) self.sigmaSpinBox.setToolTip(tip) self.sigmaSpinBox.suffix = "mm" self.sigmaFrame.layout().addWidget(self.sigmaSpinBox) self.widgets.append(self.sigmaSpinBox) self.sigmaSpinBox.minimum = self.minimumSigma self.sigmaSlider.minimum = self.minimumSigma self.sigmaSpinBox.maximum = self.maximumSigma self.sigmaSlider.maximum = self.maximumSigma decimals = math.floor(math.log(self.minimumSigma,10)) if decimals < 0: self.sigmaSpinBox.decimals = -decimals + 2 self.apply = qt.QPushButton("Apply", self.frame) self.apply.setToolTip("Apply the extension operation") self.frame.layout().addWidget(self.apply) self.widgets.append(self.apply) helpDoc = \ """Use this effect to apply the watershed from markers segmentation from multiple initial labels. The input to this filter is current labelmap image which is expected to contain multiple labels as initial markss. The marks or labels are grown to fill the image and with edges defining the bondaries between. To segment a single object, mark the object, and then it is suggested to surround the object with a negative label on each axis. The "Object Scale" parameter is use to adjust the smoothness of the output image and prevent leakage. It is used internally for the sigma of the gradient magnitude. """ HelpButton(self.frame, helpDoc) self.sigmaSlider.connect( 'valueChanged(int)', self.sigmaSpinBox.setValue ) self.sigmaSpinBox.connect( 'valueChanged(double)', self.sigmaSlider.setValue ) # if either widget is changed both should change and this should be triggered self.connections.append( ( self.sigmaSpinBox, 'valueChanged(double)', self.onSigmaValueChanged ) ) self.connections.append( (self.apply, 'clicked()', self.onApply) ) # Add vertical spacer self.frame.layout().addStretch(1)
def create(self): super(GooCutOptions,self).create() self.botButton = qt.QPushButton(self.frame) self.botButton.text = "Start Bot" self.frame.layout().addWidget(self.botButton) self.toleranceFrame = qt.QFrame(self.frame) self.toleranceFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.toleranceFrame) self.widgets.append(self.toleranceFrame) self.toleranceLabel = qt.QLabel("Tolerance:", self.toleranceFrame) self.toleranceLabel.setToolTip("Set the tolerance of the wand in terms of background pixel values") self.toleranceFrame.layout().addWidget(self.toleranceLabel) self.widgets.append(self.toleranceLabel) self.toleranceSpinBox = qt.QDoubleSpinBox(self.toleranceFrame) self.toleranceSpinBox.setToolTip("Set the tolerance of the wand in terms of background pixel values") self.toleranceSpinBox.minimum = 0 self.toleranceSpinBox.maximum = 1000 self.toleranceSpinBox.suffix = "" self.toleranceFrame.layout().addWidget(self.toleranceSpinBox) self.widgets.append(self.toleranceSpinBox) self.maxPixelsFrame = qt.QFrame(self.frame) self.maxPixelsFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.maxPixelsFrame) self.widgets.append(self.maxPixelsFrame) self.maxPixelsLabel = qt.QLabel("Max Pixels per click:", self.maxPixelsFrame) self.maxPixelsLabel.setToolTip("Set the maxPixels for each click") self.maxPixelsFrame.layout().addWidget(self.maxPixelsLabel) self.widgets.append(self.maxPixelsLabel) self.maxPixelsSpinBox = qt.QDoubleSpinBox(self.maxPixelsFrame) self.maxPixelsSpinBox.setToolTip("Set the maxPixels for each click") self.maxPixelsSpinBox.minimum = 1 self.maxPixelsSpinBox.maximum = 1000 self.maxPixelsSpinBox.suffix = "" self.maxPixelsFrame.layout().addWidget(self.maxPixelsSpinBox) self.widgets.append(self.maxPixelsSpinBox) HelpButton(self.frame, "Use this tool to label all voxels that are within a tolerance of where you click") self.botButton.connect('clicked()', self.onStartBot) self.toleranceSpinBox.connect('valueChanged(double)', self.onToleranceSpinBoxChanged) self.maxPixelsSpinBox.connect('valueChanged(double)', self.onMaxPixelsSpinBoxChanged) # Add vertical spacer self.frame.layout().addStretch(1) # TODO: the functionality for the steered volume should migrate to # the edit helper class when functionality is finalized. backgroundVolume = self.editUtil.getBackgroundVolume() labelVolume = self.editUtil.getLabelVolume() steeredName = backgroundVolume.GetName() + '-steered' steeredVolume = slicer.util.getNode(steeredName) if not steeredVolume: volumesLogic = slicer.modules.volumes.logic() steeredVolume = volumesLogic.CloneVolume( slicer.mrmlScene, labelVolume, steeredName) compositeNodes = slicer.util.getNodes('vtkMRMLSliceCompositeNode*') for compositeNode in compositeNodes.values(): compositeNode.SetForegroundVolumeID(steeredVolume.GetID()) compositeNode.SetForegroundOpacity(0.5)
def create(self): super(BinaryWatershedEffectOptions, self).create() if not HAVE_SIMPLEITK: self.warningLabel = qt.QLabel() self.warningLabel.text = "BinaryWatershed is not available because\nSimpleITK is not available in this build" self.widgets.append(self.warningLabel) self.frame.layout().addWidget(self.warningLabel) return self.splitSizeFrame = qt.QFrame(self.frame) self.splitSizeFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.splitSizeFrame) self.widgets.append(self.splitSizeFrame) tip = "Sets the a minimum size for labels which will be split into multiple objects." self.splitSizeLabel = qt.QLabel("Split Size:", self.frame) self.splitSizeLabel.setToolTip(tip) self.splitSizeFrame.layout().addWidget(self.splitSizeLabel) self.widgets.append(self.splitSizeLabel) self.minimumSplitSize = 0 self.maximumSplitSize = 100 self.splitSizeSlider = qt.QSlider(qt.Qt.Horizontal, self.frame) self.splitSizeSlider.setValue(1) self.splitSizeFrame.layout().addWidget(self.splitSizeSlider) self.splitSizeFrame.setToolTip(tip) self.widgets.append(self.splitSizeSlider) self.splitSizeSpinBox = qt.QDoubleSpinBox(self.frame) self.splitSizeSpinBox.setToolTip(tip) self.splitSizeSpinBox.setValue(1) self.splitSizeSpinBox.suffix = "mm" self.splitSizeFrame.layout().addWidget(self.splitSizeSpinBox) self.widgets.append(self.splitSizeSpinBox) self.splitSizeSpinBox.minimum = self.minimumSplitSize self.splitSizeSlider.minimum = self.minimumSplitSize self.splitSizeSpinBox.maximum = self.maximumSplitSize self.splitSizeSlider.maximum = self.maximumSplitSize self.apply = qt.QPushButton("Apply", self.frame) self.apply.setToolTip("Apply the binary watershed operation") self.frame.layout().addWidget(self.apply) self.widgets.append(self.apply) helpDoc = """Split selected label into separate objects based at minimum size the objects.""" HelpButton(self.frame, helpDoc) self.apply.connect('clicked()', self.onApply) self.splitSizeSlider.connect('valueChanged(int)', self.splitSizeSpinBox.setValue) self.splitSizeSpinBox.connect('valueChanged(double)', self.splitSizeSlider.setValue) # if either widget is changed both should change and this should be triggered self.connections.append((self.splitSizeSpinBox, 'valueChanged(double)', self.onSplitSizeValueChanged)) # Add vertical spacer self.frame.layout().addStretch(1)
def create(self): super(PETTumorSegmentationEffectOptions, self).create() #Save space in the GUI self.frame.layout().setSpacing(0) self.frame.layout().setMargin(0) # refinementBoxesFrame contains the options for how clicks are handled self.refinementBoxesFrame = qt.QFrame(self.frame) self.refinementBoxesFrame.setLayout(qt.QHBoxLayout()) self.refinementBoxesFrame.layout().setSpacing(0) self.refinementBoxesFrame.layout().setMargin(0) self.frame.layout().addWidget(self.refinementBoxesFrame) #default is global refinement (threshold refinement) self.noRefinementRadioButton = qt.QRadioButton( "Create new", self.refinementBoxesFrame) self.noRefinementRadioButton.setToolTip( "On click, always segment a new object.") self.globalRefinementRadioButton = qt.QRadioButton( "Global refinement", self.refinementBoxesFrame) self.globalRefinementRadioButton.setToolTip( "On click, refine globally (adjusting then entire boundary) if no center point for the label, otherwise segment a new object." ) self.localRefinementRadioButton = qt.QRadioButton( "Local refinement", self.refinementBoxesFrame) self.localRefinementRadioButton.setToolTip( "On click, refine locally (adjusting part of the boundary) if no center point for the label, otherwise segment a new object." ) self.globalRefinementRadioButton.setChecked(True) #radio button so only one can be applied self.refinementBoxesFrame.layout().addWidget( qt.QLabel("Interaction style: ", self.refinementBoxesFrame)) self.refinementBoxesFrame.layout().addWidget( self.noRefinementRadioButton) self.refinementBoxesFrame.layout().addWidget( self.globalRefinementRadioButton) self.refinementBoxesFrame.layout().addWidget( self.localRefinementRadioButton) self.refinementBoxesFrame.layout().addStretch(1) self.widgets.append(self.noRefinementRadioButton) self.widgets.append(self.globalRefinementRadioButton) self.widgets.append(self.localRefinementRadioButton) self.noRefinementRadioButton.connect('clicked()', self.onRefinementTypeChanged) self.localRefinementRadioButton.connect('clicked()', self.onRefinementTypeChanged) self.globalRefinementRadioButton.connect('clicked()', self.onRefinementTypeChanged) #options are hidden (collapsed) until requested self.optFrame = ctk.ctkCollapsibleButton(self.frame) self.optFrame.setText("Options") self.optFrame.setLayout(qt.QVBoxLayout()) self.optFrame.layout().setSpacing(0) self.optFrame.layout().setMargin(0) self.optFrame.visible = True self.optFrame.collapsed = True self.optFrame.collapsedHeight = 0 self.optFrame.setToolTip("Displays algorithm options.") #most useful options are kept on top: Splitting, Sealing, Assist Centering, Allow # Overwriting #to save vertical space, put 2 ina row, so subframes here with horizontal layout are used #first row self.commonCheckBoxesFrame1 = qt.QFrame(self.optFrame) self.commonCheckBoxesFrame1.setLayout(qt.QHBoxLayout()) self.commonCheckBoxesFrame1.layout().setSpacing(0) self.commonCheckBoxesFrame1.layout().setMargin(0) self.optFrame.layout().addWidget(self.commonCheckBoxesFrame1) #top left self.splittingCheckBox = qt.QCheckBox("Splitting", self.commonCheckBoxesFrame1) self.splittingCheckBox.setToolTip( "Cut off adjacent objects to the target via watershed or local minimum. Useful for lymph node chains." ) self.splittingCheckBox.checked = False self.commonCheckBoxesFrame1.layout().addWidget(self.splittingCheckBox) self.widgets.append(self.splittingCheckBox) #top right self.sealingCheckBox = qt.QCheckBox("Sealing", self.commonCheckBoxesFrame1) self.sealingCheckBox.setToolTip( "Close single-voxel gaps in the object or between the object and other objects, if above the threshold. Useful for lymph node chains." ) self.sealingCheckBox.checked = False self.commonCheckBoxesFrame1.layout().addWidget(self.sealingCheckBox) self.widgets.append(self.sealingCheckBox) #second row self.commonCheckBoxesFrame2 = qt.QFrame(self.optFrame) self.commonCheckBoxesFrame2.setLayout(qt.QHBoxLayout()) self.commonCheckBoxesFrame2.layout().setSpacing(0) self.commonCheckBoxesFrame2.layout().setMargin(0) self.optFrame.layout().addWidget(self.commonCheckBoxesFrame2) #bottom left self.assistCenteringCheckBox = qt.QCheckBox( "Assist Centering", self.commonCheckBoxesFrame2) self.assistCenteringCheckBox.setToolTip( "Move the center to the highest voxel within 7 physical units, without being on or next to other object labels. Improves consistency." ) self.assistCenteringCheckBox.checked = True self.commonCheckBoxesFrame2.layout().addWidget( self.assistCenteringCheckBox) self.widgets.append(self.assistCenteringCheckBox) #bottom right self.allowOverwritingCheckBox = qt.QCheckBox( "Allow Overwriting", self.commonCheckBoxesFrame2) self.allowOverwritingCheckBox.setToolTip("Ignore other object labels.") self.allowOverwritingCheckBox.checked = False self.commonCheckBoxesFrame2.layout().addWidget( self.allowOverwritingCheckBox) self.widgets.append(self.allowOverwritingCheckBox) #advanced options, for abnormal cases such as massive necrotic objects or #low-transition scans like phantoms #infrequently used, just keep vertical self.advFrame = ctk.ctkCollapsibleButton(self.optFrame) self.advFrame.setText("Advanced") self.advFrame.setLayout(qt.QVBoxLayout()) self.advFrame.layout().setSpacing(0) self.advFrame.layout().setMargin(0) self.advFrame.visible = True self.advFrame.collapsed = True self.advFrame.collapsedHeight = 0 self.advFrame.setToolTip( "Displays more advanced algorithm options. Do not use if you don't know what they mean." ) #top self.necroticRegionCheckBox = qt.QCheckBox("Necrotic Region", self.advFrame) self.necroticRegionCheckBox.setToolTip( "Prevents cutoff from low uptake. Use if placing a center inside a necrotic region." ) self.necroticRegionCheckBox.checked = False self.advFrame.layout().addWidget(self.necroticRegionCheckBox) self.widgets.append(self.necroticRegionCheckBox) #middle self.denoiseThresholdCheckBox = qt.QCheckBox("Denoise Threshold", self.advFrame) self.denoiseThresholdCheckBox.setToolTip( "Calculates threshold based on median-filtered image. Use only if scan is very noisey." ) self.denoiseThresholdCheckBox.checked = False self.advFrame.layout().addWidget(self.denoiseThresholdCheckBox) self.widgets.append(self.denoiseThresholdCheckBox) #bottom self.linearCostCheckBox = qt.QCheckBox("Linear Cost", self.advFrame) self.linearCostCheckBox.setToolTip( "Cost function below threshold is linear rather than based on region. Use only if little/no transition region in uptake." ) self.linearCostCheckBox.checked = False self.advFrame.layout().addWidget(self.linearCostCheckBox) self.widgets.append(self.linearCostCheckBox) self.optFrame.layout().addWidget(self.advFrame) #apply button kept at bottom of all options self.applyButton = qt.QPushButton("Apply", self.optFrame) self.optFrame.layout().addWidget(self.applyButton) self.applyButton.connect('clicked()', self.onApply) self.widgets.append(self.applyButton) self.applyButton.setToolTip( "Redo last segmentation with the same center and refinement points with any changes in options." ) #When changing settings, update the MRML with it self.assistCenteringCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.allowOverwritingCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.splittingCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.sealingCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.necroticRegionCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.denoiseThresholdCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.linearCostCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.frame.layout().addWidget(self.optFrame) HelpButton( self.frame, "Click on a lesion in a PET scan to segment it. Depending on refinement settings, click again to refine globally and/or locally. Options may help deal with cases such as segmenting individual lesions in a chain. For more information: http://www.slicer.org/slicerWiki/index.php/Documentation/4.4/Modules/PETTumorSegmentationEffect" ) # Add vertical spacer self.frame.layout().addStretch(1) # Clear any existing data and undo/redo queue; working directly with other tools is # beyond the scope of this self.logic.reset() self.updateGUIFromMRML(self, 0)
def create(self): super(RobustStatisticsSegmenterOptions, self).create() self.goToRobustStatisticsSegmenter = qt.QPushButton( "Go To RSS Segmenter", self.frame) self.goToRobustStatisticsSegmenter.setToolTip( "Robust Statistics Segmentation - allows fast segmentation of 2D/3D data given an initial seed." ) self.frame.layout().addWidget(self.goToRobustStatisticsSegmenter) self.widgets.append(self.goToRobustStatisticsSegmenter) # gui widgets for exposing some parameter control self.smooth_boundary = qt.QCheckBox("Smooth Boundary?", self.frame) self.good_contrast = qt.QCheckBox("Good Contrast?", self.frame) self.smooth_boundary.checked = True self.good_contrast.checked = True self.smooth_boundary.setToolTip( "Is the boundary of the region smooth (not jagged)?.") self.good_contrast.setToolTip( "Is the boundary of the region visually very clear?.") self.frame.layout().addWidget(self.smooth_boundary) self.frame.layout().addWidget(self.good_contrast) self.widgets.append(self.smooth_boundary) self.widgets.append(self.good_contrast) # create button group for selecting size self.region_small = qt.QRadioButton("Small ~10mL", self.frame) self.region_small.setToolTip("about the size of a grape") self.region_medium = qt.QRadioButton("Medium ~100mL", self.frame) self.region_medium.setToolTip("about the size of a golf ball") self.region_large = qt.QRadioButton("Large ~500mL", self.frame) self.region_large.setToolTip("about the size of your fist") self.region_medium.checked = True self.frame.layout().addWidget(self.region_small) self.widgets.append(self.region_small) self.frame.layout().addWidget(self.region_medium) self.widgets.append(self.region_medium) self.frame.layout().addWidget(self.region_large) self.widgets.append(self.region_large) # # Setup parameters [minimalist & intuitive] # self.apply = qt.QPushButton("Apply", self.frame) self.apply.setToolTip( "Segment the region of interest from the seed provided - using the Robust Statistical Segmenter" ) self.frame.layout().addWidget(self.apply) self.widgets.append(self.apply) HelpButton(self.frame, "Use this tool to segment 3D regions.") # Add vertical spacer self.frame.layout().addStretch(1) self.apply.connect('clicked()', self.onApply) self.goToRobustStatisticsSegmenter.connect( 'clicked()', self.onGoToRobustStatisticsSegmenter) # disable segmentation unless seed is selected self.confirmSeedSelection()
def create(self): super(TraceAndSelectOptions, self).create() ## Custom threshold box # Note: This is needed because other tools can disable, hide, or manipulate the default threshold box # We need one unique to our tool self.threshLabel = qt.QLabel("Threshold", self.frame) self.threshLabel.setToolTip( "In threshold mode, the label will only be set if the background value is within this range." ) self.frame.layout().addWidget(self.threshLabel) self.widgets.append(self.threshLabel) self.thresh = ctk.ctkRangeWidget(self.frame) self.thresh.spinBoxAlignment = 0xff # put enties on top self.thresh.singleStep = 0.01 self.setRangeWidgetToBackgroundRange(self.thresh) self.frame.layout().addWidget(self.thresh) self.widgets.append(self.thresh) ## End custom threshold box ## Preview checkbox self.preview = qt.QCheckBox("Preview outlines", self.frame) self.preview.setToolTip( "Preview the outline of a selection with right-click.") self.frame.layout().addWidget(self.preview) ## End preview checkbox self.modeButtons = qt.QButtonGroup(self.frame) self.tissueRadioButton = qt.QRadioButton("Tissue Mode", self.frame) self.boneRadioButton = qt.QRadioButton("Bone/Nerve Mode", self.frame) self.hbox = qt.QHBoxLayout() self.hbox.addWidget(self.boneRadioButton) self.hbox.addWidget(self.tissueRadioButton) self.frame.layout().addLayout(self.hbox) self.modeButtons.addButton(self.boneRadioButton) self.modeButtons.addButton(self.tissueRadioButton) self.widgets.append(self.tissueRadioButton) self.widgets.append(self.boneRadioButton) ## ERROR MESSAGE FRAME self.errorMessageFrame = qt.QTextEdit(self.frame) self.frame.layout().addWidget(self.errorMessageFrame) #self.errorMessageFrame.setLayout(qt.QHBoxLayout) self.errorMessageFrame.setFixedWidth(280) self.errorMessageFrame.setReadOnly(True) self.errorMessageFrame.setText('No Error Detected') self.errorMessageFrame.setStyleSheet("QTextEdit {color:green}") self.widgets.append(self.errorMessageFrame) ## END ERROR MESSAGE FRAME ## For the offset value selection process self.offsetvalueFrame = qt.QFrame(self.frame) self.offsetvalueFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.offsetvalueFrame) self.widgets.append(self.offsetvalueFrame) self.offsetvalueLabel = qt.QLabel("Offset Value:", self.offsetvalueFrame) self.offsetvalueLabel.setToolTip( "Set the offset value shift upon an action") self.offsetvalueFrame.layout().addWidget(self.offsetvalueLabel) self.widgets.append(self.offsetvalueLabel) self.offsetvalueSpinBox = qt.QDoubleSpinBox(self.offsetvalueFrame) self.offsetvalueSpinBox.setToolTip( "Set the offset value shift upon an action") self.offsetvalueSpinBox.minimum = -1000 self.offsetvalueSpinBox.maximum = 1000 self.offsetvalueSpinBox.suffix = "" self.offsetvalueFrame.layout().addWidget(self.offsetvalueSpinBox) self.widgets.append(self.offsetvalueSpinBox) ## End offset value selection self.maxPixelsFrame = qt.QFrame(self.frame) self.maxPixelsFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.maxPixelsFrame) self.widgets.append(self.maxPixelsFrame) self.maxPixelsLabel = qt.QLabel("Max Pixels per click:", self.maxPixelsFrame) self.maxPixelsLabel.setToolTip("Set the maxPixels for each click") self.maxPixelsFrame.layout().addWidget(self.maxPixelsLabel) self.widgets.append(self.maxPixelsLabel) self.maxPixelsSpinBox = qt.QDoubleSpinBox(self.maxPixelsFrame) self.maxPixelsSpinBox.setToolTip("Set the maxPixels for each click") self.maxPixelsSpinBox.minimum = 1 self.maxPixelsSpinBox.maximum = 100000 self.maxPixelsSpinBox.suffix = "" self.maxPixelsFrame.layout().addWidget(self.maxPixelsSpinBox) self.widgets.append(self.maxPixelsSpinBox) # Help Browser self.helpBrowser = qt.QPushButton("Visit the Webpage") # End Help Browser self.frame.layout().addWidget(self.helpBrowser) HelpButton( self.frame, "Use this tool to help you label all voxels enclosed in an area bounded by the the largest path of pixels within the specified threshold." ) # don't connect the signals and slots directly - instead, add these # to the list of connections so that gui callbacks can be cleanly # disabled while the gui is being updated. This allows several gui # elements to be interlinked with signal/slots but still get updated # as a unit to the new value of the mrml node. # self.thresholdPaint.hide() self.connections.append((self.maxPixelsSpinBox, 'valueChanged(double)', self.onMaxPixelsSpinBoxChanged)) self.connections.append( (self.preview, "clicked()", self.onPreviewChanged)) self.connections.append( (self.tissueRadioButton, "clicked()", self.onTissueButtonChanged)) self.connections.append( (self.boneRadioButton, "clicked()", self.onBoneButtonChanged)) self.connections.append( (self.offsetvalueSpinBox, 'valueChanged(double)', self.onOffsetValueSpinBoxChanged)) self.connections.append((self.thresh, "valuesChanged(double,double)", self.onThreshValuesChange)) self.connections.append( (self.helpBrowser, "clicked()", self.onHelpBrowserPressed)) # Add vertical spacer self.frame.layout().addStretch(1)