7 """Abstract scripted segment editor effects for effects implemented in python.
9 An example of generic effect is ``ThresholdEffect``.
11 To use the effect, follow these steps:
13 1. Instantiation and registration
15 Instantiate segment editor effect adaptor class from
16 module (e.g. from setup function), and set python source::
18 import qSlicerSegmentationsEditorEffectsPythonQt as effects
19 scriptedEffect = effects.qSlicerSegmentEditorScriptedEffect(None)
20 scriptedEffect.setPythonSource(MyEffect.filePath)
21 scriptedEffect.self().register()
23 If effect name is added to ``slicer.modules.segmenteditorscriptedeffectnames``
24 list then the above instantiation and registration steps are not necessary,
25 as the `SegmentEditor` module do all these.
27 2. Call host C++ implementation using::
29 self.scriptedEffect.functionName()
31 2.a. Most frequently used methods are:
33 - Parameter get/set: ``parameter``, ``integerParameter``, ``doubleParameter``, ``setParameter``
34 - Add options widget: ``addOptionsWidget``
35 - Coordinate transforms: ``rasToXy``, ``xyzToRas``, ``xyToRas``, ``xyzToIjk``, ``xyToIjk``
36 - Convenience getters: ``renderWindow``, ``renderer``, ``viewNode``
38 2.b. Always call API functions (the ones that are defined in the adaptor \
39 class ``qSlicerSegmentEditorScriptedEffect``) using the adaptor accessor ``self.scriptedEffect``.
43 self.scriptedEffect.updateGUIFromMRML()
45 3. To prevent deactivation of an effect by clicking place fiducial toolbar button, \
46 override ``interactionNodeModified(self, interactionNode)``
53 effectFactorySingleton = slicer.qSlicerSegmentEditorEffectFactory.instance()
58 Clean up resources, event observers, and Qt signal/slot connections
59 to ensure proper object deletion.
61 Subclasses should override this method to disconnect any subclass-specific
62 signals and slots. This method should be called before the object is
63 garbage collected or explicitly deleted on the C++ side.
65 Failing to disconnect signals/slots may prevent the object from being
66 garbage collected, leading to memory leaks.
68 For more details, see: https://github.com/Slicer/Slicer/issues/7392
76 rasVector = qt.QVector3D(ras[0], ras[1], ras[2])
78 return [xyPoint.x(), xyPoint.y()]
81 xyzVector = qt.QVector3D(xyz[0], xyz[1], xyz[2])
83 return [rasVector.x(), rasVector.y(), rasVector.z()]
86 xyPoint = qt.QPoint(xy[0], xy[1])
88 return [rasVector.x(), rasVector.y(), rasVector.z()]
90 def xyzToIjk(self, xyz, viewWidget, image, parentTransformNode=None):
91 xyzVector = qt.QVector3D(xyz[0], xyz[1], xyz[2])
93 return [int(ijkVector.x()), int(ijkVector.y()), int(ijkVector.z())]
95 def xyToIjk(self, xy, viewWidget, image, parentTransformNode=None):
96 xyPoint = qt.QPoint(xy[0], xy[1])
98 return [int(ijkVector.x()), int(ijkVector.y()), int(ijkVector.z())]
107 spinbox.unitAwareProperties &= ~(slicer.qMRMLSpinBox.MinimumValue | slicer.qMRMLSpinBox.MaximumValue | slicer.qMRMLSpinBox.Precision)
108 stepSize = 10 ** (math.floor(math.log10(min(imageData.GetSpacing()) / 10.0)))
109 spinbox.minimum = stepSize
110 spinbox.maximum = 10 ** (math.ceil(math.log10(max(imageData.GetSpacing()) * 100.0)))
111 spinbox.singleStep = stepSize
113 spinbox.decimals = max(int(-math.floor(math.log10(stepSize))), 0)
xyzToRas(self, xyz, viewWidget)
rasToXy(self, ras, viewWidget)
__init__(self, scriptedEffect)
xyzToIjk(self, xyz, viewWidget, image, parentTransformNode=None)
setWidgetMinMaxStepFromImageSpacing(self, spinbox, imageData)
xyToIjk(self, xy, viewWidget, image, parentTransformNode=None)
xyToRas(self, xy, viewWidget)