Beispiel #1
0
class HelperBox(VTKObservationMixin):

  mergeValidCommand = _map_property(lambda self: self.structureListWidget, "mergeValidCommand")

  # Backward compatibility
  structures = _map_property(lambda self: self.structureListWidget, "structures")

  def __init__(self, parent=None):
    VTKObservationMixin.__init__(self)

    self.editUtil = EditUtil() # Kept for backward compatibility

    # mrml volume node instances
    self.master = None
    self.masterWhenMergeWasSet = None
    # Editor color LUT
    self.colorNodeID = None
    # string
    self.createMergeOptions = ""
    self.mergeVolumePostfix = "-label"
    # slicer helper class
    self.volumesLogic = slicer.modules.volumes.logic()
    # widgets that are dynamically created on demand
    # pseudo signals
    # - python callable that gets True or False
    self.selectCommand = None

    if not parent:
      self.parent = slicer.qMRMLWidget()
      self.parent.setLayout(qt.QVBoxLayout())
      self.parent.setMRMLScene(slicer.mrmlScene)
      self.create()
      self.parent.show()
    else:
      self.parent = parent
      self.create()

  def onEnter(self):

    self.addObserver(slicer.mrmlScene,
        slicer.vtkMRMLScene.NodeAddedEvent,
        self.structureListWidget.updateStructures)

    self.addObserver(slicer.mrmlScene,
        slicer.vtkMRMLScene.NodeRemovedEvent,
        self.structureListWidget.updateStructures)

  def onExit(self):
    self.removeObservers(method=self.structureListWidget.updateStructures)

  def cleanup(self):
    self.onExit()
    self.structureListWidget.cleanup()

  @property
  def merge(self):
    return self.mergeSelector.currentNode()

  @merge.setter
  def merge(self, node):
    self.mergeSelector.setCurrentNode(node)

  def newMerge(self):
    """create a merge volume for the current master even if one exists"""
    self.createMergeOptions = "new"
    self.labelCreateDialog()

  def createMerge(self):
    """create a merge volume for the current master"""
    if not self.master:
      # should never happen
      slicer.util.errorDisplay( "Cannot create merge volume without master" )

    masterName = self.master.GetName()
    mergeName = masterName + self.mergeVolumePostfix
    if self.createMergeOptions.find("new") >= 0:
      merge = None
    else:
      merge = self.mergeVolume()
    self.createMergeOptions = ""

    if not merge:
      merge = self.volumesLogic.CreateAndAddLabelVolume( slicer.mrmlScene, self.master, mergeName )
      merge.GetDisplayNode().SetAndObserveColorNodeID( self.colorNodeID )
      self.setMergeVolume( merge )
    self.select(mergeVolume=merge)

  def select(self, masterVolume=None, mergeVolume=None):
    """select master volume - load merge volume if one with the correct name exists"""

    if masterVolume is None:
        masterVolume = self.masterSelector.currentNode()
    self.master = masterVolume

    self.masterSelector.blockSignals(True)
    self.masterSelector.setCurrentNode(self.master)
    self.masterSelector.blockSignals(False)

    self.mergeSelector.setCurrentNode(mergeVolume)

    if self.master and not self.mergeVolume():
      # the master exists, but there is no merge volume yet
      # bring up dialog to create a merge with a user-selected color node
      self.labelCreateDialog()

    merge = self.mergeVolume()
    if merge:
      if not merge.IsA("vtkMRMLLabelMapVolumeNode"):
        slicer.util.errorDisplay( "Error: selected merge label volume is not a label volume" )
      else:
        EditUtil.setActiveVolumes(self.master, merge)
        self.mergeSelector.setCurrentNode(merge)

    self.structureListWidget.master = self.master
    self.structureListWidget.merge = merge
    self.structureListWidget.updateStructures()

    if self.master and merge:
      warnings = self.volumesLogic.CheckForLabelVolumeValidity(self.master,merge)
      if warnings != "":
        warnings = "Geometry of master and merge volumes do not match.\n\n" + warnings
        slicer.util.errorDisplay( "Warning: %s" % warnings )

    # trigger a modified event on the parameter node so that other parts of the GUI
    # (such as the EditColor) will know to update and enable themselves
    EditUtil.getParameterNode().Modified()

    if self.selectCommand:
      self.selectCommand()

  def setVolumes(self,masterVolume,mergeVolume):
    """set both volumes at the same time - trick the callback into
    thinking that the merge volume is already set so it won't prompt for a new one"""
    self.masterWhenMergeWasSet = masterVolume
    self.select(masterVolume=masterVolume, mergeVolume=mergeVolume)

  def setMasterVolume(self,masterVolume):
    """select merge volume"""
    if isinstance(masterVolume, basestring):
      masterVolume = slicer.mrmlScene.GetNodeByID(masterVolume)
    self.masterSelector.setCurrentNode( masterVolume )

  def setMergeVolume(self,mergeVolume=None):
    """select merge volume"""
    if isinstance(mergeVolume, basestring):
      mergeVolume = slicer.mrmlScene.GetNodeByID(mergeVolume)
    if self.master:
      self.masterWhenMergeWasSet = self.master
      self.select(masterVolume=self.master,mergeVolume=mergeVolume)

  def mergeVolume(self):
    """select merge volume"""
    if not self.master:
      return None

    # if we already have a merge and the master hasn't changed, use it
    if self.mergeSelector.currentNode() and self.master == self.masterWhenMergeWasSet:
      return self.mergeSelector.currentNode()

    self.masterWhenMergeWasSet = None

    # otherwise pick the merge based on the master name
    # - either return the merge volume or empty string
    masterName = self.master.GetName()
    mergeName = masterName + self.mergeVolumePostfix
    merge = slicer.util.getFirstNodeByName(mergeName, className=self.master.GetClassName())
    self.mergeSelector.setCurrentNode(merge)
    return self.mergeSelector.currentNode()

  #
  # callback helpers (slots)
  #
  def onSelect(self, node):
    self.select()

  def onMergeSelect(self, node):
    self.select(mergeVolume=node)


  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 selectStructure(self, idx):
    """backward compatibility"""
    self.structureListWidget.selectStructure(idx)

  def labelCreateDialog(self):
    """label create dialog"""
    if self.master is None:
        return
    dlg = LabelCreateDialog(slicer.util.mainWindow(), self.master, self.mergeVolumePostfix)
    colorLogic = slicer.modules.colors.logic()
    dlg.colorNodeID = colorLogic.GetDefaultEditorColorNodeID()

    if dlg.exec_() == qt.QDialog.Accepted:
      self.colorNodeID = dlg.colorNodeID
      self.createMerge()
