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()
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
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()
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()
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)
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
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) '''
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)
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)