Slicer 5.13
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
Loading...
Searching...
No Matches
ScriptedPipelineSceneConnector.py
Go to the documentation of this file.
1import slicer
2from slicer import (
3 vtkMRMLLayerDMPipelineFactory,
4 vtkMRMLLayerDMPipelineScriptedCreator,
5)
6
7
9 """
10 Convenience base class connecting the scripted LayerDM pipelines of one module to the scene.
11
12 Subclass and override:
13 - getPipelines: return the pipeline classes handled by the module.
14 - getSceneObservers: optionally return (eventId, callback) pairs to observe on the MRML scene.
15 - onConnected: optionally perform additional setup after connecting (for instance adding
16 data nodes to the scene).
17
18 Expected usage in a scripted module:
19 - Instantiate the subclass at module level.
20 - Call connect at application startup and from the module widget's setup. connect removes any
21 previous connection first, so re-connecting from setup makes a module reload rebind the
22 reloaded pipeline classes (the LayerDM pipeline managers automatically recreate the pipelines
23 of a creator which was removed from the factory).
24 - Call disconnect from the module widget's cleanup, which is invoked by the module reload
25 machinery before the widget is rebuilt and when the module is unloaded.
26 """
27
28 def __init__(self, scene=None):
29 """
30 :param scene: Optional MRML scene to connect to. If None, the slicer.mrmlScene singleton is used
31 when connect is called. Passing the scene explicitly avoids depending on the singleton, which
32 is not available in trame-slicer.
33 """
34 self._scene = scene
35 self._connectedScene = None
36 self._pipelineCreator = None
38
39 def getScene(self):
40 """
41 Returns the scene this connector is connected to.
42 While disconnected, returns the scene it would connect to (the scene given at construction,
43 or the slicer.mrmlScene singleton).
44 Subclass overrides should use this instead of the slicer.mrmlScene singleton.
45 """
46 if self._connectedScene is not None:
47 return self._connectedScene
48 return self._scene if self._scene is not None else slicer.mrmlScene
49
50 def getPipelines(self) -> list:
51 """
52 Override to return the pipeline classes handled by the module.
53 Each class should provide a TryCreatePipeline(viewNode, node) class method returning a new pipeline
54 instance or None. The classes are queried in order until one returns a pipeline.
55 """
56 return []
57
58 def getSceneObservers(self) -> list:
59 """Override to return (eventId, callback) pairs to observe on the MRML scene while connected."""
60 return []
61
62 def onConnected(self) -> None:
63 """Override to perform additional setup after connecting (for instance adding data nodes to the scene)."""
64
65 def connect(self) -> None:
66 """
67 Registers a pipeline creator for the getPipelines classes, adds the getSceneObservers observers and
68 calls onConnected. Any previous connection held by this instance is removed first.
69
70 :raises TypeError: If any of the getPipelines classes doesn't implement TryCreatePipeline.
71 Checked eagerly, as a missing TryCreatePipeline would otherwise only fail when a node is
72 added to the scene, far from the actual mistake.
73 """
74 pipelines = self.getPipelines()
75 for pipeline in pipelines:
76 if not callable(getattr(pipeline, "TryCreatePipeline", None)):
77 raise TypeError(
78 f"{pipeline.__name__} cannot be used with {type(self).__name__}: "
79 "it does not implement the TryCreatePipeline(viewNode, node) class method.")
80
81 self.disconnect()
82 self._connectedScene = self._scene if self._scene is not None else slicer.mrmlScene
83
84 def tryCreate(viewNode, node):
85 for pipeline in pipelines:
86 ret = pipeline.TryCreatePipeline(viewNode, node)
87 if ret is not None:
88 return ret
89 return None
90
91 self._pipelineCreator = vtkMRMLLayerDMPipelineScriptedCreator()
92 self._pipelineCreator.SetPythonCallback(tryCreate)
93 vtkMRMLLayerDMPipelineFactory.GetInstance().AddPipelineCreator(self._pipelineCreator)
94
95 for eventId, callback in self.getSceneObservers():
96 self._sceneObserverTags.append(self._connectedScene.AddObserver(eventId, callback))
97
98 self.onConnected()
99
100 def disconnect(self) -> None:
101 """Undoes the connection done by connect. Safe to call when nothing is connected."""
102 if self._pipelineCreator is not None:
104 self._pipelineCreator = None
105 for tag in self._sceneObserverTags:
106 self._connectedScene.RemoveObserver(tag)
107 self._sceneObserverTags = []
108 self._connectedScene = None
static vtkSmartPointer< vtkMRMLLayerDMPipelineFactory > GetInstance()
Singleton instance of the factory used by the displayable manager.