Пример #1
0
 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()
Пример #2
0
  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'
Пример #3
0
    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'
Пример #4
0
 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()
Пример #5
0
    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
Пример #6
0
    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)
Пример #7
0
  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 )
Пример #8
0
  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)
Пример #10
0
    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)