Last active
February 3, 2022 23:57
-
-
Save mikebind/a3a4ee96076ab23d0e0339a47d02adfb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import os | |
import unittest | |
import vtk, qt, ctk, slicer | |
import SegmentStatistics | |
from slicer.ScriptedLoadableModule import * | |
from slicer.util import TESTING_DATA_URL | |
from slicer.util import VTKObservationMixin | |
class TestDebug2(ScriptedLoadableModule): | |
"""Uses ScriptedLoadableModule base class, available at: | |
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py | |
""" | |
def __init__(self, parent): | |
ScriptedLoadableModule.__init__(self, parent) | |
self.parent.title = "TestCheckbox" # TODO make this more human readable by adding spaces | |
self.parent.categories = ["Examples"] | |
self.parent.dependencies = [] | |
self.parent.contributors = ["John Doe (AnyWare Corp.)"] # replace with "Firstname Lastname (Organization)" | |
self.parent.helpText = """ | |
The Help text for this scripted module. | |
""" | |
self.parent.helpText += self.getDefaultModuleDocumentationLink() | |
self.parent.acknowledgementText = """ | |
The acknowledgementText | |
""" | |
# | |
# TestDebug2Widget | |
# | |
class TestDebug2Widget(ScriptedLoadableModuleWidget, VTKObservationMixin): | |
"""Uses ScriptedLoadableModuleWidget base class, available at: | |
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py | |
""" | |
def __init__(self, parent=None): | |
""" | |
Called when the user opens the module the first time and the widget is initialized. | |
""" | |
ScriptedLoadableModuleWidget.__init__(self, parent) | |
VTKObservationMixin.__init__(self) # needed for parameter node observation | |
self.logic = None | |
self._parameterNode = None | |
self._updatingGUIFromParameterNode = False | |
def setup(self): | |
ScriptedLoadableModuleWidget.setup(self) | |
# Instantiate and connect widgets ... | |
# | |
# Parameters Area | |
# | |
parametersCollapsibleButton = ctk.ctkCollapsibleButton() | |
parametersCollapsibleButton.text = "ROI" | |
self.layout.addWidget(parametersCollapsibleButton) | |
parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) | |
self.logic = TestDebug2Logic() | |
# | |
# input volume selector | |
# | |
self.inputSelector = slicer.qMRMLNodeComboBox() | |
self.inputSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"] | |
self.inputSelector.selectNodeUponCreation = True | |
self.inputSelector.addEnabled = False | |
self.inputSelector.removeEnabled = False | |
self.inputSelector.noneEnabled = False | |
self.inputSelector.showHidden = False | |
self.inputSelector.showChildNodeTypes = False | |
self.inputSelector.setMRMLScene(slicer.mrmlScene) | |
self.inputSelector.setToolTip( "Pick the input to the algorithm." ) | |
parametersFormLayout.addRow("Input Volume: ", self.inputSelector) | |
# | |
# ROI checkbox | |
# | |
self.ROICheckBox = ctk.ctkCheckBox() | |
self.ROICheckBox.enabled = True | |
self.ROICheckBox.checked = False | |
parametersFormLayout.addRow("ROI:", self.ROICheckBox) | |
# self.ROICheckBox.setMRMLVolumeNode(volNode) | |
self.addObserver(slicer.mrmlScene, slicer.mrmlScene.StartCloseEvent, self.onSceneStartClose) | |
self.addObserver(slicer.mrmlScene, slicer.mrmlScene.EndCloseEvent, self.onSceneEndClose) | |
# connections | |
self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onInputVolumeSelectorChange) | |
self.ROICheckBox.connect('clicked(bool)', self.onCheckBox) | |
self.initializeParameterNode() | |
# Add vertical spacer | |
self.layout.addStretch(1) | |
def onInputVolumeSelectorChange(self): | |
""" | |
Called when the input volume selector selection changes | |
""" | |
roiCheckedFlag = self.ROICheckBox.checked # true if ROI checkbox is checked | |
volRenLogic = slicer.modules.volumerendering.logic() | |
# Get new volume node | |
newVolNode = self.inputSelector.currentNode() | |
if newVolNode: | |
volRenDispNode = volRenLogic.GetFirstVolumeRenderingDisplayNode(newVolNode) | |
newROINode = volRenDispNode.GetROINode() | |
if newROINode: | |
newROIIsVisible = bool(newROINode.GetDisplayNode().GetVisibility()) | |
# Set checkbox based on current ROI visibility | |
self.ROICheckBox.checked = newROIIsVisible | |
# update parameter node | |
self.updateParameterNodeFromGUI() | |
def onCheckBox(self): | |
""" | |
Called when the checkbox is toggled | |
""" | |
VolumeNode = self._parameterNode.GetNodeReference('InputVolume') | |
if VolumeNode: | |
self.logic.updateROIOnVolume(VolumeNode, self.ROICheckBox.checked) | |
self.updateParameterNodeFromGUI() | |
def cleanup(self): | |
""" | |
Called when the application closes and the module widget is destroyed. | |
""" | |
self.removeObservers() | |
def enter(self): | |
""" | |
Called each time the user opens this module. | |
""" | |
# Make sure parameter node exists and observed | |
self.initializeParameterNode() | |
def exit(self): | |
""" | |
Called each time the user opens a different module. | |
""" | |
# Do not react to parameter node changes (GUI wlil be updated when the user enters into the module) | |
self.removeObserver(self._parameterNode, vtk.vtkCommand.ModifiedEvent, self.updateGUIFromParameterNode) | |
def onSceneStartClose(self, caller, event): | |
""" | |
Called just before the scene is closed. | |
""" | |
# Parameter node will be reset, do not use it anymore | |
self.setParameterNode(None) | |
def onSceneEndClose(self, caller, event): | |
""" | |
Called just after the scene is closed. | |
""" | |
# If this module is shown while the scene is closed then recreate a new parameter node immediately | |
if self.parent.isEntered: | |
self.initializeParameterNode() | |
def initializeParameterNode(self): | |
""" | |
Ensure parameter node exists and observed. | |
""" | |
# Parameter node stores all user choices in parameter values, node selections, etc. | |
# so that when the scene is saved and reloaded, these settings are restored. | |
self.setParameterNode(self.logic.getParameterNode()) | |
# Select default input nodes if nothing is selected yet to save a few clicks for the user | |
if not self._parameterNode.GetNodeReference("InputVolume"): | |
firstVolumeNode = slicer.mrmlScene.GetFirstNodeByClass("vtkMRMLScalarVolumeNode") | |
if firstVolumeNode: | |
self._parameterNode.SetNodeReferenceID("InputVolume", firstVolumeNode.GetID()) | |
def setParameterNode(self, inputParameterNode): | |
""" | |
Set and observe parameter node. | |
Observation is needed because when the parameter node is changed then the GUI must be updated immediately. | |
""" | |
# Unobserve previously selected parameter node and add an observer to the newly selected. | |
# Changes of parameter node are observed so that whenever parameters are changed by a script or any other module | |
# those are reflected immediately in the GUI. | |
if self._parameterNode is not None: | |
self.removeObserver(self._parameterNode, vtk.vtkCommand.ModifiedEvent, self.updateGUIFromParameterNode) | |
self._parameterNode = inputParameterNode | |
if self._parameterNode is not None: | |
self.addObserver(self._parameterNode, vtk.vtkCommand.ModifiedEvent, self.updateGUIFromParameterNode) | |
# Initial GUI update | |
self.updateGUIFromParameterNode() | |
def updateGUIFromParameterNode(self, caller=None, event=None): | |
""" | |
This method is called whenever parameter node is changed. | |
The module GUI is updated to show the current state of the parameter node. | |
""" | |
if self._parameterNode is None or self._updatingGUIFromParameterNode: | |
return | |
# Make sure GUI changes do not call updateParameterNodeFromGUI (it could cause infinite loop) | |
self._updatingGUIFromParameterNode = True | |
# Update node selectors and sliders | |
self.inputSelector.setCurrentNode(self._parameterNode.GetNodeReference("InputVolume")) | |
self.ROICheckBox.checked = (self._parameterNode.GetParameter("ROI") == "true") | |
# All the GUI updates are done | |
self._updatingGUIFromParameterNode = False | |
def updateParameterNodeFromGUI(self, caller=None, event=None): | |
""" | |
This method is called when the user makes any change in the GUI. | |
The changes are saved into the parameter node (so that they are restored when the scene is saved and loaded). | |
""" | |
if self._parameterNode is None or self._updatingGUIFromParameterNode: | |
return | |
wasModified = self._parameterNode.StartModify() # Modify all properties in a single batch | |
self._parameterNode.SetNodeReferenceID("InputVolume", self.inputSelector.currentNodeID) | |
self._parameterNode.SetParameter("ROI", "true" if self.ROICheckBox.checked else "false") | |
self._parameterNode.EndModify(wasModified) | |
# | |
# TestDebug2Logic | |
# | |
class TestDebug2Logic(ScriptedLoadableModuleLogic): | |
"""This class should implement all the actual | |
computation done by your module. The interface | |
should be such that other python code can import | |
this class and make use of the functionality without | |
requiring an instance of the Widget. | |
Uses ScriptedLoadableModuleLogic base class, available at: | |
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py | |
""" | |
def __init__(self): | |
""" | |
Called when the logic class is instantiated. Can be used for initializing member variables. | |
""" | |
ScriptedLoadableModuleLogic.__init__(self) | |
def updateROIOnVolume(self, VolumeNode, ROIchecked=False): | |
""" Controls visibility of the volume rendering ROI for the currently selected | |
input volume | |
""" | |
volRenDispNode = slicer.modules.volumerendering.logic().GetFirstVolumeRenderingDisplayNode(VolumeNode) | |
roiNode = volRenDispNode.GetROINode() | |
if ROIchecked: | |
roiNode.GetDisplayNode().SetVisibility(1) | |
else: | |
roiNode.GetDisplayNode().SetVisibility(0) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment