コード例 #1
0
ファイル: ColorBox.py プロジェクト: dstoup/Slicer
 def __init__(self,
              parent=None,
              parameterNode=None,
              parameter=None,
              colorNode=None,
              selectCommand=None):
     self.colorNode = colorNode
     self.parameterNode = parameterNode
     self.parameter = parameter
     self.selectCommand = selectCommand
     self.recents = []
     self.label = None
     if not parent:
         self.parent = slicer.qMRMLWidget()
         self.parent.setObjectName('EditMRMLWidget')
         self.parent.setLayout(qt.QVBoxLayout())
         self.parent.setMRMLScene(slicer.mrmlScene)
         self.create()
         p = qt.QCursor().pos()
         self.parent.setGeometry(p.x(), p.y(), 300, 700)
         self.parent.show()
         self.parent.raise_()
     else:
         self.parent = parent
         self.create()
コード例 #2
0
ファイル: ExtensionWizard.py プロジェクト: Walkkking/Slicer
 def createReadOnlyLineEdit():
     le = qt.QLineEdit()
     le.readOnly = True
     le.frame = False
     le.styleSheet = "QLineEdit { background:transparent; }"
     le.cursor = qt.QCursor(qt.Qt.IBeamCursor)
     return le
コード例 #3
0
ファイル: EditBox.py プロジェクト: dstoup/Slicer
 def cursorForEffect(self, effectName):
     """Return an instance of QCursor customized for the given effectName.
 TODO: this could be moved to the EffectTool class so that effects can manage
 per-widget cursors, possibly turning them off or making them dynamic
 """
     if not effectName in self.effectCursors:
         baseImage = qt.QImage(":/Icons/AnnotationPointWithArrow.png")
         effectImage = qt.QImage(self.effectIconFiles[effectName])
         width = max(baseImage.width(), effectImage.width())
         pad = -9
         height = pad + baseImage.height() + effectImage.height()
         width = height = max(width, height)
         center = int(width / 2)
         cursorImage = qt.QImage(width, height, qt.QImage().Format_ARGB32)
         painter = qt.QPainter()
         cursorImage.fill(0)
         painter.begin(cursorImage)
         point = qt.QPoint(center - (baseImage.width() / 2), 0)
         painter.drawImage(point, baseImage)
         point.setX(center - (effectImage.width() / 2))
         point.setY(cursorImage.height() - effectImage.height())
         painter.drawImage(point, effectImage)
         painter.end()
         cursorPixmap = qt.QPixmap()
         cursorPixmap = cursorPixmap.fromImage(cursorImage)
         self.effectCursors[effectName] = qt.QCursor(
             cursorPixmap, center, 0)
     return self.effectCursors[effectName]
コード例 #4
0
ファイル: HelperBox.py プロジェクト: franklinwk/Slicer
  def labelSelectDialog(self):
    """label table dialog"""

    if not self.labelSelect:
      self.labelSelect = qt.QFrame()
      self.labelSelect.setLayout( qt.QVBoxLayout() )

      self.labelPromptLabel = qt.QLabel()
      self.labelSelect.layout().addWidget( self.labelPromptLabel )


      self.labelSelectorFrame = qt.QFrame()
      self.labelSelectorFrame.setLayout( qt.QHBoxLayout() )
      self.labelSelect.layout().addWidget( self.labelSelectorFrame )

      self.labelSelectorLabel = qt.QLabel()
      self.labelPromptLabel.setText( "Label Map: " )
      self.labelSelectorFrame.layout().addWidget( self.labelSelectorLabel )

      self.labelSelector = slicer.qMRMLNodeComboBox()
      self.labelSelector.nodeTypes = ( "vtkMRMLScalarVolumeNode", "" )
      self.labelSelector.addAttribute( "vtkMRMLScalarVolumeNode", "LabelMap", "1" )
      # todo addAttribute
      self.labelSelector.selectNodeUponCreation = False
      self.labelSelector.addEnabled = False
      self.labelSelector.noneEnabled = False
      self.labelSelector.removeEnabled = False
      self.labelSelector.showHidden = False
      self.labelSelector.showChildNodeTypes = False
      self.labelSelector.setMRMLScene( slicer.mrmlScene )
      self.labelSelector.setToolTip( "Pick the label map to edit" )
      self.labelSelectorFrame.layout().addWidget( self.labelSelector )

      self.labelButtonFrame = qt.QFrame()
      self.labelButtonFrame.setLayout( qt.QHBoxLayout() )
      self.labelSelect.layout().addWidget( self.labelButtonFrame )

      self.labelDialogApply = qt.QPushButton("Apply", self.labelButtonFrame)
      self.labelDialogApply.setToolTip( "Use currently selected label node." )
      self.labelButtonFrame.layout().addWidget(self.labelDialogApply)

      self.labelDialogCancel = qt.QPushButton("Cancel", self.labelButtonFrame)
      self.labelDialogCancel.setToolTip( "Cancel current operation." )
      self.labelButtonFrame.layout().addWidget(self.labelDialogCancel)

      self.labelButtonFrame.layout().addStretch(1)

      self.labelDialogCreate = qt.QPushButton("Create New...", self.labelButtonFrame)
      self.labelDialogCreate.setToolTip( "Cancel current operation." )
      self.labelButtonFrame.layout().addWidget(self.labelDialogCreate)

      self.labelDialogApply.connect("clicked()", self.onLabelDialogApply)
      self.labelDialogCancel.connect("clicked()", self.labelSelect.hide)
      self.labelDialogCreate.connect("clicked()", self.onLabelDialogCreate)

    self.labelPromptLabel.setText( "Select existing label map volume to edit." )
    p = qt.QCursor().pos()
    self.labelSelect.setGeometry(p.x(), p.y(), 400, 200)
    self.labelSelect.show()
コード例 #5
0
 def cursorOff(self, widget):
     """Turn off and save the current cursor so
 the user can see an overlay that tracks the mouse"""
     if self.savedWidget == widget:
         return
     else:
         self.cursorOn()
     self.savedWidget = widget
     self.savedCursor = widget.cursor
     qt_BlankCursor = 10
     widget.setCursor(qt.QCursor(qt_BlankCursor))
コード例 #6
0
ファイル: EditBox.py プロジェクト: WYZ621/Slicer
 def enterFloatingMode(self):
   self.mainFrame.setParent(None)
   cursorPosition = qt.QCursor().pos()
   w = self.mainFrame.width
   h = self.mainFrame.height
   self.mainFrame.pos = qt.QPoint(cursorPosition.x() - w/2, cursorPosition.y() - h/2)
   self.mainFrame.show()
   self.mainFrame.raise_()
   Key_Space = 0x20 # not in PythonQt
   self.toggleShortcut = qt.QShortcut(self.mainFrame)
   self.toggleShortcut.setKey( qt.QKeySequence(Key_Space) )
   self.toggleShortcut.connect( 'activated()', self.toggleFloatingMode )
コード例 #7
0
    def registerPlanCtToCbctLandmark(self, planCtFiducialListID,
                                     cbctFiducialListID):
        try:
            qt.QApplication.setOverrideCursor(qt.QCursor(qt.Qt.BusyCursor))
            parametersFiducial = {}
            parametersFiducial["fixedLandmarks"] = cbctFiducialListID
            parametersFiducial["movingLandmarks"] = planCtFiducialListID

            # Create linear transform which will store the registration transform
            try:
                cbctToPlanTransformNode = slicer.util.getNode(
                    self.cbctToPlanTransformName)
            except:
                cbctToPlanTransformNode = slicer.vtkMRMLLinearTransformNode()
                slicer.mrmlScene.AddNode(cbctToPlanTransformNode)
                cbctToPlanTransformNode.SetName(self.cbctToPlanTransformName)
            parametersFiducial[
                "saveTransform"] = cbctToPlanTransformNode.GetID()
            parametersFiducial["transformType"] = "Rigid"

            # Run fiducial registration
            fiducialRegistration = slicer.modules.fiducialregistration
            cliFiducialRegistrationRigidNode = None
            cliFiducialRegistrationRigidNode = slicer.cli.run(
                fiducialRegistration, None, parametersFiducial)

            waitCount = 0
            while cliFiducialRegistrationRigidNode.GetStatusString(
            ) != 'Completed' and waitCount < 200:
                self.delayDisplay(
                    "Register PLANCT to CBCT using fiducial registration... %d"
                    % waitCount)
                waitCount += 1
            self.delayDisplay(
                "Register PLANCT to CBCT using fiducial registration finished")
            qt.QApplication.restoreOverrideCursor()

            # Apply transform to PLANCT fiducials
            planCtFiducialsNode = slicer.mrmlScene.GetNodeByID(
                planCtFiducialListID)
            planCtFiducialsNode.SetAndObserveTransformNodeID(
                cbctToPlanTransformNode.GetID())

            return [
                cbctToPlanTransformNode,
                cliFiducialRegistrationRigidNode.GetParameterAsString('rms')
            ]

        except Exception as e:
            import traceback
            traceback.print_exc()
コード例 #8
0
    def registerPlanCtToCbctAutomatic(self, planCtVolumeID, cbctVolumeID):
        try:
            qt.QApplication.setOverrideCursor(qt.QCursor(qt.Qt.BusyCursor))
            parametersRigid = {}
            parametersRigid["fixedVolume"] = cbctVolumeID
            parametersRigid["movingVolume"] = planCtVolumeID
            parametersRigid["useRigid"] = True
            parametersRigid["initializeTransformMode"] = "useGeometryAlign"
            parametersRigid["samplingPercentage"] = 0.0005
            parametersRigid[
                "maximumStepLength"] = 15  # Start with long-range translations
            parametersRigid["relaxationFactor"] = 0.8  # Relax quickly
            parametersRigid["translationScale"] = 1000000  # Suppress rotation
            # parametersRigid["backgroundFillValue"] = -1000.0

            # Set output transform
            try:
                cbctToPlanTransformNode = slicer.util.getNode(
                    self.cbctToPlanTransformName)
            except:
                cbctToPlanTransformNode = slicer.vtkMRMLLinearTransformNode()
                slicer.mrmlScene.AddNode(cbctToPlanTransformNode)
                cbctToPlanTransformNode.SetName(self.cbctToPlanTransformName)
            parametersRigid["linearTransform"] = cbctToPlanTransformNode.GetID(
            )

            # Runs the brainsfit registration
            brainsFit = slicer.modules.brainsfit
            cliBrainsFitRigidNode = None
            cliBrainsFitRigidNode = slicer.cli.run(brainsFit, None,
                                                   parametersRigid)

            waitCount = 0
            while cliBrainsFitRigidNode.GetStatusString(
            ) != 'Completed' and waitCount < 200:
                self.delayDisplay(
                    "Register PlanCT to CBCT using rigid registration... %d" %
                    waitCount)
                waitCount += 1
            self.delayDisplay(
                "Register PlanCT to CBCT using rigid registration finished")
            qt.QApplication.restoreOverrideCursor()

            # Invert output transform (planToCbct) to get the desired cbctToPlan transform
            cbctToPlanTransformNode.GetMatrixTransformToParent().Invert()

            return cbctToPlanTransformNode

        except Exception as e:
            import traceback
            traceback.print_exc()
コード例 #9
0
    def __init__(self, parent):
        print("Initializing paint")
        self.painting = False
        self.parent = parent
        self.crosshairNode = slicer.util.getNode('Crosshair')
        self.crosshairNode.AddObserver(
            slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent,
            self.onMouseMoved)

        self.myArray = []
        #slicer.util.array(self.parent.labelNode.GetID())
        #self.editUtil = EditorLib.EditUtil.EditUtil()

        for e in [
                "LeftButtonPressEvent", "LeftButtonReleaseEvent",
                "MouseMoveEvent"
        ]:
            print("Adding observer to interactor: " + e)
            self.parent.AddObserver(e, self.processEvent, 1.0)
        cursorPosition = qt.QCursor().pos()
        print(cursorPosition.x(), cursorPosition.y())