Beispiel #2
0
class HelperBox(VTKObservationMixin):

    mergeValidCommand = _map_property(lambda self: self.structureListWidget,
                                      "mergeValidCommand")

    # Backward compatibility
    structures = _map_property(lambda self: self.structureListWidget,
                               "structures")

    def __init__(self, parent=None):
        VTKObservationMixin.__init__(self)

        self.editUtil = EditUtil()  # Kept for backward compatibility

        # mrml volume node instances
        self.master = None
        self.masterWhenMergeWasSet = None
        # Editor color LUT
        self.colorNodeID = None
        # string
        self.createMergeOptions = ""
        self.mergeVolumePostfix = "-label"
        # slicer helper class
        self.volumesLogic = slicer.modules.volumes.logic()
        # widgets that are dynamically created on demand
        # pseudo signals
        # - python callable that gets True or False
        self.selectCommand = None

        if not parent:
            self.parent = slicer.qMRMLWidget()
            self.parent.setLayout(qt.QVBoxLayout())
            self.parent.setMRMLScene(slicer.mrmlScene)
            self.create()
            self.parent.show()
        else:
            self.parent = parent
            self.create()

    def onEnter(self):

        self.addObserver(slicer.mrmlScene, slicer.vtkMRMLScene.NodeAddedEvent,
                         self.structureListWidget.updateStructures)

        self.addObserver(slicer.mrmlScene,
                         slicer.vtkMRMLScene.NodeRemovedEvent,
                         self.structureListWidget.updateStructures)

    def onExit(self):
        self.removeObservers(method=self.structureListWidget.updateStructures)

    def cleanup(self):
        self.onExit()
        self.structureListWidget.cleanup()

    @property
    def merge(self):
        return self.mergeSelector.currentNode()

    @merge.setter
    def merge(self, node):
        self.mergeSelector.setCurrentNode(node)

    def newMerge(self):
        """create a merge volume for the current master even if one exists"""
        self.createMergeOptions = "new"
        self.labelCreateDialog()

    def createMerge(self):
        """create a merge volume for the current master"""
        if not self.master:
            # should never happen
            slicer.util.errorDisplay(
                "Cannot create merge volume without master")

        masterName = self.master.GetName()
        mergeName = masterName + self.mergeVolumePostfix
        if self.createMergeOptions.find("new") >= 0:
            merge = None
        else:
            merge = self.mergeVolume()
        self.createMergeOptions = ""

        if not merge:
            merge = self.volumesLogic.CreateAndAddLabelVolume(
                slicer.mrmlScene, self.master, mergeName)
            merge.GetDisplayNode().SetAndObserveColorNodeID(self.colorNodeID)
            self.setMergeVolume(merge)
        self.select(mergeVolume=merge)

    def select(self, masterVolume=None, mergeVolume=None):
        """select master volume - load merge volume if one with the correct name exists"""

        if masterVolume == None:
            masterVolume = self.masterSelector.currentNode()
        self.master = masterVolume

        self.masterSelector.blockSignals(True)
        self.masterSelector.setCurrentNode(self.master)
        self.masterSelector.blockSignals(False)

        self.mergeSelector.setCurrentNode(mergeVolume)

        if self.master and not self.mergeVolume():
            # the master exists, but there is no merge volume yet
            # bring up dialog to create a merge with a user-selected color node
            self.labelCreateDialog()

        merge = self.mergeVolume()
        if merge:
            if not merge.IsA("vtkMRMLLabelMapVolumeNode"):
                slicer.util.errorDisplay(
                    "Error: selected merge label volume is not a label volume")
            else:
                EditUtil.setActiveVolumes(self.master, merge)
                self.mergeSelector.setCurrentNode(merge)

        self.structureListWidget.master = self.master
        self.structureListWidget.merge = merge
        self.structureListWidget.updateStructures()

        if self.master and merge:
            warnings = self.volumesLogic.CheckForLabelVolumeValidity(
                self.master, merge)
            if warnings != "":
                warnings = "Geometry of master and merge volumes do not match.\n\n" + warnings
                slicer.util.errorDisplay("Warning: %s" % warnings)

        # trigger a modified event on the parameter node so that other parts of the GUI
        # (such as the EditColor) will know to update and enable themselves
        EditUtil.getParameterNode().Modified()

        if self.selectCommand:
            self.selectCommand()

    def setVolumes(self, masterVolume, mergeVolume):
        """set both volumes at the same time - trick the callback into
    thinking that the merge volume is already set so it won't prompt for a new one"""
        self.masterWhenMergeWasSet = masterVolume
        self.select(masterVolume=masterVolume, mergeVolume=mergeVolume)

    def setMasterVolume(self, masterVolume):
        """select merge volume"""
        if isinstance(masterVolume, basestring):
            masterVolume = slicer.mrmlScene.GetNodeByID(masterVolume)
        self.masterSelector.setCurrentNode(masterVolume)

    def setMergeVolume(self, mergeVolume=None):
        """select merge volume"""
        if isinstance(mergeVolume, basestring):
            mergeVolume = slicer.mrmlScene.GetNodeByID(mergeVolume)
        if self.master:
            self.masterWhenMergeWasSet = self.master
            self.select(masterVolume=self.master, mergeVolume=mergeVolume)

    def mergeVolume(self):
        """select merge volume"""
        if not self.master:
            return None

        # if we already have a merge and the master hasn't changed, use it
        if self.mergeSelector.currentNode(
        ) and self.master == self.masterWhenMergeWasSet:
            return self.mergeSelector.currentNode()

        self.masterWhenMergeWasSet = None

        # otherwise pick the merge based on the master name
        # - either return the merge volume or empty string
        masterName = self.master.GetName()
        mergeName = masterName + self.mergeVolumePostfix
        merge = slicer.util.getFirstNodeByName(
            mergeName, className=self.master.GetClassName())
        self.mergeSelector.setCurrentNode(merge)
        return self.mergeSelector.currentNode()

    #
    # callback helpers (slots)
    #
    def onSelect(self, node):
        self.select()

    def onMergeSelect(self, node):
        self.select(mergeVolume=node)

    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 selectStructure(self, idx):
        """backward compatibility"""
        self.structureListWidget.selectStructure(idx)

    def labelCreateDialog(self):
        """label create dialog"""
        if self.master is None:
            return
        dlg = LabelCreateDialog(slicer.util.mainWindow(), self.master,
                                self.mergeVolumePostfix)
        colorLogic = slicer.modules.colors.logic()
        dlg.colorNodeID = colorLogic.GetDefaultEditorColorNodeID()

        if dlg.exec_() == qt.QDialog.Accepted:
            self.colorNodeID = dlg.colorNodeID
            self.createMerge()
Beispiel #3
0
  def create(self):
    """create the segmentation helper box"""

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

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

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

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


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

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

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

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

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

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

    #
    # signals, slots, and observers
    #

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

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

    # so buttons will initially be disabled
    self.master = None
    self.structureListWidget.updateStructures()
Beispiel #4
0
    def create(self):
        """create the segmentation helper box"""

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

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

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

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

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

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

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

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

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

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

        #
        # signals, slots, and observers
        #

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

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

        # so buttons will initially be disabled
        self.master = None
        self.structureListWidget.updateStructures()