Ejemplo n.º 1
1
  def preview(self, color=None, checked = True):
    """previewsing the result of thresholding"""
    if not self.editUtil.getBackgroundImage() or not self.editUtil.getLabelImage():
      return

    if not checked:
      self.cursorActor.VisibilityOff()
      self.sliceView.scheduleRender()
      return

    #
    # make a lookup table where inside the threshold is opaque and colored
    # by the label color, while the background is transparent (black)
    # - apply the threshold operation to the currently visible background
    #   (output of the layer logic's vtkImageReslice instance)
    #

    if not color:
      color = self.getPaintColor

    if not self.lut:
      self.lut = vtk.vtkLookupTable()

    self.lut.SetRampToLinear()
    self.lut.SetNumberOfTableValues( 2 )
    self.lut.SetTableRange( 0, 1 )
    self.lut.SetTableValue( 0,  0, 0, 0,  0 )
    r,g,b,a = color
    self.lut.SetTableValue( 1,  r, g, b,  a )

    if not self.map:
      self.map = vtk.vtkImageMapToRGBA()
    self.map.SetOutputFormatToRGBA()
    self.map.SetLookupTable( self.lut )

    if not self.thresh:
      self.thresh = vtk.vtkImageThreshold()
    sliceLogic = self.sliceWidget.sliceLogic()
    backgroundLogic = sliceLogic.GetBackgroundLayer()
    if vtk.VTK_MAJOR_VERSION <= 5:
      self.thresh.SetInput( backgroundLogic.GetReslice().GetOutput() )
    else:
      self.thresh.SetInputConnection( backgroundLogic.GetReslice().GetOutputPort() )
    self.thresh.ThresholdBetween( self.min, self.max )
    self.thresh.SetInValue( 1 )
    self.thresh.SetOutValue( 0 )
    self.thresh.SetOutputScalarTypeToUnsignedChar()
    if vtk.VTK_MAJOR_VERSION <= 5:
      self.map.SetInput( self.thresh.GetOutput() )
      self.map.Update()
      self.cursorMapper.SetInput( self.map.GetOutput() )
    else:
      self.map.SetInputConnection( self.thresh.GetOutputPort() )
      self.cursorMapper.SetInputConnection( self.map.GetOutputPort() )

    self.cursorActor.VisibilityOn()

    self.sliceView.scheduleRender()
Ejemplo n.º 2
0
 def createColorScalarBar(self, sliceViewName):
   scalarBar = vtk.vtkScalarBarActor()
   scalarBar.SetTitle("")
   # adjust text property
   lookupTable = vtk.vtkLookupTable()
   scalarBar.SetLookupTable(lookupTable)
   scalarBarWidget = vtk.vtkScalarBarWidget()
   scalarBarWidget.SetScalarBarActor(scalarBar)
   self.colorScalarBarWidgets[sliceViewName] = scalarBarWidget
   return scalarBar
Ejemplo n.º 3
0
    def preview(self, color=None):

        if not self.editUtil.getBackgroundImage(
        ) or not self.editUtil.getLabelImage():
            return

        #
        # make a lookup table where inside the threshold is opaque and colored
        # by the label color, while the background is transparent (black)
        # - apply the threshold operation to the currently visible background
        #   (output of the layer logic's vtkImageReslice instance)
        #

        if not color:
            color = self.getPaintColor

        if not self.lut:
            self.lut = vtk.vtkLookupTable()

        self.lut.SetRampToLinear()
        self.lut.SetNumberOfTableValues(2)
        self.lut.SetTableRange(0, 1)
        self.lut.SetTableValue(0, 0, 0, 0, 0)
        r, g, b, a = color
        self.lut.SetTableValue(1, r, g, b, a)

        if not self.map:
            self.map = vtk.vtkImageMapToRGBA()
        self.map.SetOutputFormatToRGBA()
        self.map.SetLookupTable(self.lut)

        if not self.thresh:
            self.thresh = vtk.vtkImageThreshold()
        sliceLogic = self.sliceWidget.sliceLogic()
        backgroundLogic = sliceLogic.GetBackgroundLayer()
        if vtk.VTK_MAJOR_VERSION <= 5:
            self.thresh.SetInput(backgroundLogic.GetReslice().GetOutput())
        else:
            self.thresh.SetInputConnection(
                backgroundLogic.GetReslice().GetOutputPort())
        self.thresh.ThresholdBetween(self.min, self.max)
        self.thresh.SetInValue(1)
        self.thresh.SetOutValue(0)
        self.thresh.SetOutputScalarTypeToUnsignedChar()
        if vtk.VTK_MAJOR_VERSION <= 5:
            self.map.SetInput(self.thresh.GetOutput())
            self.map.Update()
            self.cursorMapper.SetInput(self.map.GetOutput())
        else:
            self.map.SetInputConnection(self.thresh.GetOutputPort())
            self.cursorMapper.SetInputConnection(self.map.GetOutputPort())

        self.cursorActor.VisibilityOn()

        self.sliceView.scheduleRender()