コード例 #10
0
 def __init__(self):
     '''
     Constructor
     '''
     """
     path=slicer.modules.usguidedprocedure.path
     modulePath=os.path.dirname(path)
     loadedDataGUIfile=os.path.join(modulePath,"USGuidedWizard/loadedData.ui")
     f = qt.QFile(loadedDataGUIfile)
     #f = qt.QFile('C:/Users/Usuario/devel/slicelets/USGuidedProcedure/USGuidedWizard/fiducials.ui')
     f.open(qt.QFile.ReadOnly)
     loader = qt.QUiLoader()
     self.loadedDataWidget = loader.load(f)
     f.close()
     """
     
     # UI   from QtDesigner  -----------------------------------------------------------------------------
     path=slicer.modules.stylusbasedusprobecalibration.path
     modulePath=os.path.dirname(path)
     fiducialsStepGUIfile=os.path.join(modulePath,"GUI/fiducials.ui")
     f = qt.QFile(fiducialsStepGUIfile)
     #f = qt.QFile('C:/Users/Usuario/devel/slicelets/USGuidedProcedure/USGuidedWizard/fiducials.ui')
     f.open(qt.QFile.ReadOnly)
     loader = qt.QUiLoader()
     self.fiducialsWidget = loader.load(f)
     f.close()
     
     # connect signals and slots
     self.fiducialsWidget.fiducialsList.connect('cellChanged(int ,int )', self.onFiducialNameChanged) 
     self.fiducialsWidget.placeFiducialButton.connect('clicked(bool)', self.onPlaceFiducialButtomClicked) 
     self.fiducialsWidget.removeFiducialButton.connect('clicked(bool)', self.onRemoveFiducialButtonClicked)
     self.fiducialsWidget.clearFiducialsListButton.connect('clicked(bool)', self.onClearFiducialsListButtonClicked)
     self.fiducialsWidget.fiducialsList.itemClicked.connect(self.onFiducialsListClicked)
 
     #listeners
     #self.listenToAnnotations()
     self.updatingList = False
     self.placeImageFiducialStep=False
     pixmap=qt.QPixmap("Resources/Icons/AnnotationPointWithArrow.png")
     self.placeFiducialCursor= qt.QCursor(pixmap)
コード例 #11
0
    def calibrate(self, measuredVolumeID):
        qt.QApplication.setOverrideCursor(qt.QCursor(qt.Qt.BusyCursor))
        import time
        start = time.time()

        measuredVolume = slicer.util.getNode(measuredVolumeID)
        calibratedVolume = slicer.vtkMRMLScalarVolumeNode()
        calibratedVolumeName = measuredVolume.GetName() + '_Calibrated'
        calibratedVolumeName = slicer.mrmlScene.GenerateUniqueName(
            calibratedVolumeName)
        calibratedVolume.SetName(calibratedVolumeName)
        slicer.mrmlScene.AddNode(calibratedVolume)
        measuredImageDataCopy = vtk.vtkImageData()
        measuredImageDataCopy.DeepCopy(measuredVolume.GetImageData())
        calibratedVolume.SetAndObserveImageData(measuredImageDataCopy)
        calibratedVolume.CopyOrientation(measuredVolume)
        if measuredVolume.GetParentTransformNode() != None:
            calibratedVolume.SetAndObserveTransformNodeID(
                measuredVolume.GetParentTransformNode().GetID())

        coefficients = numpy_support.numpy_to_vtk(
            self.calibrationPolynomialCoefficients)

        if slicer.modules.geldosimetryanalysisalgo.logic(
        ).ApplyPolynomialFunctionOnVolume(calibratedVolume,
                                          coefficients) == False:
            logging.error('Calibration failed')
            slicer.mrmlScene.RemoveNode(calibratedVolume)
            return None

        end = time.time()
        qt.QApplication.restoreOverrideCursor()
        logging.info(
            'Calibration of MEASURED volume is successful (time: {0})'.format(
                end - start))
        return calibratedVolume
コード例 #12
0
ファイル: ColorBox.py プロジェクト: satra/Slicer
 def __init__(self,
              parent=None,
              parameterNode=None,
              parameter=None,
              colorNode=None,
              selectCommand=None):
     self.colorNode = colorNode
     self.parameterNode = parameterNode
     self.parameter = parameter
     self.selectCommand = selectCommand
     self.showRecents = False  # TODO: make a group for recents for visual feedback (otherwise confusing)
     self.recents = []
     self.label = None
     if not parent:
         self.parent = slicer.qMRMLWidget()
         self.parent.setLayout(qt.QVBoxLayout())
         self.parent.setMRMLScene(slicer.mrmlScene)
         self.create()
         p = qt.QCursor().pos()
         self.parent.setGeometry(p.x(), p.y(), 300, 700)
         self.parent.show()
     else:
         self.parent = parent
         self.create()
