Slicer  5.0
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
AbstractScriptedSegmentEditorEffect.py
Go to the documentation of this file.
1 import qt
2 
3 import slicer
4 
5 
6 #
7 # Abstract class of python scripted segment editor effects
8 #
9 
11  """ Abstract scripted segment editor effects for effects implemented in python
12 
13  USAGE:
14  1. Instantiation and registration
15  Instantiate segment editor effect adaptor class from
16  module (e.g. from setup function), and set python source:
17  > import qSlicerSegmentationsEditorEffectsPythonQt as effects
18  > scriptedEffect = effects.qSlicerSegmentEditorScriptedEffect(None)
19  > scriptedEffect.setPythonSource(MyEffect.filePath)
20  > scriptedEffect.self().register()
21  If effect name is added to slicer.modules.segmenteditorscriptedeffectnames
22  list then the above instantiation and registration steps are not necessary,
23  as the SegmentEditor module do all these.
24 
25  2. Call host C++ implementation using
26  > self.scriptedEffect.functionName()
27 
28  2.a. Most frequently used such methods are:
29  Parameter get/set: parameter, integerParameter, doubleParameter, setParameter
30  Add options widget: addOptionsWidget
31  Coordinate transforms: rasToXy, xyzToRas, xyToRas, xyzToIjk, xyToIjk
32  Convenience getters: renderWindow, renderer, viewNode
33 
34  2.b. Always call API functions (the ones that are defined in the adaptor
35  class qSlicerSegmentEditorScriptedEffect) using the adaptor accessor:
36  > self.scriptedEffect.updateGUIFromMRML()
37 
38  3. To prevent deactivation of an effect by clicking place fiducial toolbar button,
39  override interactionNodeModified(self, interactionNode)
40 
41  An example for a generic effect is the ThresholdEffect
42 
43  """
44 
45  def __init__(self, scriptedEffect):
46  self.scriptedEffect = scriptedEffect
47 
48  def register(self):
49  effectFactorySingleton = slicer.qSlicerSegmentEditorEffectFactory.instance()
50  effectFactorySingleton.registerEffect(self.scriptedEffect)
51 
52  #
53  # Utility functions for convenient coordinate transformations
54  #
55  def rasToXy(self, ras, viewWidget):
56  rasVector = qt.QVector3D(ras[0], ras[1], ras[2])
57  xyPoint = self.scriptedEffect.rasToXy(rasVector, viewWidget)
58  return [xyPoint.x(), xyPoint.y()]
59 
60  def xyzToRas(self, xyz, viewWidget):
61  xyzVector = qt.QVector3D(xyz[0], xyz[1], xyz[2])
62  rasVector = self.scriptedEffect.xyzToRas(xyzVector, viewWidget)
63  return [rasVector.x(), rasVector.y(), rasVector.z()]
64 
65  def xyToRas(self, xy, viewWidget):
66  xyPoint = qt.QPoint(xy[0], xy[1])
67  rasVector = self.scriptedEffect.xyToRas(xyPoint, viewWidget)
68  return [rasVector.x(), rasVector.y(), rasVector.z()]
69 
70  def xyzToIjk(self, xyz, viewWidget, image, parentTransformNode=None):
71  xyzVector = qt.QVector3D(xyz[0], xyz[1], xyz[2])
72  ijkVector = self.scriptedEffect.xyzToIjk(xyzVector, viewWidget, image, parentTransformNode)
73  return [int(ijkVector.x()), int(ijkVector.y()), int(ijkVector.z())]
74 
75  def xyToIjk(self, xy, viewWidget, image, parentTransformNode=None):
76  xyPoint = qt.QPoint(xy[0], xy[1])
77  ijkVector = self.scriptedEffect.xyToIjk(xyPoint, viewWidget, image, parentTransformNode)
78  return [int(ijkVector.x()), int(ijkVector.y()), int(ijkVector.z())]
79 
80  def setWidgetMinMaxStepFromImageSpacing(self, spinbox, imageData):
81  # Set spinbox minimum, maximum, and step size from vtkImageData spacing:
82  # Set widget minimum spacing and step size to be 1/10th or less than minimum spacing
83  # Set widget minimum spacing to be 100x or more than minimum spacing
84  if not imageData:
85  return
86  import math
87  spinbox.unitAwareProperties &= ~(slicer.qMRMLSpinBox.MinimumValue | slicer.qMRMLSpinBox.MaximumValue | slicer.qMRMLSpinBox.Precision)
88  stepSize = 10**(math.floor(math.log10(min(imageData.GetSpacing()) / 10.0)))
89  spinbox.minimum = stepSize
90  spinbox.maximum = 10**(math.ceil(math.log10(max(imageData.GetSpacing()) * 100.0)))
91  spinbox.singleStep = stepSize
92  # number of decimals is set to be able to show the step size (e.g., stepSize = 0.01 => decimals = 2)
93  spinbox.decimals = max(int(-math.floor(math.log10(stepSize))), 0)