Ejemplo n.º 4
0
 def createColorScalarBar(self, sliceViewName):
   scalarBar = slicer.vtkPVScalarBarActor()
   scalarBar.SetTitle(" ")
   # adjust text property
   scalarBar.SetRangeLabelFormat('%.0f')
   lookupTable = vtk.vtkLookupTable()
   scalarBar.SetLookupTable(lookupTable)
   scalarBarWidget = vtk.vtkScalarBarWidget()
   scalarBarWidget.SetScalarBarActor(scalarBar)
   self.colorScalarBarWidgets[sliceViewName] = scalarBarWidget
   return scalarBar
  def preview(self,color=None):

    if not self.editUtil.getBackgroundImage() or not self.editUtil.getLabelImage():
      return

    #
    # make a lookup table where inside the threshold is opaque and colored
    # by the label color, while the background is transparent (black)
    # - apply the threshold operation to the currently visible background
    #   (output of the layer logic's vtkImageReslice instance)
    #

    if not color:
      color = self.getPaintColor

    if not self.lut:
      self.lut = vtk.vtkLookupTable()

    self.lut.SetRampToLinear()
    self.lut.SetNumberOfTableValues( 3 )
    self.lut.SetTableRange( 0, 2 )
    self.lut.SetTableValue( 0,  0, 0, 0,  0 )
    r,g,b,a = color
    self.lut.SetTableValue( 1,  r, g, b,  a )
    #self.lut.SetTableValue( 2,  r, g, b,  a )

    if not self.map:
      self.map = vtk.vtkImageMapToRGBA()
    self.map.SetOutputFormatToRGBA()
    self.map.SetLookupTable( self.lut )

    if not self.thresh:
      self.thresh = vtk.vtkImageThreshold()
    sliceLogic = self.sliceWidget.sliceLogic()
    backgroundLogic = sliceLogic.GetBackgroundLayer()
#    backgroundNodeName = backgroundNode.GetName()
#    backgroundImage = sitk.ReadImage( sitkUtils.GetSlicerITKReadWriteAddress( backgroundNodeName ) )

    self.thresh.SetInput( backgroundLogic.GetReslice().GetOutput() )
    self.thresh.ThresholdBetween( self.min, self.max )
    self.thresh.SetInValue( 1 )
    self.thresh.SetOutValue( 0 )
    self.thresh.SetOutputScalarTypeToUnsignedChar()
    self.map.SetInput( self.thresh.GetOutput() )

    self.map.Update()

    self.cursorMapper.SetInput( self.map.GetOutput() )
    self.cursorActor.VisibilityOn()

    self.sliceView.scheduleRender()
Ejemplo n.º 6
0
 def updateScalarBarRange(self, sliceLogic, volumeNode, scalarBar, selectedLayer):
   vdn = volumeNode.GetDisplayNode()
   if vdn:
     vcn = vdn.GetColorNode()
     lut = vcn.GetLookupTable()
     lut2 = vtk.vtkLookupTable()
     lut2.DeepCopy(lut)
     width = vtk.mutable(0)
     level = vtk.mutable(0)
     rangeLow = vtk.mutable(0)
     rangeHigh = vtk.mutable(0)
     if selectedLayer == 'background':
       sliceLogic.GetBackgroundWindowLevelAndRange(width,level,rangeLow,rangeHigh)
     else:
       sliceLogic.GetForegroundWindowLevelAndRange(width,level,rangeLow,rangeHigh)
     lut2.SetRange(level-width/2,level+width/2)
     scalarBar.SetLookupTable(lut2)
Ejemplo n.º 7
0
 def createColorScalarBar(self, sliceViewName):
   if self.hasVTKPVScalarBarActor:
     scalarBar = slicer.vtkPVScalarBarActor()
   else:
     scalarBar = vtk.vtkScalarBarActor()
   scalarBar.SetTitle(" ")
   # adjust text property
   if self.hasVTKPVScalarBarActor:
     scalarBar.SetRangeLabelFormat(self.rangeLabelFormat)
   lookupTable = vtk.vtkLookupTable()
   scalarBar.SetLookupTable(lookupTable)
   scalarBarWidget = vtk.vtkScalarBarWidget()
   scalarBarWidget.SetScalarBarActor(scalarBar)
   if vtk.VTK_MAJOR_VERSION <= 5:
     scalarBarWidget.RepositionableOff()
   self.colorScalarBarWidgets[sliceViewName] = scalarBarWidget
   return scalarBar
Ejemplo n.º 8
0
 def updateScalarBarRange(self, sliceLogic, volumeNode, scalarBar, selectedLayer):
   vdn = volumeNode.GetDisplayNode()
   if vdn:
     vcn = vdn.GetColorNode()
     lut = vcn.GetLookupTable()
     lut2 = vtk.vtkLookupTable()
     lut2.DeepCopy(lut)
     width = vtk.mutable(0)
     level = vtk.mutable(0)
     rangeLow = vtk.mutable(0)
     rangeHigh = vtk.mutable(0)
     if selectedLayer == 'background':
       sliceLogic.GetBackgroundWindowLevelAndRange(width,level,rangeLow,rangeHigh)
     else:
       sliceLogic.GetForegroundWindowLevelAndRange(width,level,rangeLow,rangeHigh)
     lut2.SetRange(int(level-width/2),int(level+width/2))
     scalarBar.SetLookupTable(lut2)
     '''
Ejemplo n.º 9
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 = 5.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)
Ejemplo n.º 10
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)