コード例 #13
0
    def setup(self):
        # Instantiate and connect widgets ...
        self.RingOff = None
        self.RingOn = None

        # Tags to manage event observers
        self.tagSourceNode = None
        self.tagDestinationNode = None

        #####################
        ## For debugging
        ##
        ## Reload and Test area
        reloadCollapsibleButton = ctk.ctkCollapsibleButton()
        reloadCollapsibleButton.text = "Reload && Test"
        self.layout.addWidget(reloadCollapsibleButton)
        reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton)

        ## reload button
        ## (use this during development, but remove it when delivering
        ##  your module to users)
        self.reloadButton = qt.QPushButton("Reload")
        self.reloadButton.toolTip = "Reload this module."
        self.reloadButton.name = "CurveMaker Reload"
        reloadFormLayout.addWidget(self.reloadButton)
        self.reloadButton.connect('clicked()', self.onReload)
        ##
        #####################

        #
        # Parameters Area
        #
        parametersCollapsibleButton = ctk.ctkCollapsibleButton()
        parametersCollapsibleButton.text = "Parameters"
        self.layout.addWidget(parametersCollapsibleButton)

        # Layout within the dummy collapsible button
        parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton)

        #
        # Source points (vtkMRMLMarkupsFiducialNode)
        #
        self.SourceSelector = slicer.qMRMLNodeComboBox()
        self.SourceSelector.nodeTypes = (("vtkMRMLMarkupsFiducialNode"), "")
        self.SourceSelector.addEnabled = True
        self.SourceSelector.removeEnabled = False
        self.SourceSelector.noneEnabled = True
        self.SourceSelector.showHidden = False
        self.SourceSelector.renameEnabled = True
        self.SourceSelector.showChildNodeTypes = False
        self.SourceSelector.setMRMLScene(slicer.mrmlScene)
        self.SourceSelector.setToolTip(
            "Pick up a Markups node listing fiducials.")
        parametersFormLayout.addRow("Source points: ", self.SourceSelector)

        #
        # Target point (vtkMRMLMarkupsFiducialNode)
        #
        self.DestinationSelector = slicer.qMRMLNodeComboBox()
        self.DestinationSelector.nodeTypes = (("vtkMRMLModelNode"), "")
        self.DestinationSelector.addEnabled = True
        self.DestinationSelector.removeEnabled = False
        self.DestinationSelector.noneEnabled = True
        self.DestinationSelector.showHidden = False
        self.DestinationSelector.renameEnabled = True
        self.DestinationSelector.selectNodeUponCreation = True
        self.DestinationSelector.showChildNodeTypes = False
        self.DestinationSelector.setMRMLScene(slicer.mrmlScene)
        self.DestinationSelector.setToolTip("Pick up or create a Model node.")
        parametersFormLayout.addRow("Curve model: ", self.DestinationSelector)

        #
        # Radius for the tube
        #
        self.RadiusSliderWidget = ctk.ctkSliderWidget()
        self.RadiusSliderWidget.singleStep = 1.0
        self.RadiusSliderWidget.minimum = 1.0
        self.RadiusSliderWidget.maximum = 50.0
        self.RadiusSliderWidget.value = 5.0
        self.RadiusSliderWidget.setToolTip("Set the raidus of the tube.")
        parametersFormLayout.addRow("Radius (mm): ", self.RadiusSliderWidget)

        #
        # Radio button to select interpolation method
        #
        self.InterpolationLayout = qt.QHBoxLayout()
        self.InterpolationNone = qt.QRadioButton("None")
        self.InterpolationCardinalSpline = qt.QRadioButton("Cardinal Spline")
        self.InterpolationHermiteSpline = qt.QRadioButton(
            "Hermite Spline (for Endoscopy)")
        self.InterpolationLayout.addWidget(self.InterpolationNone)
        self.InterpolationLayout.addWidget(self.InterpolationCardinalSpline)
        self.InterpolationLayout.addWidget(self.InterpolationHermiteSpline)

        self.InterpolationGroup = qt.QButtonGroup()
        self.InterpolationGroup.addButton(self.InterpolationNone)
        self.InterpolationGroup.addButton(self.InterpolationCardinalSpline)
        self.InterpolationGroup.addButton(self.InterpolationHermiteSpline)

        parametersFormLayout.addRow("Interpolation: ",
                                    self.InterpolationLayout)

        #
        # Interpolation Resolution
        #
        self.InterpResolutionSliderWidget = ctk.ctkSliderWidget()
        self.InterpResolutionSliderWidget.singleStep = 1.0
        self.InterpResolutionSliderWidget.minimum = 3.0
        self.InterpResolutionSliderWidget.maximum = 50.0
        self.InterpResolutionSliderWidget.value = 25.0
        self.InterpResolutionSliderWidget.setToolTip(
            "Number of interpolation points between control points. Default is 25."
        )
        parametersFormLayout.addRow("Resolution: ",
                                    self.InterpResolutionSliderWidget)

        #
        # Radio button for ring mode
        #
        self.RingLayout = qt.QHBoxLayout()
        self.RingOff = qt.QRadioButton("Off")
        self.RingOn = qt.QRadioButton("On")
        self.RingLayout.addWidget(self.RingOff)
        self.RingLayout.addWidget(self.RingOn)
        self.RingGroup = qt.QButtonGroup()
        self.RingGroup.addButton(self.RingOff)
        self.RingGroup.addButton(self.RingOn)

        parametersFormLayout.addRow("Ring mode: ", self.RingLayout)

        #
        # Check box to start curve visualization
        #
        self.EnableAutoUpdateCheckBox = qt.QCheckBox()
        self.EnableAutoUpdateCheckBox.checked = 0
        self.EnableAutoUpdateCheckBox.setToolTip(
            "If checked, the CurveMaker module keeps updating the model as the points are updated."
        )
        parametersFormLayout.addRow("Auto update:",
                                    self.EnableAutoUpdateCheckBox)

        #
        # Button to generate a curve
        #
        self.GenerateButton = qt.QPushButton("Generate Curve")
        self.GenerateButton.toolTip = "Generate Curve"
        self.GenerateButton.enabled = True
        parametersFormLayout.addRow("", self.GenerateButton)

        # Connections
        self.InterpolationNone.connect('clicked(bool)',
                                       self.onSelectInterpolationNone)
        self.InterpolationCardinalSpline.connect(
            'clicked(bool)', self.onSelectInterpolationCardinalSpline)
        self.InterpolationHermiteSpline.connect(
            'clicked(bool)', self.onSelectInterpolationHermiteSpline)
        self.RingOff.connect('clicked(bool)', self.onRingOff)
        self.RingOn.connect('clicked(bool)', self.onRingOn)
        self.EnableAutoUpdateCheckBox.connect('toggled(bool)',
                                              self.onEnableAutoUpdate)
        self.SourceSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                    self.onSourceSelected)
        self.DestinationSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                         self.onDestinationSelected)
        self.RadiusSliderWidget.connect("valueChanged(double)",
                                        self.onTubeUpdated)
        self.InterpResolutionSliderWidget.connect(
            "valueChanged(double)", self.onInterpResolutionUpdated)
        self.GenerateButton.connect('clicked(bool)', self.onGenerateCurve)

        # Set default
        ## default interpolation method
        self.InterpolationCardinalSpline.setChecked(True)
        self.onSelectInterpolationCardinalSpline(True)

        ## default ring mode
        self.RingOff.setChecked(True)
        self.onRingOff(True)

        #
        # Curve Length area
        #
        lengthCollapsibleButton = ctk.ctkCollapsibleButton()
        lengthCollapsibleButton.text = "Length"
        self.layout.addWidget(lengthCollapsibleButton)
        lengthFormLayout = qt.QFormLayout(lengthCollapsibleButton)
        lengthCollapsibleButton.collapsed = True

        #-- Curve length
        self.lengthLineEdit = qt.QLineEdit()
        self.lengthLineEdit.text = '--'
        self.lengthLineEdit.readOnly = True
        self.lengthLineEdit.frame = True
        self.lengthLineEdit.styleSheet = "QLineEdit { background:transparent; }"
        self.lengthLineEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)

        lengthFormLayout.addRow("Curve Length (mm):", self.lengthLineEdit)

        #
        # Distance Area
        #
        distanceCollapsibleButton = ctk.ctkCollapsibleButton()
        distanceCollapsibleButton.text = "Distance"
        distanceCollapsibleButton.collapsed = True
        self.layout.addWidget(distanceCollapsibleButton)
        distanceFormLayout = qt.QFormLayout(distanceCollapsibleButton)

        #-- Point-to-curve distance

        #  - Markups selector for input points
        distanceLayout = qt.QVBoxLayout()

        self.targetFiducialsSelector = slicer.qMRMLNodeComboBox()
        self.targetFiducialsSelector.nodeTypes = ((
            "vtkMRMLMarkupsFiducialNode"), "")
        self.targetFiducialsSelector.selectNodeUponCreation = True
        self.targetFiducialsSelector.addEnabled = True
        self.targetFiducialsSelector.removeEnabled = True
        self.targetFiducialsSelector.noneEnabled = True
        self.targetFiducialsSelector.showHidden = False
        self.targetFiducialsSelector.showChildNodeTypes = False
        self.targetFiducialsSelector.setMRMLScene(slicer.mrmlScene)
        self.targetFiducialsSelector.setToolTip("Select Markups for targets")
        distanceLayout.addWidget(self.targetFiducialsSelector)

        self.targetFiducialsNode = None
        self.tagDestinationDispNode = None

        self.targetFiducialsSelector.connect(
            "currentNodeChanged(vtkMRMLNode*)", self.onTargetFiducialsSelected)

        self.fiducialsTable = qt.QTableWidget(1, 3)
        self.fiducialsTable.setSelectionBehavior(
            qt.QAbstractItemView.SelectRows)
        self.fiducialsTable.setSelectionMode(
            qt.QAbstractItemView.SingleSelection)
        self.fiducialsTableHeaders = ["Name", "Position (mm)", "Distance (mm)"]
        self.fiducialsTable.setHorizontalHeaderLabels(
            self.fiducialsTableHeaders)
        self.fiducialsTable.horizontalHeader().setStretchLastSection(True)
        distanceLayout.addWidget(self.fiducialsTable)

        self.extrapolateCheckBox = qt.QCheckBox()
        self.extrapolateCheckBox.checked = 0
        self.extrapolateCheckBox.setToolTip(
            "Extrapolate the first and last segment to calculate the distance")
        self.extrapolateCheckBox.connect('toggled(bool)',
                                         self.updateTargetFiducialsTable)
        self.extrapolateCheckBox.text = 'Extrapolate curves to measure the distances'

        self.showErrorVectorCheckBox = qt.QCheckBox()
        self.showErrorVectorCheckBox.checked = 0
        self.showErrorVectorCheckBox.setToolTip(
            "Show error vectors, which is defined by the target point and the closest point on the curve. The vector is perpendicular to the curve, unless the closest point is one end of the curve."
        )
        self.showErrorVectorCheckBox.connect('toggled(bool)',
                                             self.updateTargetFiducialsTable)
        self.showErrorVectorCheckBox.text = 'Show error vectors'

        distanceLayout.addWidget(self.extrapolateCheckBox)
        distanceLayout.addWidget(self.showErrorVectorCheckBox)
        distanceFormLayout.addRow("Distance from:", distanceLayout)

        #
        # Curvature Area
        #
        curvatureCollapsibleButton = ctk.ctkCollapsibleButton()
        curvatureCollapsibleButton.text = "Curvature"
        curvatureCollapsibleButton.collapsed = True
        self.layout.addWidget(curvatureCollapsibleButton)
        curvatureFormLayout = qt.QFormLayout(curvatureCollapsibleButton)

        #-- Curvature
        self.curvatureLayout = qt.QHBoxLayout()
        self.curvatureOff = qt.QRadioButton("Off")
        self.curvatureOff.connect('clicked(bool)', self.onCurvatureOff)
        self.curvatureOn = qt.QRadioButton("On")
        self.curvatureOn.connect('clicked(bool)', self.onCurvatureOn)
        self.curvatureLayout.addWidget(self.curvatureOff)
        self.curvatureLayout.addWidget(self.curvatureOn)
        self.curvatureGroup = qt.QButtonGroup()
        self.curvatureGroup.addButton(self.curvatureOff)
        self.curvatureGroup.addButton(self.curvatureOn)

        curvatureFormLayout.addRow("Curvature mode:", self.curvatureLayout)

        autoCurvatureRangeFormLayout = qt.QFormLayout(
            curvatureCollapsibleButton)
        self.autoCurvatureRangeLayout = qt.QHBoxLayout()
        self.autoCurvatureRangeOff = qt.QRadioButton("Manual")
        self.autoCurvatureRangeOff.connect('clicked(bool)',
                                           self.onAutoCurvatureRangeOff)
        self.autoCurvatureRangeOn = qt.QRadioButton("Auto")
        self.autoCurvatureRangeOn.connect('clicked(bool)',
                                          self.onAutoCurvatureRangeOn)
        self.autoCurvatureRangeLayout.addWidget(self.autoCurvatureRangeOff)
        self.autoCurvatureRangeLayout.addWidget(self.autoCurvatureRangeOn)
        self.autoCurvatureRangeGroup = qt.QButtonGroup()
        self.autoCurvatureRangeGroup.addButton(self.autoCurvatureRangeOff)
        self.autoCurvatureRangeGroup.addButton(self.autoCurvatureRangeOn)

        curvatureFormLayout.addRow("Color range:",
                                   self.autoCurvatureRangeLayout)

        #-- Color range
        self.curvatureColorRangeWidget = ctk.ctkRangeWidget()
        self.curvatureColorRangeWidget.setToolTip("Set color range")
        self.curvatureColorRangeWidget.setDecimals(3)
        self.curvatureColorRangeWidget.singleStep = 0.001
        self.curvatureColorRangeWidget.minimumValue = 0.0
        self.curvatureColorRangeWidget.maximumValue = 0.5
        self.curvatureColorRangeWidget.minimum = 0.0
        self.curvatureColorRangeWidget.maximum = 1.0
        curvatureFormLayout.addRow("Color range: ",
                                   self.curvatureColorRangeWidget)
        self.curvatureColorRangeWidget.connect(
            'valuesChanged(double, double)', self.onUpdateCurvatureColorRange)

        #-- Curvature data
        self.meanCurvatureLineEdit = qt.QLineEdit()
        self.meanCurvatureLineEdit.text = '--'
        self.meanCurvatureLineEdit.readOnly = True
        self.meanCurvatureLineEdit.frame = True
        self.meanCurvatureLineEdit.styleSheet = "QLineEdit { background:transparent; }"
        self.meanCurvatureLineEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)
        self.meanCurvatureLineEdit.enabled = False
        curvatureFormLayout.addRow("Mean (mm^-1):", self.meanCurvatureLineEdit)

        self.minCurvatureLineEdit = qt.QLineEdit()
        self.minCurvatureLineEdit.text = '--'
        self.minCurvatureLineEdit.readOnly = True
        self.minCurvatureLineEdit.frame = True
        self.minCurvatureLineEdit.styleSheet = "QLineEdit { background:transparent; }"
        self.minCurvatureLineEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)
        self.minCurvatureLineEdit.enabled = False
        curvatureFormLayout.addRow("Minimum (mm^-1):",
                                   self.minCurvatureLineEdit)

        self.maxCurvatureLineEdit = qt.QLineEdit()
        self.maxCurvatureLineEdit.text = '--'
        self.maxCurvatureLineEdit.readOnly = True
        self.maxCurvatureLineEdit.frame = True
        self.maxCurvatureLineEdit.styleSheet = "QLineEdit { background:transparent; }"
        self.maxCurvatureLineEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)
        self.maxCurvatureLineEdit.enabled = False
        curvatureFormLayout.addRow("Maximum (mm^-1):",
                                   self.maxCurvatureLineEdit)

        ## Create a scale for curvature
        self.scalarBarWidget = vtk.vtkScalarBarWidget()
        actor = self.scalarBarWidget.GetScalarBarActor()
        actor.SetOrientationToVertical()
        actor.SetNumberOfLabels(11)
        actor.SetTitle("Curvature (mm^-1)")
        actor.SetLabelFormat(" %#8.3f")
        actor.SetPosition(0.1, 0.1)
        actor.SetWidth(0.1)
        actor.SetHeight(0.8)
        self.scalarBarWidget.SetEnabled(0)

        layout = slicer.app.layoutManager()
        view = layout.threeDWidget(0).threeDView()
        renderer = layout.activeThreeDRenderer()
        self.scalarBarWidget.SetInteractor(
            renderer.GetRenderWindow().GetInteractor())
        self.lookupTable = vtk.vtkLookupTable()
        self.lookupTable.SetRange(0.0, 100.0)
        self.scalarBarWidget.GetScalarBarActor().SetLookupTable(
            self.lookupTable)

        ## default curvature mode: off
        self.curvatureOff.setChecked(True)
        self.onCurvatureOff(True)
        self.autoCurvatureRangeOff.setChecked(True)
        self.onAutoCurvatureRangeOff(True)

        # Add vertical spacer
        self.layout.addStretch(1)
コード例 #14
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)
        # Instantiate and connect widgets ...

        #--------------------------------------------------
        # For debugging
        #
        # Reload and Test area
        reloadCollapsibleButton = ctk.ctkCollapsibleButton()
        reloadCollapsibleButton.text = "Reload && Test"
        self.layout.addWidget(reloadCollapsibleButton)
        reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton)

        reloadCollapsibleButton.collapsed = True

        # reload button
        # (use this during development, but remove it when delivering
        #  your module to users)
        self.reloadButton = qt.QPushButton("Reload")
        self.reloadButton.toolTip = "Reload this module."
        self.reloadButton.name = "NeedleGuideTemlpate Reload"
        reloadFormLayout.addWidget(self.reloadButton)
        self.reloadButton.connect('clicked()', self.onReload)
        #
        #--------------------------------------------------

        #
        # Fiducial Node
        #
        fiducialsCollapsibleButton = ctk.ctkCollapsibleButton()
        fiducialsCollapsibleButton.text = "Fiducials"
        self.layout.addWidget(fiducialsCollapsibleButton)

        # Layout within the dummy collapsible button
        fiducialsFormLayout = qt.QFormLayout(fiducialsCollapsibleButton)

        #
        # Fiducial node selector
        #
        self.fiducialSelector = slicer.qMRMLNodeComboBox()
        self.fiducialSelector.nodeTypes = (("vtkMRMLMarkupsFiducialNode"), "")
        self.fiducialSelector.selectNodeUponCreation = True
        self.fiducialSelector.addEnabled = True
        self.fiducialSelector.removeEnabled = True
        self.fiducialSelector.noneEnabled = False
        self.fiducialSelector.renameEnabled = True
        self.fiducialSelector.showHidden = False
        self.fiducialSelector.showChildNodeTypes = False
        self.fiducialSelector.setMRMLScene(slicer.mrmlScene)
        self.fiducialSelector.setToolTip("Pick the input to the algorithm.")
        fiducialsFormLayout.addRow("Input Volume: ", self.fiducialSelector)

        #
        # Reconfigure Button
        #
        self.radiusEdit = qt.QDoubleSpinBox()
        self.radiusEdit.setMinimum(0.0)
        self.radiusEdit.setMaximum(500.0)
        self.radiusEdit.setSingleStep(0.5)
        self.radiusEdit.setValue(50)

        self.numFiducialsEdit = qt.QSpinBox()
        self.numFiducialsEdit.setMinimum(0)
        self.numFiducialsEdit.setMaximum(100)
        self.numFiducialsEdit.setSingleStep(1)
        self.numFiducialsEdit.setValue(5)

        fiducialsFormLayout.addRow("Radius (mm):", self.radiusEdit)
        fiducialsFormLayout.addRow("# of fiducials:", self.numFiducialsEdit)

        self.reconfigureButton = qt.QPushButton("Reconfigure Fiducials")
        self.reconfigureButton.toolTip = "Reconfigure fiducial frame"
        self.reconfigureButton.enabled = False
        fiducialsFormLayout.addRow(self.reconfigureButton)

        #
        # Test Area
        #
        testCollapsibleButton = ctk.ctkCollapsibleButton()
        testCollapsibleButton.text = "Test"
        self.layout.addWidget(testCollapsibleButton)

        # Layout within the dummy collapsible button
        parametersFormLayout = qt.QFormLayout(testCollapsibleButton)

        #
        # input volume selector
        #
        self.inputSelector = slicer.qMRMLNodeComboBox()
        self.inputSelector.nodeTypes = (("vtkMRMLMarkupsFiducialNode"), "")
        self.inputSelector.selectNodeUponCreation = True
        self.inputSelector.addEnabled = False
        self.inputSelector.removeEnabled = False
        self.inputSelector.noneEnabled = False
        self.inputSelector.showHidden = False
        self.inputSelector.showChildNodeTypes = False
        self.inputSelector.setMRMLScene(slicer.mrmlScene)
        self.inputSelector.setToolTip("Pick the input to the algorithm.")
        parametersFormLayout.addRow("Input Fiducial: ", self.inputSelector)

        #
        # reference volume selector
        #
        self.referenceSelector = slicer.qMRMLNodeComboBox()
        self.referenceSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "")
        self.referenceSelector.selectNodeUponCreation = False
        self.referenceSelector.addEnabled = True
        self.referenceSelector.removeEnabled = True
        self.referenceSelector.noneEnabled = False
        self.referenceSelector.showHidden = False
        self.referenceSelector.showChildNodeTypes = False
        self.referenceSelector.setMRMLScene(slicer.mrmlScene)
        self.referenceSelector.setToolTip(
            "Pick the reference to the algorithm.")
        parametersFormLayout.addRow("Reference Volume: ",
                                    self.referenceSelector)

        logFileLayout = qt.QHBoxLayout()
        self.logFileLineEdit = qt.QLineEdit()
        self.logFileLineEdit.text = ''
        self.logFileLineEdit.readOnly = True
        self.logFileLineEdit.frame = True
        self.logFileLineEdit.styleSheet = "QLineEdit { background:transparent; }"
        self.logFileLineEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)
        logFileLayout.addWidget(self.logFileLineEdit)

        self.logFileButton = qt.QPushButton("Choose File...")
        self.logFileButton.toolTip = "Choose log file from dialog box"
        logFileLayout.addWidget(self.logFileButton)

        parametersFormLayout.addRow("Log file:", logFileLayout)

        #
        # Apply Button
        #
        self.applyButton = qt.QPushButton("Apply")
        self.applyButton.toolTip = "Run the algorithm."
        self.applyButton.enabled = False
        parametersFormLayout.addRow(self.applyButton)

        # connections
        self.fiducialSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                      self.onFiducialSelect)
        self.reconfigureButton.connect('clicked(bool)',
                                       self.onReconfigureButton)
        self.logFileButton.connect('clicked(bool)', self.onLogFileButton)
        self.applyButton.connect('clicked(bool)', self.onApplyButton)
        self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                   self.onSelect)
        self.referenceSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                       self.onSelect)

        # Add vertical spacer
        self.layout.addStretch(1)

        # Create logic
        self.logic = FiducialRegistrationTestLogic(None)

        # Enable buttons, if nodes are selected
        self.onSelect()
        self.onFiducialSelect()
コード例 #15
0
	#
    # Curve Length area
    #
    lengthCollapsibleButton = ctk.ctkCollapsibleButton()
    lengthCollapsibleButton.text = "Length"
    self.layout.addWidget(lengthCollapsibleButton)
    lengthFormLayout = qt.QFormLayout(lengthCollapsibleButton)
    lengthCollapsibleButton.collapsed = True

    #-- Curve length
    self.lengthLineEdit = qt.QLineEdit()
    self.lengthLineEdit.text = '--'
    self.lengthLineEdit.readOnly = True
    self.lengthLineEdit.frame = True
    self.lengthLineEdit.styleSheet = "QLineEdit { background:transparent; }"
self.lengthLineEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)

  def cleanup(self):
    pass

  def onSelect(self):
    self.applyButton.enabled = self.inputSelector.currentNode() and self.outputSelector.currentNode()

  def onApplyButton(self):
    logic = GeodesicPathSlicerLogic()

    inputVolume = self.inputSelector.currentNode()
    
    if not (inputVolume and fiducial):
      qt.QMessageBox.critical(slicer.util.mainWindow(), 'GeodesicPath', 'Input and two ficuial points are required for GeodesicPath')
      return
コード例 #16
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)
        # Instantiate and connect widgets ...

        self.logic = NeedleGuideTemplateLogic(None)

        #--------------------------------------------------
        # For debugging
        #
        # Reload and Test area
        reloadCollapsibleButton = ctk.ctkCollapsibleButton()
        reloadCollapsibleButton.text = "Reload && Test"
        self.layout.addWidget(reloadCollapsibleButton)
        reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton)

        reloadCollapsibleButton.collapsed = True

        # reload button
        # (use this during development, but remove it when delivering
        #  your module to users)
        self.reloadButton = qt.QPushButton("Reload")
        self.reloadButton.toolTip = "Reload this module."
        self.reloadButton.name = "NeedleGuideTemlpate Reload"
        reloadFormLayout.addWidget(self.reloadButton)
        self.reloadButton.connect('clicked()', self.onReload)
        #
        #--------------------------------------------------

        #--------------------------------------------------
        #
        # Configuration
        #
        configCollapsibleButton = ctk.ctkCollapsibleButton()
        configCollapsibleButton.text = "Configuration"
        self.layout.addWidget(configCollapsibleButton)

        configFormLayout = qt.QFormLayout(configCollapsibleButton)

        configCollapsibleButton.collapsed = True

        templateConfigPathLayout = qt.QHBoxLayout()

        self.templateConfigPathEdit = qt.QLineEdit()
        self.templateConfigPathEdit.text = ""
        self.templateConfigPathEdit.readOnly = False
        self.templateConfigPathEdit.frame = True
        self.templateConfigPathEdit.styleSheet = "QLineEdit { background:transparent; }"
        self.templateConfigPathEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)
        templateConfigPathLayout.addWidget(self.templateConfigPathEdit)

        self.templateConfigButton = qt.QPushButton("...")
        self.templateConfigButton.toolTip = "Choose a template configuration file"
        self.templateConfigButton.enabled = True
        self.templateConfigButton.connect('clicked(bool)',
                                          self.onTemplateConfigButton)
        templateConfigPathLayout.addWidget(self.templateConfigButton)

        configFormLayout.addRow("Template Config File: ",
                                templateConfigPathLayout)

        fiducialConfigPathLayout = qt.QHBoxLayout()

        self.fiducialConfigPathEdit = qt.QLineEdit()
        self.fiducialConfigPathEdit.text = ""
        self.fiducialConfigPathEdit.readOnly = False
        self.fiducialConfigPathEdit.frame = True
        self.fiducialConfigPathEdit.styleSheet = "QLineEdit { background:transparent; }"
        self.fiducialConfigPathEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)
        fiducialConfigPathLayout.addWidget(self.fiducialConfigPathEdit)

        self.fiducialConfigButton = qt.QPushButton("...")
        self.fiducialConfigButton.toolTip = "Choose a fiducial configuration file"
        self.fiducialConfigButton.enabled = True
        self.fiducialConfigButton.connect('clicked(bool)',
                                          self.onFiducialConfigButton)
        fiducialConfigPathLayout.addWidget(self.fiducialConfigButton)

        configFormLayout.addRow("Fiducial Config File: ",
                                fiducialConfigPathLayout)

        #
        # Main Area
        #
        mainCollapsibleButton = ctk.ctkCollapsibleButton()
        mainCollapsibleButton.text = "Main"

        self.layout.addWidget(mainCollapsibleButton)

        # Layout within the dummy collapsible button
        #mainFormLayout = qt.QFormLayout(mainCollapsibleButton)
        mainLayout = qt.QVBoxLayout(mainCollapsibleButton)

        mainFormFrame = qt.QFrame()
        mainFormLayout = qt.QFormLayout(mainFormFrame)
        mainLayout.addWidget(mainFormFrame)

        self.showTemplateCheckBox = qt.QCheckBox()
        self.showTemplateCheckBox.checked = 0
        self.showTemplateCheckBox.setToolTip("Show 3D model of the template")
        mainFormLayout.addRow("Show Template:", self.showTemplateCheckBox)
        self.showTemplateCheckBox.connect('toggled(bool)', self.onShowTemplate)

        self.showFiducialCheckBox = qt.QCheckBox()
        self.showFiducialCheckBox.checked = 0
        self.showFiducialCheckBox.setToolTip("Show 3D model of the fiducial")
        mainFormLayout.addRow("Show Fiducial:", self.showFiducialCheckBox)
        self.showFiducialCheckBox.connect('toggled(bool)', self.onShowFiducial)

        self.showTrajectoriesCheckBox = qt.QCheckBox()
        self.showTrajectoriesCheckBox.checked = 0
        self.showTrajectoriesCheckBox.setToolTip(
            "Show 3D model of the fiducial")
        mainFormLayout.addRow("Show Trajectories:",
                              self.showTrajectoriesCheckBox)
        self.showTrajectoriesCheckBox.connect('toggled(bool)',
                                              self.onShowTrajectories)

        #
        # input volume selector
        #
        self.targetFiducialsSelector = slicer.qMRMLNodeComboBox()
        self.targetFiducialsSelector.nodeTypes = ((
            "vtkMRMLMarkupsFiducialNode"), "")
        self.targetFiducialsSelector.selectNodeUponCreation = True
        self.targetFiducialsSelector.addEnabled = True
        self.targetFiducialsSelector.removeEnabled = True
        self.targetFiducialsSelector.noneEnabled = False
        self.targetFiducialsSelector.showHidden = False
        self.targetFiducialsSelector.showChildNodeTypes = False
        self.targetFiducialsSelector.setMRMLScene(slicer.mrmlScene)
        self.targetFiducialsSelector.setToolTip("Select Markups for targets")
        mainFormLayout.addRow("Targets: ", self.targetFiducialsSelector)

        self.targetFiducialsNode = None
        self.targetFiducialsSelector.connect(
            "currentNodeChanged(vtkMRMLNode*)", self.onFiducialsSelected)

        #
        # Target List Table
        #
        self.table = qt.QTableWidget(1, 4)
        self.table.setSelectionBehavior(qt.QAbstractItemView.SelectRows)
        self.table.setSelectionMode(qt.QAbstractItemView.SingleSelection)
        #self.table.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)

        self.headers = ["Name", "Hole", "Depth (mm)", "Position (RAS)"]
        self.table.setHorizontalHeaderLabels(self.headers)
        self.table.horizontalHeader().setStretchLastSection(True)

        mainLayout.addWidget(self.table)

        self.table.connect('cellClicked(int, int)', self.onTableSelected)

        self.onFiducialsSelected()

        ##
        ## input volume selector
        ##
        #self.inputSelector = slicer.qMRMLNodeComboBox()
        #self.inputSelector.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
        #self.inputSelector.addAttribute( "vtkMRMLScalarVolumeNode", "LabelMap", 0 )
        #self.inputSelector.selectNodeUponCreation = True
        #self.inputSelector.addEnabled = False
        #self.inputSelector.removeEnabled = False
        #self.inputSelector.noneEnabled = False
        #self.inputSelector.showHidden = False
        #self.inputSelector.showChildNodeTypes = False
        #self.inputSelector.setMRMLScene( slicer.mrmlScene )
        #self.inputSelector.setToolTip( "Pick the input to the algorithm." )
        #mainFormLayout.addRow("Input Volume: ", self.inputSelector)

        ##
        ## scale factor for screen shots
        ##
        #self.screenshotScaleFactorSliderWidget = ctk.ctkSliderWidget()
        #self.screenshotScaleFactorSliderWidget.singleStep = 1.0
        #self.screenshotScaleFactorSliderWidget.minimum = 1.0
        #self.screenshotScaleFactorSliderWidget.maximum = 50.0
        #self.screenshotScaleFactorSliderWidget.value = 1.0
        #self.screenshotScaleFactorSliderWidget.setToolTip("Set scale factor for the screen shots.")
        #mainFormLayout.addRow("Screenshot scale factor", self.screenshotScaleFactorSliderWidget)

        ##
        ## Apply Button
        ##
        #self.applyButton = qt.QPushButton("Apply")
        #self.applyButton.toolTip = "Run the algorithm."
        #self.applyButton.enabled = False
        #mainFormLayout.addRow(self.applyButton)

        # connections
        #self.applyButton.connect('clicked(bool)', self.onApplyButton)
        #self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)

        #--------------------------------------------------
        #
        # Projection
        #
        projectionCollapsibleButton = ctk.ctkCollapsibleButton()
        projectionCollapsibleButton.text = "Projection"

        self.layout.addWidget(projectionCollapsibleButton)
        projectionLayout = qt.QVBoxLayout(projectionCollapsibleButton)

        projectionCollapsibleButton.collapsed = False

        self.openWindowButton = qt.QPushButton("OpenWindow")
        self.openWindowButton.toolTip = "Run the algorithm."
        self.openWindowButton.enabled = True
        projectionLayout.addWidget(self.openWindowButton)

        self.openWindowButton.connect('clicked(bool)', self.onOpenWindowButton)

        # Add vertical spacer
        self.layout.addStretch(1)

        self.ex = None
