|
| 1 | +""" |
| 2 | +This example shows how to create a custom volume rendering for a volume node using the SlicerLayerDisplayableManager |
| 3 | +extension. |
| 4 | +
|
| 5 | +It goes over the following concepts: |
| 6 | + - Creates a VR display pipeline on a selected volume node in the scene |
| 7 | + - Register the pipeline creation mechanism |
| 8 | +
|
| 9 | +Usage: |
| 10 | + This example is implemented as a scripted module and can be added as such to Slicer. |
| 11 | + Due to import order considerations, the pipeline code is lazy loaded from the CustomVRLib python package. |
| 12 | +""" |
| 13 | + |
| 14 | +import qt |
| 15 | +import slicer |
| 16 | +from slicer.ScriptedLoadableModule import ScriptedLoadableModule, ScriptedLoadableModuleWidget |
| 17 | + |
| 18 | + |
| 19 | +class CustomVR(ScriptedLoadableModule): |
| 20 | + def __init__(self, parent): |
| 21 | + ScriptedLoadableModule.__init__(self, parent) |
| 22 | + self.parent.title = "Custom VR Pipeline Example" |
| 23 | + self.parent.categories = ["qSlicerAbstractCoreModule", "Examples"] |
| 24 | + self.parent.dependencies = [] |
| 25 | + self.parent.contributors = [] |
| 26 | + self.parent.helpText = "" |
| 27 | + self.parent.acknowledgementText = "" |
| 28 | + |
| 29 | + |
| 30 | +class CustomVRWidget(ScriptedLoadableModuleWidget): |
| 31 | + """ |
| 32 | + In this example, we will display a custom volume rendering and use VTK compute shader for processing the volume. |
| 33 | + To avoid initialization problems, the pipeline registration is done lazily during the setup. |
| 34 | + """ |
| 35 | + |
| 36 | + def setup(self) -> None: |
| 37 | + from CustomVRLib import registerPipeline |
| 38 | + |
| 39 | + registerPipeline() |
| 40 | + ScriptedLoadableModuleWidget.setup(self) |
| 41 | + |
| 42 | + widget = qt.QWidget() |
| 43 | + layout = qt.QVBoxLayout(widget) |
| 44 | + |
| 45 | + # Configure volume selector node |
| 46 | + self._volumeNodeSelector = slicer.qMRMLNodeComboBox(widget) |
| 47 | + self._volumeNodeSelector.nodeTypes = ["vtkMRMLVolumeNode"] |
| 48 | + self._volumeNodeSelector.selectNodeUponCreation = True |
| 49 | + self._volumeNodeSelector.addEnabled = False |
| 50 | + self._volumeNodeSelector.removeEnabled = False |
| 51 | + self._volumeNodeSelector.showHidden = False |
| 52 | + self._volumeNodeSelector.renameEnabled = True |
| 53 | + self._volumeNodeSelector.setMRMLScene(slicer.mrmlScene) |
| 54 | + layout.addWidget(self._volumeNodeSelector) |
| 55 | + |
| 56 | + # Configure toggle button |
| 57 | + toggleDisplayButton = qt.QPushButton("Toggle display") |
| 58 | + toggleDisplayButton.clicked.connect(self._toggleVolumeDisplay) |
| 59 | + layout.addWidget(toggleDisplayButton) |
| 60 | + layout.addStretch() |
| 61 | + |
| 62 | + self.layout.addWidget(widget) |
| 63 | + |
| 64 | + def _toggleVolumeDisplay(self, *_): |
| 65 | + from CustomVRLib import CustomVRPipeline |
| 66 | + |
| 67 | + volumeNode = self._volumeNodeSelector.currentNode() |
| 68 | + if not volumeNode: |
| 69 | + return |
| 70 | + |
| 71 | + wasVisible = CustomVRPipeline.GetVRNodeVisibility(volumeNode, slicer.mrmlScene) |
| 72 | + vrNode = CustomVRPipeline.CreateVRNode(volumeNode, slicer.mrmlScene) |
| 73 | + CustomVRPipeline.SetVRNodeVisible(vrNode, not wasVisible) |
| 74 | + |
| 75 | + def onReload(self): |
| 76 | + """ |
| 77 | + Customization of reload to allow reloading of the CustomVRLib files. |
| 78 | + """ |
| 79 | + import importlib |
| 80 | + |
| 81 | + packageName = "CustomVRLib" |
| 82 | + submodules = ["CustomVRPipeline"] |
| 83 | + |
| 84 | + # Reload the package |
| 85 | + module = importlib.import_module(packageName) |
| 86 | + importlib.reload(module) |
| 87 | + |
| 88 | + # Reload submodules |
| 89 | + for sub in submodules: |
| 90 | + fullName = f"{packageName}.{sub}" |
| 91 | + submodule = importlib.import_module(fullName) |
| 92 | + importlib.reload(submodule) |
| 93 | + |
| 94 | + ScriptedLoadableModuleWidget.onReload(self) |
0 commit comments