def setQuickieRadius(self,radius): labelVolume = EditUtil.getLabelVolume() if labelVolume: if self.radiusUnitsToggle.text == 'px:': spacing = labelVolume.GetSpacing() if self.radiusPixelMode == 'diag': from math import sqrt diag = sqrt(reduce(lambda x,y:x+y, map(lambda x: x**2, spacing))) mmRadius = diag * radius elif self.radiusPixelMode == 'min': mmRadius = min(spacing) * radius else: print (self,"Unknown pixel mode - using 5mm") mmRadius = 5 else: mmRadius = radius self.disconnectWidgets() self.radiusSpinBox.setValue(mmRadius) self.radius.setValue(mmRadius) self.connectWidgets() self.updateMRMLFromGUI()
def __init__(self, parent=0): # get pixel-size-dependent parameters # calculate this before calling superclass init # so it can be used to set mrml defaults if needed labelVolume = EditUtil.getLabelVolume() if labelVolume and labelVolume.GetImageData(): spacing = labelVolume.GetSpacing() dimensions = labelVolume.GetImageData().GetDimensions() self.minimumRadius = 0.5 * min(spacing) bounds = [a*b for a,b in zip(spacing,dimensions)] self.maximumRadius = 0.5 * max(bounds) else: self.minimumRadius = 0.01 self.maximumRadius = 100 super(PaintEffectOptions,self).__init__(parent) # option to use 'min' or 'diag' # - min means pixel radius is min spacing # - diag means corner to corner length self.radiusPixelMode = 'min'
def __init__(self, parent=0): # get pixel-size-dependent parameters # calculate this before calling superclass init # so it can be used to set mrml defaults if needed labelVolume = EditUtil.getLabelVolume() if labelVolume and labelVolume.GetImageData(): spacing = labelVolume.GetSpacing() dimensions = labelVolume.GetImageData().GetDimensions() self.minimumRadius = 0.5 * min(spacing) bounds = [a * b for a, b in zip(spacing, dimensions)] self.maximumRadius = 0.5 * max(bounds) else: self.minimumRadius = 0.01 self.maximumRadius = 100 super(PaintEffectOptions, self).__init__(parent) # option to use 'min' or 'diag' # - min means pixel radius is min spacing # - diag means corner to corner length self.radiusPixelMode = 'min'
def setQuickieRadius(self, radius): labelVolume = EditUtil.getLabelVolume() if labelVolume: if self.radiusUnitsToggle.text == 'px:': spacing = labelVolume.GetSpacing() if self.radiusPixelMode == 'diag': from math import sqrt diag = sqrt( reduce(lambda x, y: x + y, map(lambda x: x**2, spacing))) mmRadius = diag * radius elif self.radiusPixelMode == 'min': mmRadius = min(spacing) * radius else: print(self, "Unknown pixel mode - using 5mm") mmRadius = 5 else: mmRadius = radius self.disconnectWidgets() self.radiusSpinBox.setValue(mmRadius) self.radius.setValue(mmRadius) self.connectWidgets() self.updateMRMLFromGUI()
def _onEffectChanged(self, effectName): if self.currentEffect == effectName: return # # If there is no background volume or label map, do nothing # if not EditUtil.getBackgroundVolume(): return if not EditUtil.getLabelVolume(): return self.currentEffect = effectName EditUtil.restoreLabel() # Update action if possible - if not, we aren't ready to select the effect if effectName not in self.actions: return self.actions[effectName].checked = True # # an effect was selected, so build an options GUI # - check to see if it is an extension effect, # if not, try to create it, else ignore it # For extensions, look for 'effect'Options and 'effect'Tool # in the editorExtensions map and use those to create the # effect # if self.currentOption: # clean up any existing effect self.currentOption.__del__() self.currentOption = None for tool in self.currentTools: tool.sliceWidget.unsetCursor() tool.cleanup() self.currentTools = [] # look at builtins and extensions # - TODO: other effect styles are deprecated effectClass = None if effectName in slicer.modules.editorExtensions.keys(): effectClass = slicer.modules.editorExtensions[effectName]() elif effectName in self.editorBuiltins.keys(): effectClass = self.editorBuiltins[effectName]() if effectClass: # for effects, create an options gui and an # instance for every slice view self.currentOption = effectClass.options(self.optionsFrame) self.currentOption.setMRMLDefaults() self.currentOption.undoRedo = self.undoRedo self.currentOption.defaultEffect = self.defaultEffect self.currentOption.create() self.currentOption.updateGUI() layoutManager = slicer.app.layoutManager() sliceNodeCount = slicer.mrmlScene.GetNumberOfNodesByClass( 'vtkMRMLSliceNode') for nodeIndex in xrange(sliceNodeCount): # find the widget for each node in scene sliceNode = slicer.mrmlScene.GetNthNodeByClass( nodeIndex, 'vtkMRMLSliceNode') sliceWidget = layoutManager.sliceWidget( sliceNode.GetLayoutName()) if sliceWidget: tool = effectClass.tool(sliceWidget) tool.undoRedo = self.undoRedo self.currentTools.append(tool) self.currentOption.tools = self.currentTools else: # fallback to internal classes try: options = eval("%sOptions" % effectName) self.currentOption = options(self.optionsFrame) except NameError, AttributeError: # No options for this effect, skip it pass
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 = 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.objectName = self.__class__.__name__ + 'Apply' 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 marks. 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 makeModel(self,modelName='EditorModel',smooth=True): # # create a model using the command line module # based on the current editor parameters # volumeNode = EditUtil.getLabelVolume() if not volumeNode: return # # set up the model maker node # parameters = {} parameters['Name'] = modelName parameters["InputVolume"] = volumeNode.GetID() parameters['FilterType'] = "Sinc" # build only the currently selected model. parameters['Labels'] = EditUtil.getLabel() parameters["StartLabel"] = -1 parameters["EndLabel"] = -1 parameters['GenerateAll'] = False parameters["JointSmoothing"] = False parameters["SplitNormals"] = True parameters["PointNormals"] = True parameters["SkipUnNamed"] = True if smooth: parameters["Decimate"] = 0.25 parameters["Smooth"] = 10 else: parameters["Decimate"] = 0 parameters["Smooth"] = 0 # # output # - make a new hierarchy node if needed # numNodes = slicer.mrmlScene.GetNumberOfNodesByClass( "vtkMRMLModelHierarchyNode" ) outHierarchy = None for n in xrange(numNodes): node = slicer.mrmlScene.GetNthNodeByClass( n, "vtkMRMLModelHierarchyNode" ) if node.GetName() == "Editor Models": outHierarchy = node break if not outHierarchy: outHierarchy = slicer.vtkMRMLModelHierarchyNode() outHierarchy.SetScene( slicer.mrmlScene ) outHierarchy.SetName( "Editor Models" ) slicer.mrmlScene.AddNode( outHierarchy ) parameters["ModelSceneFile"] = outHierarchy modelMaker = slicer.modules.modelmaker # # run the task (in the background) # - use the GUI to provide progress feedback # - use the GUI's Logic to invoke the task # - model will show up when the processing is finished # slicer.cli.run(modelMaker, None, parameters) slicer.util.showStatusMessage( "Model Making Started...", 2000 )
def _onEffectChanged(self, effectName): if self.currentEffect == effectName: return # # If there is no background volume or label map, do nothing # if not EditUtil.getBackgroundVolume(): return if not EditUtil.getLabelVolume(): return self.currentEffect = effectName EditUtil.restoreLabel() # Update action if possible - if not, we aren't ready to select the effect if effectName not in self.actions: return self.actions[effectName].checked = True # # an effect was selected, so build an options GUI # - check to see if it is an extension effect, # if not, try to create it, else ignore it # For extensions, look for 'effect'Options and 'effect'Tool # in the editorExtensions map and use those to create the # effect # if self.currentOption: # clean up any existing effect self.currentOption.__del__() self.currentOption = None for tool in self.currentTools: tool.sliceWidget.unsetCursor() tool.cleanup() self.currentTools = [] # look at builtins and extensions # - TODO: other effect styles are deprecated effectClass = None if effectName in slicer.modules.editorExtensions.keys(): effectClass = slicer.modules.editorExtensions[effectName]() elif effectName in self.editorBuiltins.keys(): effectClass = self.editorBuiltins[effectName]() if effectClass: # for effects, create an options gui and an # instance for every slice view self.currentOption = effectClass.options(self.optionsFrame) self.currentOption.setMRMLDefaults() self.currentOption.undoRedo = self.undoRedo self.currentOption.defaultEffect = self.defaultEffect self.currentOption.create() self.currentOption.updateGUI() layoutManager = slicer.app.layoutManager() sliceNodeCount = slicer.mrmlScene.GetNumberOfNodesByClass('vtkMRMLSliceNode') for nodeIndex in xrange(sliceNodeCount): # find the widget for each node in scene sliceNode = slicer.mrmlScene.GetNthNodeByClass(nodeIndex, 'vtkMRMLSliceNode') sliceWidget = layoutManager.sliceWidget(sliceNode.GetLayoutName()) if sliceWidget: tool = effectClass.tool(sliceWidget) tool.undoRedo = self.undoRedo self.currentTools.append(tool) self.currentOption.tools = self.currentTools else: # fallback to internal classes try: options = eval("%sOptions" % effectName) self.currentOption = options(self.optionsFrame) except NameError, AttributeError: # No options for this effect, skip it pass
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 = 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.objectName = self.__class__.__name__ + 'Apply' 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 marks. 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 makeModel(self, modelName='EditorModel', smooth=True): # # create a model using the command line module # based on the current editor parameters # volumeNode = EditUtil.getLabelVolume() if not volumeNode: return # # set up the model maker node # parameters = {} parameters['Name'] = modelName parameters["InputVolume"] = volumeNode.GetID() parameters['FilterType'] = "Sinc" # build only the currently selected model. parameters['Labels'] = EditUtil.getLabel() parameters["StartLabel"] = -1 parameters["EndLabel"] = -1 parameters['GenerateAll'] = False parameters["JointSmoothing"] = False parameters["SplitNormals"] = True parameters["PointNormals"] = True parameters["SkipUnNamed"] = True if smooth: parameters["Decimate"] = 0.25 parameters["Smooth"] = 10 else: parameters["Decimate"] = 0 parameters["Smooth"] = 0 # # output # - make a new hierarchy node if needed # numNodes = slicer.mrmlScene.GetNumberOfNodesByClass( "vtkMRMLModelHierarchyNode") outHierarchy = None for n in xrange(numNodes): node = slicer.mrmlScene.GetNthNodeByClass( n, "vtkMRMLModelHierarchyNode") if node.GetName() == "Editor Models": outHierarchy = node break if not outHierarchy: outHierarchy = slicer.vtkMRMLModelHierarchyNode() outHierarchy.SetScene(slicer.mrmlScene) outHierarchy.SetName("Editor Models") slicer.mrmlScene.AddNode(outHierarchy) parameters["ModelSceneFile"] = outHierarchy modelMaker = slicer.modules.modelmaker # # run the task (in the background) # - use the GUI to provide progress feedback # - use the GUI's Logic to invoke the task # - model will show up when the processing is finished # slicer.cli.run(modelMaker, None, parameters) slicer.util.showStatusMessage("Model Making Started...", 2000)