コード例 #17
0
ファイル: EditBox.py プロジェクト: satra/Slicer
class EditBox(object):
    def __init__(self,
                 parent=0,
                 optionsFrame=None,
                 embedded=False,
                 suppliedEffects=[]):
        self.effects = []
        self.effectButtons = {}
        self.effectMapper = qt.QSignalMapper()
        self.effectMapper.connect('mapped(const QString&)', self.selectEffect)
        self.editUtil = EditUtil.EditUtil()

        # check for extensions - if none have been registered, just create the empty dictionary
        try:
            slicer.modules.editorExtensions
        except AttributeError:
            slicer.modules.editorExtensions = {}

        # embedded boolean specifies whether or not this edit box is to be embedded
        # into another moduleWidget
        # - if it is, all effect buttons will be displayed in a single row
        self.embedded = embedded

        # save the list of supplied effects that the caller wants to use
        # (should be a subset of EditBox.availableMouseTools + EditBox.availableOperations)
        self.suppliedEffects = suppliedEffects

        if parent == 0:
            self.parent = qt.QFrame()
            self.parent.setLayout(qt.QVBoxLayout())
            self.create()
            self.parent.show()
        else:
            self.parent = parent
            self.create()

        # frame that holds widgets specific for each effect
        if not optionsFrame:
            self.optionsFrame = qt.QFrame(self.parent)
        else:
            self.optionsFrame = optionsFrame

        # state variables for selected effect in the box
        # - currentOption is an instance of an option GUI
        # - currentTools is a list of EffectTool instances
        self.currentOption = None
        self.currentTools = []

    #
    # Public lists of the available effects provided by the editor
    #

    # effects that change the mouse cursor
    availableMouseTools = (
        "ChangeIsland",
        "ChooseColor",
        "ImplicitCube",
        "ImplicitEllipse",
        "ImplicitRectangle",
        "Draw",
        "RemoveIslands",
        "ConnectedComponents",
        "ThresholdBucket",
        "ThresholdPaintLabel",
        "SaveIsland",
        "SlurpColor",
        "Paint",
        "DefaultTool",
        "LevelTracing",
        "MakeModel",
        "Wand",
        "GrowCutSegment",
    )

    # effects that operate from the menu
    availableOperations = (
        "ErodeLabel",
        "DilateLabel",
        "DeleteFiducials",
        "LabelOpacity",
        "ChangeLabel",
        "FiducialVisibilityOff",
        "FiducialVisibilityOn",
        "GoToEditorModule",
        "IdentifyIslands",
        "LabelVisibilityOff",
        "LabelVisibilityOn",
        "NextFiducial",
        "SnapToGridOff",
        "SnapToGridOn",
        "EraseLabel",
        "Threshold",
        "PinOpen",
        "PreviousFiducial",
        "InterpolateLabels",
        "LabelOpacity",
        "ToggleLabelOutline",
        "Watershed",
        "PreviousCheckPoint",
        "NextCheckPoint",
    )

    # these buttons do not switch you out of the current tool
    availableNonmodal = ("FiducialVisibilityOn", "LabelVisibilityOff",
                         "LabelVisibilityOn", "NextFiducial",
                         "PreviousFiducial", "DeleteFiducials", "SnapToGridOn",
                         "SnapToGridOff", "EraseLabel", "PreviousCheckPoint",
                         "NextCheckPoint", "ToggleLabelOutline",
                         "SnapToGridOff", "SnapToGridOn", "LabelOpacity")

    # these buttons start disabled (check points will re-enable when circumstances are right)
    availableDisabled = (
        "ChooseColor",
        "ImplicitCube",
        "ImplicitEllipse",
        "ConnectedComponents",
        "SlurpColor",
        "ThresholdPaintLabel",
        "ThresholdBucket",
        "DeleteFiducials",
        "LabelOpacity",
        "FiducialVisibilityOff",
        "FiducialVisibilityOn",
        "LabelVisibilityOff",
        "LabelVisibilityOn",
        "SnapToGridOff",
        "SnapToGridOn",
        "InterpolateLabels",
        "LabelOpacity",
        "ToggleLabelOutline",
        "Watershed",
        "Wand",
    )

    # allow overriding the developers name of the tool for a more user-friendly label name
    displayNames = {}
    displayNames["PreviousCheckPoint"] = "Undo"
    displayNames["NextCheckPoint"] = "Redo"

    # calculates the intersection of two flat lists
    @classmethod
    def listIntersection(cls, inList1, inList2):
        outList = [val for val in inList1 if val in inList2]
        return outList

    # fill the _effects array bases on what you find in the interpreter
    # if a list of effects was supplied, then use that list instead of all of the effects
    def findEffects(self, path=""):

        # for now, the built in effects are hard-coded to facilitate
        # the icons and layout

        self.effects = []

        # if a list of effects was supplied, then use that list instead of all of the effects
        # don't forget to check that the supplied effects are valid: ensure they exist in the lists of available effects

        if (self.suppliedEffects):
            self.mouseTools = tuple(
                self.listIntersection(self.suppliedEffects,
                                      EditBox.availableMouseTools))
            self.operations = tuple(
                self.listIntersection(self.suppliedEffects,
                                      EditBox.availableOperations))
            self.nonmodal = tuple(
                self.listIntersection(self.suppliedEffects,
                                      EditBox.availableNonmodal))
            self.disabled = tuple(
                self.listIntersection(self.suppliedEffects,
                                      EditBox.availableDisabled))
        # if a list of effects is not supplied, then provide all effects
        else:
            self.mouseTools = EditBox.availableMouseTools
            self.operations = EditBox.availableOperations
            self.nonmodal = EditBox.availableNonmodal
            self.disabled = EditBox.availableDisabled
        '''
    for key in slicer.modules.editorExtensions.keys():
      e = slicer.modules.editorExtensions[key]()
      if 'MouseTool' in e.attributes:
        self.mouseTools.append(key)
      if 'Nonmodal' in e.attributes:
        self.operations.append(key)
      if 'Disabled' in e.attributes:
        self.disabled.append(key)
    '''

        # combined list of all effects
        self.effects = self.mouseTools + self.operations

        # add any extensions that have been registered
        self.effects = self.effects + tuple(
            slicer.modules.editorExtensions.keys())

        # for each effect
        # - look for implementation class of pattern *Effect
        # - get an icon name for the pushbutton
        iconDir = os.environ['SLICER_HOME'] + '/' + os.environ[
            'SLICER_SHARE_DIR'] + '/Tcl/ImageData/'

        self.effectClasses = {}
        self.effectIconFiles = {}
        self.effectModes = {}
        self.icons = {}
        for effect in self.effects:
            tclclass = tcl('info command %sEffect' % effect)
            if tclclass != '':
                self.effectClasses[effect] = tclclass
            else:
                self.effectClasses[effect] = "EffectSWidget"

            for iconType in ("", "Selected", "Disabled"):
                self.effectIconFiles[
                    effect, iconType] = iconDir + effect + iconType + '.png'
                iconMode = ""
                if self.disabled.__contains__(effect):
                    # - don't use the disabled icon for now - Qt's setEnabled method works fine
                    #iconMode = "Disabled"
                    pass

                self.effectModes[effect] = iconMode

    #
    # create a row of the edit box given a list of
    # effect names (items in _effects(list)
    #
    def createButtonRow(self, effects, rowLabel=""):

        f = qt.QFrame(self.parent)
        self.parent.layout().addWidget(f)
        self.rowFrames.append(f)
        hbox = qt.QHBoxLayout()
        f.setLayout(hbox)

        if rowLabel:
            label = qt.QLabel(rowLabel)
            hbox.addWidget(label)

        for effect in effects:
            # check that the effect belongs in our list of effects before including
            # (handles non-embedded widgets where the caller has supplied a custom list of effects)
            if (effect in self.effects):
                i = self.icons[effect] = qt.QIcon(
                    self.effectIconFiles[effect, self.effectModes[effect]])
                a = self.actions[effect] = qt.QAction(i, '', f)
                self.effectButtons[effect] = b = self.buttons[
                    effect] = qt.QToolButton()
                b.setDefaultAction(a)
                b.setToolTip(effect)
                if EditBox.displayNames.has_key(effect):
                    b.setToolTip(EditBox.displayNames[effect])
                hbox.addWidget(b)
                if self.disabled.__contains__(effect):
                    b.setDisabled(1)

                # Setup the mapping between button and its associated effect name
                self.effectMapper.setMapping(self.buttons[effect], effect)
                # Connect button with signal mapper
                self.buttons[effect].connect('clicked()', self.effectMapper,
                                             'map()')

        hbox.addStretch(1)

    # create the edit box
    def create(self):

        self.findEffects()

        #
        # the buttons
        #
        self.rowFrames = []
        self.actions = {}
        self.buttons = {}
        self.icons = {}
        self.callbacks = {}

        # if not using embedded format: create all of the buttons
        # createButtonRow() ensures that only effects in self.effects are exposed,
        # so if the user supplied a list of effects only those in that list will be exposed
        if (not self.embedded):
            self.createButtonRow(
                ("DefaultTool", "EraseLabel", "Paint", "Draw", "LevelTracing",
                 "ImplicitRectangle", "IdentifyIslands", "ChangeIsland",
                 "RemoveIslands", "SaveIsland"))
            self.createButtonRow(
                ("ErodeLabel", "DilateLabel", "Threshold", "ChangeLabel",
                 "MakeModel", "GrowCutSegment"))
            extensions = []
            for k in slicer.modules.editorExtensions:
                extensions.append(k)
            self.createButtonRow(extensions)
            # TODO: add back prev/next fiducial
            #self.createButtonRow( ("PreviousFiducial", "NextFiducial") )
            self.createButtonRow(("PreviousCheckPoint", "NextCheckPoint"),
                                 rowLabel="Undo/Redo: ")
        # if using embedded format: create all of the buttons in the effects list in a single row
        else:
            self.createButtonRow(self.effects)

        #
        # the labels (not shown in embedded format)
        #
        self.toolsActiveToolFrame = qt.QFrame(self.parent)
        self.toolsActiveToolFrame.setLayout(qt.QHBoxLayout())
        self.parent.layout().addWidget(self.toolsActiveToolFrame)
        self.toolsActiveTool = qt.QLabel(self.toolsActiveToolFrame)
        self.toolsActiveTool.setText('Active Tool:')
        self.toolsActiveTool.setStyleSheet(
            "background-color: rgb(232,230,235)")
        self.toolsActiveToolFrame.layout().addWidget(self.toolsActiveTool)
        self.toolsActiveToolName = qt.QLabel(self.toolsActiveToolFrame)
        self.toolsActiveToolName.setText('')
        self.toolsActiveToolName.setStyleSheet(
            "background-color: rgb(232,230,235)")
        self.toolsActiveToolFrame.layout().addWidget(self.toolsActiveToolName)

        self.updateCheckPointButtons()

    def setActiveToolLabel(self, name):
        if EditBox.displayNames.has_key(name):
            name = EditBox.displayNames[name]
        self.toolsActiveToolName.setText(name)


