I have a working scripted extension that enables a user to select a path within any chosen trajectory list, as generated via the separate PathExplorer widget from the SlicerIGT extension:
However, after passing tests and restarting Slicer, I noticed a new ImportError
during launch:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/opt/slicer/lib/Python/lib/python3.9/imp.py", line 169, in load_source
module = _exec(spec, sys.modules[name])
File "<frozen importlib._bootstrap>", line 613, in _exec
File "<frozen importlib._bootstrap_external>", line 850, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "/opt/air_ws/src/slicer/AirIGT/AirGUI/AirGUI.py", line 19, in <module>
from slicer import (
ImportError: cannot import name 'vtkMRMLPathPlannerTrajectoryNode' from 'slicer' (/opt/slicer/bin/Python/slicer/__init__.py)
[Qt] loadSourceAsModule - Failed to load file "/opt/air_ws/src/air-sandbox/src/slicer/AirIGT/AirGUI/AirGUI.py" as module "AirGUI" !
[Qt] Fail to instantiate module "AirGUI"
[Qt] The following modules failed to be instantiated:
[Qt] AirGUI
I import vtkMRMLPathPlannerTrajectoryNode
from PathExplorer for Parameter node typing:
from slicer import (
vtkMRMLMarkupsLineNode,
vtkMRMLNode,
vtkMRMLPathPlannerTrajectoryNode,
vtkMRMLScalarVolumeNode,
)
@parameterNodeWrapper
class AirGUIParameterNode:
inputPaths: vtkMRMLPathPlannerTrajectoryNode
Providing convent integration with nodeTypes & SlicerParameterName for the pathsSelector UI:
<widget class="qMRMLNodeComboBox" name="pathsSelector">
<property name="toolTip">
<string>Pick input paths.</string>
</property>
<property name="nodeTypes">
<stringlist notr="true">
<string>vtkMRMLPathPlannerTrajectoryNode</string>
</stringlist>
</property>
<property name="addEnabled">
<bool>false</bool>
</property>
<property name="removeEnabled">
<bool>false</bool>
</property>
<property name="SlicerParameterName" stdset="0">
<string>inputPaths</string>
</property>
</widget>
Perhaps this results from some race conditions or lazily loaded imports? I did try declaring my external extension dependencies and moving/delaying the offending imports to inside my AirGUIParameterNode
class as a work around for this limitation, but no dice.
class AirGUI(ScriptedLoadableModule):
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = _("Air GUI")
self.parent.categories = [translate("qSlicerAbstractCoreModule", "Wizards")]
self.parent.dependencies = [
"OpenIGTLinkIF",
"PathExplorer",
]
Any recommendation for scripted modules using vtkMRML
types from external C++ extentions?
Thanks!