# needs to be a valid effect name and state of "", Disabled, or Selected

    TODO = """
itcl::body EditBox::setButtonState {effect state} {
  $::slicer3::ApplicationGUI SetIconImage \
      $_effects($effect,icon) $_effects($effect,imageData$state)
  $o($effect,button) SetImageToIcon $_effects($effect,icon)
  switch $state {
    Selected -
    "" {
      $o($effect,button) SetState 1
    }
    "Disabled" {
      $o($effect,button) SetState 0
    }
  }
}
"""

    #
    # Pause running the current effect, reverting to the default tool
    #
    def pauseEffect(self):
        self.selectEffect("DefaultTool")

    #
    # Resume running the effect that was being used before a pause (TODO)
    #
    def resumeEffect(self):
        pass

    #
    # manage the editor effects
    #
    def selectEffect(self, effect):
        from slicer import app

        #
        # if a modal effect was selected, 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 not self.nonmodal.__contains__(effect):
            if self.currentOption:
                self.currentOption.__del__()
                self.currentOption = None
                for tool in self.currentTools:
                    tool.cleanup()
                self.currentTools = []
            if effect in slicer.modules.editorExtensions.keys():
                extensionEffect = slicer.modules.editorExtensions[effect]()
                self.currentOption = extensionEffect.options(self.optionsFrame)
                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 = extensionEffect.tool(sliceWidget)
                        self.currentTools.append(tool)
            else:
                try:
                    options = eval("%sOptions" % effect)
                    self.currentOption = options(self.optionsFrame)
                except NameError, AttributeError:
                    # No options for this effect, skip it
                    pass

        #
        # If there is no background volume or label map, do nothing
        #
        # TODO should do this regardless of whether or not there is an option
        if not self.editUtil.getBackgroundVolume():
            return
        if not self.editUtil.getLabelVolume():
            return

        app.restoreOverrideCursor()
        self.setActiveToolLabel(effect)
        if not self.nonmodal.__contains__(effect):
            tcl('EffectSWidget::RemoveAll')
            tcl('EditorSetActiveToolLabel %s' % effect)

        # mouse tool changes cursor, and dismisses popup/menu
        mouseTool = False
        if self.mouseTools.__contains__(effect):
            mouseTool = True

        if effect == "DefaultTool":
            # do nothing - this will reset cursor mode
            tcl('EditorSetActiveToolLabel DefaultTool')
        elif effect == "GoToEditorModule":
            tcl('EditorSelectModule')
            tcl('EditorSetActiveToolLabel DefaultTool')
        elif effect == "LabelCheckPoint":
            # save a copy of the current label layer into the scene
            tcl('EditorLabelCheckPoint')
            tcl('EditorSetActiveToolLabel DefaultTool')
        elif effect == "PreviousFiducial":
            tcl('::FiducialsSWidget::JumpAllToNextFiducial -1')
            tcl('EditorSetActiveToolLabel DefaultTool')
        elif effect == "NextFiducial":
            tcl('::FiducialsSWidget::JumpAllToNextFiducial 1')
            tcl('EditorSetActiveToolLabel DefaultTool')
        elif effect == "EraseLabel":
            tcl('EditorToggleErasePaintLabel')
        elif effect == "PreviousCheckPoint":
            tcl('EditorPerformPreviousCheckPoint')
        elif effect == "NextCheckPoint":
            tcl('EditorPerformNextCheckPoint')
        else:
            if effect == "GrowCutSegment":
                self.editorGestureCheckPoint()
                #volumesLogic = slicer.modules.volumes.logic()
                #print ("VolumesLogic is %s " % volumesLogic)
                #tcl('EditorGestureCheckPoint $%s' % volumesLogic)
            if mouseTool:
                # TODO: make some nice custom cursor shapes
                # - for now use the built in override cursor
                #pix = qt.QPixmap()
                #pix.load(self.effectIconFiles[effect,""])
                #cursor = qt.QCursor(pix)
                #app.setOverrideCursor(cursor, 0, 0)
                cursor = qt.QCursor(1)
                app.setOverrideCursor(cursor)
            else:
                app.restoreOverrideCursor()

            #
            # create an instance of the effect for each of the active sliceGUIs
            # - have the effect reset the tool label when completed
            #

            ret = tcl('catch "EffectSWidget::Add %s" res' %
                      self.effectClasses[effect])
            if ret != '0':
                dialog = qt.QErrorMessage(self.parent)
                dialog.showMessage(
                    "Could not select effect.\n\nError was:\n%s" %
                    tcl('set res'))
            else:
                tcl('EffectSWidget::ConfigureAll %s -exitCommand "EditorSetActiveToolLabel DefaultTool"'
                    % self.effectClasses[effect])
コード例 #18
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)
        # Instantiate and connect widgets ...

        #--------------------------------------------------
        # For debugging
        #
        # Reload and Test area
        reloadCollapsibleButton = ctk.ctkCollapsibleButton()
        reloadCollapsibleButton.text = "Reload && Test"
        self.layout.addWidget(reloadCollapsibleButton)
        reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton)

        reloadCollapsibleButton.collapsed = True

        # reload button
        # (use this during development, but remove it when delivering
        #  your module to users)
        self.reloadButton = qt.QPushButton("Reload")
        self.reloadButton.toolTip = "Reload this module."
        self.reloadButton.name = "NeedleGuideTemlpate Reload"
        reloadFormLayout.addWidget(self.reloadButton)
        self.reloadButton.connect('clicked()', self.onReload)
        #
        #--------------------------------------------------

        #
        # Fiducial Node
        #
        fiducialsCollapsibleButton = ctk.ctkCollapsibleButton()
        fiducialsCollapsibleButton.text = "Fiducials"
        self.layout.addWidget(fiducialsCollapsibleButton)

        # Layout within the dummy collapsible button
        fiducialsFormLayout = qt.QFormLayout(fiducialsCollapsibleButton)

        #
        # Fiducial node selector
        #
        self.fiducial1Selector = slicer.qMRMLNodeComboBox()
        self.fiducial1Selector.nodeTypes = (("vtkMRMLMarkupsFiducialNode"), "")
        self.fiducial1Selector.selectNodeUponCreation = True
        self.fiducial1Selector.addEnabled = True
        self.fiducial1Selector.removeEnabled = True
        self.fiducial1Selector.noneEnabled = True
        self.fiducial1Selector.renameEnabled = True
        self.fiducial1Selector.showHidden = False
        self.fiducial1Selector.showChildNodeTypes = False
        self.fiducial1Selector.setMRMLScene(slicer.mrmlScene)
        self.fiducial1Selector.setToolTip("Pick the input to the algorithm.")
        fiducialsFormLayout.addRow("Fiducial 1: ", self.fiducial1Selector)

        self.fiducial2Selector = slicer.qMRMLNodeComboBox()
        self.fiducial2Selector.nodeTypes = (("vtkMRMLMarkupsFiducialNode"), "")
        self.fiducial2Selector.selectNodeUponCreation = True
        self.fiducial2Selector.addEnabled = True
        self.fiducial2Selector.removeEnabled = True
        self.fiducial2Selector.noneEnabled = True
        self.fiducial2Selector.renameEnabled = True
        self.fiducial2Selector.showHidden = False
        self.fiducial2Selector.showChildNodeTypes = False
        self.fiducial2Selector.setMRMLScene(slicer.mrmlScene)
        self.fiducial2Selector.setToolTip("Pick the input to the algorithm.")
        fiducialsFormLayout.addRow("Fiducial 2: ", self.fiducial2Selector)

        #
        # Apply Button
        #
        self.applyButton = qt.QPushButton("Apply")
        self.applyButton.toolTip = "Run the algorithm."
        self.applyButton.enabled = False
        fiducialsFormLayout.addRow(self.applyButton)

        #
        # Result
        #
        self.TREEdit = qt.QLineEdit()
        self.TREEdit.text = '--'
        self.TREEdit.readOnly = True
        self.TREEdit.frame = True
        self.TREEdit.styleSheet = "QLineEdit { background:transparent; }"
        self.TREEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)

        fiducialsFormLayout.addRow("TRE (mm):", self.TREEdit)

        self.errorRAEdit = qt.QLineEdit()
        self.errorRAEdit.text = '--'
        self.errorRAEdit.readOnly = True
        self.errorRAEdit.frame = True
        self.errorRAEdit.styleSheet = "QLineEdit { background:transparent; }"
        self.errorRAEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)

        fiducialsFormLayout.addRow("Error RA (mm):", self.errorRAEdit)

        self.errorAPEdit = qt.QLineEdit()
        self.errorAPEdit.text = '--'
        self.errorAPEdit.readOnly = True
        self.errorAPEdit.frame = True
        self.errorAPEdit.styleSheet = "QLineEdit { background:transparent; }"
        self.errorAPEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)

        fiducialsFormLayout.addRow("Error AP (mm):", self.errorAPEdit)

        self.errorSIEdit = qt.QLineEdit()
        self.errorSIEdit.text = '--'
        self.errorSIEdit.readOnly = True
        self.errorSIEdit.frame = True
        self.errorSIEdit.styleSheet = "QLineEdit { background:transparent; }"
        self.errorSIEdit.cursor = qt.QCursor(qt.Qt.IBeamCursor)

        fiducialsFormLayout.addRow("Error SI (mm):", self.errorSIEdit)

        # connections
        self.fiducial1Selector.connect("currentNodeChanged(vtkMRMLNode*)",
                                       self.onFiducialSelect)
        self.fiducial2Selector.connect("currentNodeChanged(vtkMRMLNode*)",
                                       self.onFiducialSelect)
        self.applyButton.connect('clicked(bool)', self.onApplyButton)

        # Add vertical spacer
        self.layout.addStretch(1)

        # Create logic
        self.logic = TargetRegistrationErrorLogic(None)

        # Enable buttons, if nodes are selected
        self.onFiducialSelect()
コード例 #19
0
class EditBox(object):
    def __init__(self, parent=None, optionsFrame=None):
        self.effects = []
        self.effectButtons = {}
        self.effectMapper = qt.QSignalMapper()
        self.effectMapper.connect('mapped(const QString&)', self.selectEffect)
        self.editUtil = EditUtil.EditUtil()
        self.undoRedo = EditUtil.UndoRedo()
        self.undoRedo.stateChangedCallback = self.updateUndoRedoButtons

        # check for extensions - if none have been registered, just create the empty dictionary
        try:
            slicer.modules.editorExtensions
        except AttributeError:
            slicer.modules.editorExtensions = {}

        # register the builtin extensions
        self.editorBuiltins = {}
        self.editorBuiltins["PaintEffect"] = EditorLib.PaintEffect
        self.editorBuiltins["DrawEffect"] = EditorLib.DrawEffect
        self.editorBuiltins["ThresholdEffect"] = EditorLib.ThresholdEffect
        self.editorBuiltins["RectangleEffect"] = EditorLib.RectangleEffect
        self.editorBuiltins[
            "LevelTracingEffect"] = EditorLib.LevelTracingEffect
        self.editorBuiltins["MakeModelEffect"] = EditorLib.MakeModelEffect
        self.editorBuiltins["ErodeEffect"] = EditorLib.ErodeEffect
        self.editorBuiltins["DilateEffect"] = EditorLib.DilateEffect
        self.editorBuiltins["ChangeLabelEffect"] = EditorLib.ChangeLabelEffect
        self.editorBuiltins[
            "RemoveIslandsEffect"] = EditorLib.RemoveIslandsEffect
        self.editorBuiltins[
            "IdentifyIslandsEffect"] = EditorLib.IdentifyIslandsEffect
        self.editorBuiltins["SaveIslandEffect"] = EditorLib.SaveIslandEffect
        self.editorBuiltins[
            "ChangeIslandEffect"] = EditorLib.ChangeIslandEffect
        self.editorBuiltins["GrowCutEffect"] = EditorLib.GrowCutEffect

        if not parent:
            self.parent = qt.QFrame()
            self.parent.setLayout(qt.QVBoxLayout())
            self.create()
            self.parent.show()
        else:
            self.parent = parent
            self.create()

        # frame that holds widgets specific for each effect
        if not optionsFrame:
            self.optionsFrame = qt.QFrame(self.parent)
        else:
            self.optionsFrame = optionsFrame

        # state variables for selected effect in the box
        # - currentOption is an instance of an option GUI
        # - currentTools is a list of EffectTool instances
        self.currentOption = None
        self.currentTools = []

    #
    # Public lists of the available effects provided by the editor
    #

    # effects that change the mouse cursor
    availableMouseTools = (
        "ChangeIsland",
        "ChooseColor",
        "ImplicitCube",
        "ImplicitEllipse",
        "ImplicitRectangle",
        "Draw",
        "RemoveIslands",
        "ConnectedComponents",
        "ThresholdBucket",
        "ThresholdPaintLabel",
        "SaveIsland",
        "SlurpColor",
        "Paint",
        "DefaultTool",
        "LevelTracing",
        "MakeModel",
        "Wand",
        "GrowCutSegment",
    )

    # effects that operate from the menu
    availableOperations = (
        "ErodeLabel",
        "DilateLabel",
        "DeleteFiducials",
        "LabelOpacity",
        "ChangeLabel",
        "FiducialVisibilityOff",
        "FiducialVisibilityOn",
        "GoToEditorModule",
        "IdentifyIslands",
        "LabelVisibilityOff",
        "LabelVisibilityOn",
        "NextFiducial",
        "SnapToGridOff",
        "SnapToGridOn",
        "EraseLabel",
        "Threshold",
        "PinOpen",
        "PreviousFiducial",
        "InterpolateLabels",
        "LabelOpacity",
        "ToggleLabelOutline",
        "Watershed",
        "PreviousCheckPoint",
        "NextCheckPoint",
    )

    # these buttons do not switch you out of the current tool
    availableNonmodal = ("FiducialVisibilityOn", "LabelVisibilityOff",
                         "LabelVisibilityOn", "NextFiducial",
                         "PreviousFiducial", "DeleteFiducials", "SnapToGridOn",
                         "SnapToGridOff", "EraseLabel", "PreviousCheckPoint",
                         "NextCheckPoint", "ToggleLabelOutline",
                         "SnapToGridOff", "SnapToGridOn", "LabelOpacity")

    # these buttons start disabled (check points will re-enable when circumstances are right)
    availableDisabled = (
        "ChooseColor",
        "ImplicitCube",
        "ImplicitEllipse",
        "ConnectedComponents",
        "SlurpColor",
        "ThresholdPaintLabel",
        "ThresholdBucket",
        "DeleteFiducials",
        "LabelOpacity",
        "FiducialVisibilityOff",
        "FiducialVisibilityOn",
        "LabelVisibilityOff",
        "LabelVisibilityOn",
        "SnapToGridOff",
        "SnapToGridOn",
        "InterpolateLabels",
        "LabelOpacity",
        "ToggleLabelOutline",
        "Watershed",
        "Wand",
    )

    # allow overriding the developers name of the tool for a more user-friendly label name
    displayNames = {}
    displayNames["PreviousCheckPoint"] = "Undo"
    displayNames["NextCheckPoint"] = "Redo"

    # calculates the intersection of two flat lists
    @classmethod
    def listIntersection(cls, inList1, inList2):
        outList = [val for val in inList1 if val in inList2]
        return outList

    # fill the _effects array bases on what you find in the interpreter
    def findEffects(self, path=""):

        # for now, the built in effects are hard-coded to facilitate
        # the icons and layout

        self.effects = []

        self.mouseTools = EditBox.availableMouseTools
        self.operations = EditBox.availableOperations
        self.nonmodal = EditBox.availableNonmodal
        self.disabled = EditBox.availableDisabled

        # combined list of all effects
        self.effects = self.mouseTools + self.operations

        # add builtins that have been registered
        self.effects = self.effects + tuple(self.editorBuiltins.keys())

        # add any extensions that have been registered
        self.effects = self.effects + tuple(
            slicer.modules.editorExtensions.keys())

        # for each effect
        # - look for implementation class of pattern *Effect
        # - get an icon name for the pushbutton
        iconDir = os.environ['SLICER_HOME'] + '/' + os.environ[
            'SLICER_SHARE_DIR'] + '/Tcl/ImageData/'

        self.effectIconFiles = {}
        self.effectModes = {}
        self.icons = {}
        for effect in self.effects:
            for iconType in ("", "Selected", "Disabled"):
                self.effectIconFiles[
                    effect, iconType] = iconDir + effect + iconType + '.png'
                iconMode = ""
                if self.disabled.__contains__(effect):
                    # - don't use the disabled icon for now - Qt's setEnabled method works fine
                    #iconMode = "Disabled"
                    pass

                self.effectModes[effect] = iconMode

        if effect in slicer.modules.editorExtensions.keys():
            extensionEffect = slicer.modules.editorExtensions[effect]()
            module = eval('slicer.modules.%s' % effect.lower())
            iconPath = os.path.join(os.path.dirname(module.path),
                                    "%s.png" % effect)
            self.effectIconFiles[effect, ""] = iconPath
            self.effectModes[effect] = ""

        # TOOD: add icons for builtins as resource or installed image directory
        self.effectIconFiles["PaintEffect", ""] = self.effectIconFiles["Paint",
                                                                       ""]
        self.effectIconFiles["DrawEffect", ""] = self.effectIconFiles["Draw",
                                                                      ""]
        self.effectIconFiles["ThresholdEffect",
                             ""] = self.effectIconFiles["Threshold", ""]
        self.effectIconFiles["RectangleEffect",
                             ""] = self.effectIconFiles["ImplicitRectangle",
                                                        ""]
        self.effectIconFiles["LevelTracingEffect",
                             ""] = self.effectIconFiles["LevelTracing", ""]
        self.effectIconFiles["MakeModelEffect",
                             ""] = self.effectIconFiles["MakeModel", ""]
        self.effectIconFiles["ErodeEffect",
                             ""] = self.effectIconFiles["ErodeLabel", ""]
        self.effectIconFiles["DilateEffect",
                             ""] = self.effectIconFiles["DilateLabel", ""]
        self.effectIconFiles["IdentifyIslandsEffect",
                             ""] = self.effectIconFiles["IdentifyIslands", ""]
        self.effectIconFiles["ChangeIslandEffect",
                             ""] = self.effectIconFiles["ChangeIsland", ""]
        self.effectIconFiles["RemoveIslandsEffect",
                             ""] = self.effectIconFiles["RemoveIslands", ""]
        self.effectIconFiles["SaveIslandEffect",
                             ""] = self.effectIconFiles["SaveIsland", ""]
        self.effectIconFiles["ChangeIslandEffect",
                             ""] = self.effectIconFiles["ChangeIsland", ""]
        self.effectIconFiles["ChangeLabelEffect",
                             ""] = self.effectIconFiles["ChangeLabel", ""]
        self.effectIconFiles["GrowCutEffect",
                             ""] = self.effectIconFiles["GrowCutSegment", ""]

    #
    # create a row of the edit box given a list of
    # effect names (items in _effects(list)
    #
    def createButtonRow(self, effects, rowLabel=""):

        f = qt.QFrame(self.parent)
        self.parent.layout().addWidget(f)
        self.rowFrames.append(f)
        hbox = qt.QHBoxLayout()
        f.setLayout(hbox)

        if rowLabel:
            label = qt.QLabel(rowLabel)
            hbox.addWidget(label)

        for effect in effects:
            # check that the effect belongs in our list of effects before including
            if (effect in self.effects):
                i = self.icons[effect] = qt.QIcon(
                    self.effectIconFiles[effect, self.effectModes[effect]])
                a = self.actions[effect] = qt.QAction(i, '', f)
                self.effectButtons[effect] = b = self.buttons[
                    effect] = qt.QToolButton()
                b.setDefaultAction(a)
                b.setToolTip(effect)
                if EditBox.displayNames.has_key(effect):
                    b.setToolTip(EditBox.displayNames[effect])
                hbox.addWidget(b)
                if self.disabled.__contains__(effect):
                    b.setDisabled(1)

                # Setup the mapping between button and its associated effect name
                self.effectMapper.setMapping(self.buttons[effect], effect)
                # Connect button with signal mapper
                self.buttons[effect].connect('clicked()', self.effectMapper,
                                             'map()')

        hbox.addStretch(1)

    # create the edit box
    def create(self):

        self.findEffects()

        #
        # the buttons
        #
        self.rowFrames = []
        self.actions = {}
        self.buttons = {}
        self.icons = {}
        self.callbacks = {}

        # create all of the buttons
        # createButtonRow() ensures that only effects in self.effects are exposed,
        self.createButtonRow(
            ("DefaultTool", "EraseLabel", "PaintEffect", "DrawEffect",
             "LevelTracingEffect", "RectangleEffect", "IdentifyIslandsEffect",
             "ChangeIslandEffect", "RemoveIslandsEffect", "SaveIslandEffect"))
        self.createButtonRow(
            ("ErodeEffect", "DilateEffect", "GrowCutEffect", "ThresholdEffect",
             "ChangeLabelEffect", "MakeModelEffect"))

        extensions = []
        for k in slicer.modules.editorExtensions:
            extensions.append(k)
        self.createButtonRow(extensions)

        # TODO: add back prev/next fiducial
        #self.createButtonRow( ("PreviousFiducial", "NextFiducial") )
        self.createButtonRow(("PreviousCheckPoint", "NextCheckPoint"),
                             rowLabel="Undo/Redo: ")

        #
        # the labels
        #
        self.toolsActiveToolFrame = qt.QFrame(self.parent)
        self.toolsActiveToolFrame.setLayout(qt.QHBoxLayout())
        self.parent.layout().addWidget(self.toolsActiveToolFrame)
        self.toolsActiveTool = qt.QLabel(self.toolsActiveToolFrame)
        self.toolsActiveTool.setText('Active Tool:')
        self.toolsActiveTool.setStyleSheet(
            "background-color: rgb(232,230,235)")
        self.toolsActiveToolFrame.layout().addWidget(self.toolsActiveTool)
        self.toolsActiveToolName = qt.QLabel(self.toolsActiveToolFrame)
        self.toolsActiveToolName.setText('')
        self.toolsActiveToolName.setStyleSheet(
            "background-color: rgb(232,230,235)")
        self.toolsActiveToolFrame.layout().addWidget(self.toolsActiveToolName)

        self.updateUndoRedoButtons()

    def setActiveToolLabel(self, name):
        if EditBox.displayNames.has_key(name):
            name = EditBox.displayNames[name]
        self.toolsActiveToolName.setText(name)

    #
    # switch to the default tool
    #
    def defaultEffect(self):
        self.selectEffect("DefaultTool")

    #
    # manage the editor effects
    #
    def selectEffect(self, effectName):

        #
        # If there is no background volume or label map, do nothing
        #
        if not self.editUtil.getBackgroundVolume():
            return
        if not self.editUtil.getLabelVolume():
            return

        #
        # if a modal effect was selected, 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 not self.nonmodal.__contains__(effectName):

            if self.currentOption:
                # clean up any existing effect
                self.currentOption.__del__()
                self.currentOption = None
                for tool in self.currentTools:
                    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.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

        slicer.app.restoreOverrideCursor()
        self.setActiveToolLabel(effectName)

        # mouse tool changes cursor, and dismisses popup/menu
        mouseTool = False
        if self.mouseTools.__contains__(effectName):
            mouseTool = True

        if effectName == "DefaultTool":
            # do nothing - this will reset cursor mode
            pass
        elif effectName == "EraseLabel":
            self.editUtil.toggleLabel()
        elif effectName == "PreviousCheckPoint":
            self.undoRedo.undo()
        elif effectName == "NextCheckPoint":
            self.undoRedo.redo()
        else:
            if mouseTool:
                # TODO: make some nice custom cursor shapes
                # - for now use the built in override cursor
                #pix = qt.QPixmap()
                #pix.load(self.effectIconFiles[effectName,""])
                #cursor = qt.QCursor(pix)
                #app.setOverrideCursor(cursor, 0, 0)
                cursor = qt.QCursor(1)
                slicer.app.setOverrideCursor(cursor)
            else:
                slicer.app.restoreOverrideCursor()
コード例 #20
0
 def paintLabelMap(self, labelNode):
     cursorPosition = qt.QCursor().pos()
     #w = self.mainFrame.width
     #h = self.mainFrame.height
     # self.mainFrame.pos = qt.QPoint(cursorPosition.x() - w/2, cursorPosition.y() - h/2)
     print(cursorPosition.x(), cursorPosition.y())
コード例 #21
0
    def getMeanOpticalAttenuationOfCentralCylinder(self,
                                                   calibrationVolumeNodeID,
                                                   centralRadiusMm):
        # Format of output array: the following values are provided for each slice:
        #   depth (cm), mean optical attenuation on the slice at depth, std.dev. of optical attenuation
        qt.QApplication.setOverrideCursor(qt.QCursor(qt.Qt.BusyCursor))

        calibrationVolume = slicer.util.getNode(calibrationVolumeNodeID)
        calibrationVolumeImageData = calibrationVolume.GetImageData()

        # Get image properties needed for the calculation
        calibrationVolumeSliceThicknessCm = calibrationVolume.GetSpacing(
        )[2] / 10.0
        if calibrationVolume.GetSpacing()[0] != calibrationVolume.GetSpacing(
        )[1]:
            logging.warning(
                'Image data X and Y spacing differ! This is not supported, the mean optical attenuation data may be skewed'
            )
        calibrationVolumeInPlaneSpacing = calibrationVolume.GetSpacing()[0]

        centralRadiusPixel = int(
            numpy.ceil(centralRadiusMm / calibrationVolumeInPlaneSpacing))
        if centralRadiusPixel != centralRadiusMm / calibrationVolumeInPlaneSpacing:
            logging.info(
                'Central radius has been rounded up to {0} (original radius is {1}mm = {2}px)'
                .format(centralRadiusPixel, centralRadiusMm,
                        centralRadiusMm / calibrationVolumeInPlaneSpacing))

        numberOfSlices = calibrationVolumeImageData.GetExtent(
        )[5] - calibrationVolumeImageData.GetExtent()[4] + 1
        centerXCoordinate = (calibrationVolumeImageData.GetExtent()[1] -
                             calibrationVolumeImageData.GetExtent()[0]) / 2
        centerYCoordinate = (calibrationVolumeImageData.GetExtent()[3] -
                             calibrationVolumeImageData.GetExtent()[2]) / 2

        # Get image data in numpy array
        calibrationVolumeImageDataAsScalars = calibrationVolumeImageData.GetPointData(
        ).GetScalars()
        numpyImageDataArray = numpy_support.vtk_to_numpy(
            calibrationVolumeImageDataAsScalars)
        numpyImageDataArray = numpy.reshape(
            numpyImageDataArray,
            (calibrationVolumeImageData.GetExtent()[1] + 1,
             calibrationVolumeImageData.GetExtent()[3] + 1,
             calibrationVolumeImageData.GetExtent()[5] + 1), 'F')

        opticalAttenuationOfCentralCylinderTable = numpy.zeros(
            (numberOfSlices, 3))
        sliceNumber = 0
        z = calibrationVolumeImageData.GetExtent()[5]
        zMin = calibrationVolumeImageData.GetExtent()[4]
        while z >= zMin:
            totalPixels = 0
            totalOpticalAttenuation = 0
            listOfOpticalDensities = []
            meanOpticalAttenuation = 0

            for y in range(floor(centerYCoordinate - centralRadiusPixel + 0.5),
                           ceil(centerYCoordinate + centralRadiusPixel + 0.5)):
                for x in range(
                        floor(centerXCoordinate - centralRadiusPixel + 0.5),
                        ceil(centerXCoordinate + centralRadiusPixel + 0.5)):
                    distanceOfX = abs(x - centerXCoordinate)
                    distanceOfY = abs(y - centerYCoordinate)
                    if ((distanceOfX + distanceOfY) <= centralRadiusPixel) or (
                        (pow(distanceOfX, 2) + pow(distanceOfY, 2)) <= pow(
                            centralRadiusPixel, 2)):
                        currentOpticalAttenuation = numpyImageDataArray[x, y,
                                                                        z]
                        listOfOpticalDensities.append(
                            currentOpticalAttenuation)
                        totalOpticalAttenuation = totalOpticalAttenuation + currentOpticalAttenuation
                        totalPixels += 1

            meanOpticalAttenuation = totalOpticalAttenuation / totalPixels
            standardDeviationOpticalAttenuation = 0
            for currentOpticalAttenuationValue in range(totalPixels):
                standardDeviationOpticalAttenuation += pow(
                    (listOfOpticalDensities[currentOpticalAttenuationValue] -
                     meanOpticalAttenuation), 2)
            standardDeviationOpticalAttenuation = sqrt(
                standardDeviationOpticalAttenuation / totalPixels)
            opticalAttenuationOfCentralCylinderTable[
                sliceNumber,
                0] = sliceNumber * calibrationVolumeSliceThicknessCm
            opticalAttenuationOfCentralCylinderTable[
                sliceNumber, 1] = meanOpticalAttenuation
            opticalAttenuationOfCentralCylinderTable[
                sliceNumber, 2] = standardDeviationOpticalAttenuation
            # logging.debug('Slice (cm): ' + repr(sliceNumber*calibrationVolumeSliceThicknessCm))
            # logging.debug('  Mean: ' + repr(meanOpticalAttenuation) + '  StdDev: ' + repr(standardDeviationOpticalAttenuation))
            sliceNumber += 1
            z -= 1

        qt.QApplication.restoreOverrideCursor()
        logging.info(
            'CALIBRATION data has been successfully parsed with averaging radius {0}mm ({1}px)'
            .format(centralRadiusMm, centralRadiusPixel))
        self.calibrationDataArray = opticalAttenuationOfCentralCylinderTable
        return True
コード例 #22
0
ファイル: Effect.py プロジェクト: mehrtash/Slicer
 def cursorOff(self):
     """Turn off and save the current cursor so
 the user can see the background image during editing"""
     self.savedCursor = self.sliceWidget.cursor
     qt_BlankCursor = 10
     self.sliceWidget.setCursor(qt.QCursor(qt_BlankCursor))
コード例 #23
0
    def alignPddToCalibration(self):
        qt.QApplication.setOverrideCursor(qt.QCursor(qt.Qt.BusyCursor))
        error = -1.0

        # Check the input arrays
        if self.pddDataArray.size == 0 or self.calibrationDataArray.size == 0:
            logging.error('Pdd or calibration data is empty')
            return error

        # Discard values of 0 from both ends of the data (it is considered invalid)
        self.calibrationDataCleanedArray = self.calibrationDataArray
        calibrationCleanedNumberOfRows = self.calibrationDataCleanedArray.shape[
            0]
        while self.calibrationDataCleanedArray[0, 1] == 0:
            self.calibrationDataCleanedArray = numpy.delete(
                self.calibrationDataCleanedArray, 0, 0)
        calibrationCleanedNumberOfRows = self.calibrationDataCleanedArray.shape[
            0]
        while self.calibrationDataCleanedArray[calibrationCleanedNumberOfRows -
                                               1, 1] == 0:
            self.calibrationDataCleanedArray = numpy.delete(
                self.calibrationDataCleanedArray,
                calibrationCleanedNumberOfRows - 1, 0)
            calibrationCleanedNumberOfRows = self.calibrationDataCleanedArray.shape[
                0]

        # Remove outliers from calibration array
        self.calibrationDataCleanedArray = self.removeOutliersFromArray(
            self.calibrationDataCleanedArray, 5, 10, 0.0075)[0]

        # Do initial scaling of the calibration array based on the maximum values
        maxPdd = self.findMaxValueInArray(self.pddDataArray)
        maxCalibration = self.findMaxValueInArray(
            self.calibrationDataCleanedArray)
        initialScaling = maxPdd / maxCalibration
        # logging.debug('Initial scaling factor {0:.4f}'.format(initialScaling))

        # Create the working structures
        self.minimizer = vtk.vtkAmoebaMinimizer()
        self.minimizer.SetFunction(curveAlignmentCalibrationFunction)
        self.minimizer.SetParameterValue("xTrans", 0)
        self.minimizer.SetParameterScale("xTrans", 2)
        self.minimizer.SetParameterValue("yScale", initialScaling)
        self.minimizer.SetParameterScale("yScale", 0.1)
        self.minimizer.SetParameterValue("yTrans", 0)
        self.minimizer.SetParameterScale("yTrans", 0.2)
        self.minimizer.SetMaxIterations(50)

        self.minimizer.Minimize()
        error = self.minimizer.GetFunctionValue()
        xTrans = self.minimizer.GetParameterValue("xTrans")
        yScale = self.minimizer.GetParameterValue("yScale")
        yTrans = self.minimizer.GetParameterValue("yTrans")

        # Create aligned array
        self.createAlignedCalibrationArray(xTrans, yScale, yTrans)

        qt.QApplication.restoreOverrideCursor()
        logging.info(
            'CALIBRATION successfully aligned with PDD with error={0:.2f} and parameters xTrans={1:.2f}, yScale={2:.2f}, yTrans={3:.2f}'
            .format(error, xTrans, yScale, yTrans))
        return [error, xTrans, yScale, yTrans]