-
-
Save stevenagl12/4be9bcc382a9900182a5b7d5148e3a13 to your computer and use it in GitHub Desktop.
Scoliosis Module for Slicer
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
''' | |
Created on 28/03/2013 | |
@author: Usuario | |
''' | |
import os | |
from __main__ import vtk, qt, ctk, slicer | |
class ToolsViewer(): | |
''' | |
classdocs | |
''' | |
def __init__(self): | |
''' | |
Constructor | |
''' | |
self.notVisibleStyle ="background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #d55, stop: 0.1 #e66, stop: 0.49 #c44, stop: 0.5 #b33, stop: 1 #c44);" | |
self.visibleStyle = "background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5d5, stop: 0.1 #6e6, stop: 0.49 #4c4, stop: 0.5 #3b3, stop: 1 #4c4);" | |
self.noTrackingStyle = "background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ddd, stop: 0.1 #eee, stop: 0.49 #ccc, stop: 0.5 #bbb, stop: 1 #ccc);" | |
self.toolsWidget = qt.QFrame() | |
self.toolsWidget.setLayout( qt.QHBoxLayout() ) | |
# stylus semaphore | |
self.stylusSemaphore=qt.QPushButton() | |
self.stylusSemaphore.setEnabled(False) | |
self.stylusSemaphore.setStyleSheet(self.noTrackingStyle) | |
self.stylusSemaphore.setText("Stylus") | |
# probe semaphore | |
self.probeSemaphore=qt.QPushButton() | |
self.probeSemaphore.setEnabled(False) | |
self.probeSemaphore.setStyleSheet(self.noTrackingStyle) | |
self.probeSemaphore.setText("Probe") | |
# main reference semaphore | |
self.mainReferenceSemaphore=qt.QPushButton() | |
self.mainReferenceSemaphore.setEnabled(False) | |
self.mainReferenceSemaphore.setStyleSheet(self.noTrackingStyle) | |
self.mainReferenceSemaphore.setText("R1") | |
# second referencer semaphore | |
self.secondReferenceSemaphore=qt.QPushButton() | |
self.secondReferenceSemaphore.setEnabled(False) | |
self.secondReferenceSemaphore.setStyleSheet(self.noTrackingStyle) | |
self.secondReferenceSemaphore.setText("R2") | |
# third referencer semaphore | |
self.thirdReferenceSemaphore=qt.QPushButton() | |
self.thirdReferenceSemaphore.setEnabled(False) | |
self.thirdReferenceSemaphore.setStyleSheet(self.noTrackingStyle) | |
self.thirdReferenceSemaphore.setText("R3") | |
# wall semaphore | |
self.wallSemaphore=qt.QPushButton() | |
self.wallSemaphore.setEnabled(False) | |
self.wallSemaphore.setStyleSheet(self.noTrackingStyle) | |
self.wallSemaphore.setText("Wall") | |
self.toolsWidget.layout().addWidget(self.stylusSemaphore) | |
self.toolsWidget.layout().addWidget(self.probeSemaphore) | |
self.toolsWidget.layout().addWidget(self.mainReferenceSemaphore) | |
self.toolsWidget.layout().addWidget(self.secondReferenceSemaphore) | |
self.toolsWidget.layout().addWidget(self.thirdReferenceSemaphore) | |
self.toolsWidget.layout().addWidget(self.wallSemaphore) | |
print("Constructor of ToolViewer executed") | |
self.toolsWidget.show() | |
def getToolsWidget(self): | |
return self.toolsWidget | |
def setModuleLogic(self,logic): | |
self.logic=logic | |
# def listenToScene(self): | |
# igtl=slicer.modules.openigtlinkif | |
# logic=igtl.logic() | |
# logic.SetMRMLScene(slicer.mrmlScene) | |
# #self.connectorNode=self.logic.getConnectorNode() | |
# logic.AddObserver('ModifiedEvent',self.onConnectedEventCaptured) | |
# def onConnectedEventCaptured(self, caller, event): | |
# print("An OpenIGTLink connection was captured!") | |
# igtlConnectorNode = slicer.util.getNode("Plus Server Connection") | |
# if igtlConnectorNode is not None: | |
# self.startListeningToTransformationsModifications() | |
def startListeningToTransformationsModifications(self): | |
print("Tools viewer is listening to the scene") | |
referenceToTrackerNode = slicer.util.getNode("ReferenceToTracker") | |
referenceToTrackerNode.RemoveAllObservers() | |
#if referenceToTrackerNode is not None: | |
# self.onReferenceTransformationModified() | |
referenceToTrackerNode.AddObserver('ModifiedEvent', self.onReferenceTransformationModified) | |
r2ToTrackerNode = slicer.util.getNode("R2ToTracker") | |
r2ToTrackerNode.RemoveAllObservers() | |
r2ToTrackerNode.AddObserver('ModifiedEvent', self.onR2TransformationModified) | |
r3ToTrackerNode = slicer.util.getNode("R3ToTracker") | |
r3ToTrackerNode.RemoveAllObservers() | |
r3ToTrackerNode.AddObserver('ModifiedEvent', self.onR3TransformationModified) | |
probeToReference = slicer.util.getNode("ProbeToReference") | |
probeToReference.RemoveAllObservers() | |
#if probeToReference is not None: | |
# self.onProbeTransformationModified() | |
probeToReference.AddObserver('ModifiedEvent', self.onProbeTransformationModified) | |
stylusToReference = slicer.util.getNode("StylusTipToReference") | |
stylusToReference.RemoveAllObservers() | |
#if stylusToReference is not None: | |
# self.onStylusTransformationModified() | |
stylusToReference.AddObserver('ModifiedEvent', self.onStylusTransformationModified) | |
wallToTracker = slicer.util.getNode("WallToTracker") | |
wallToTracker.RemoveAllObservers() | |
wallToTracker.AddObserver('ModifiedEvent', self.onWallTransformationModified) | |
stylusModelNode=self.logic.getStylusModel() | |
self.stylusModelDisplayNode=stylusModelNode.GetDisplayNode() | |
self.stylusModelDisplayNode.SetVisibility(False) | |
def onReferenceTransformationModified(self, caller, event): | |
if self.logic.isValidTransformation("ReferenceToTracker"): | |
self.mainReferenceSemaphore.setStyleSheet(self.visibleStyle) | |
else: | |
self.mainReferenceSemaphore.setStyleSheet(self.notVisibleStyle) | |
def onR2TransformationModified(self, caller, event): | |
if self.logic.isValidTransformation("R2ToTracker"): | |
self.secondReferenceSemaphore.setStyleSheet(self.visibleStyle) | |
else: | |
self.secondReferenceSemaphore.setStyleSheet(self.notVisibleStyle) | |
def onR3TransformationModified(self, caller, event): | |
if self.logic.isValidTransformation("R3ToTracker"): | |
self.thirdReferenceSemaphore.setStyleSheet(self.visibleStyle) | |
else: | |
self.thirdReferenceSemaphore.setStyleSheet(self.notVisibleStyle) | |
def onWallTransformationModified(self, caller, event): | |
if self.logic.isValidTransformation("WallToTracker"): | |
self.wallSemaphore.setStyleSheet(self.visibleStyle) | |
self.logic.setTrackerToWallTransformationMatrix() | |
else: | |
self.wallSemaphore.setStyleSheet(self.notVisibleStyle) | |
def onProbeTransformationModified(self, caller, event): | |
if self.logic.isValidTransformation("ProbeToReference"): | |
self.probeSemaphore.setStyleSheet(self.visibleStyle) | |
self.logic.showRedSliceIn3D(True) | |
#print("Probe Transformation is valid!!") | |
else: | |
self.probeSemaphore.setStyleSheet(self.notVisibleStyle) | |
#slicer.util.resetSliceViews() | |
self.logic.showRedSliceIn3D(False) | |
#print("Probe Transformation is invalid!!") | |
def onStylusTransformationModified(self, caller, event): | |
if self.logic.isValidTransformation("StylusTipToReference"): | |
self.stylusSemaphore.setStyleSheet(self.visibleStyle) | |
self.stylusModelDisplayNode.SetVisibility(True) | |
else: | |
self.stylusSemaphore.setStyleSheet(self.notVisibleStyle) | |
self.stylusModelDisplayNode.SetVisibility(False) | |
def listenToTransformationsSentToTheScene(self): | |
self.sceneObserver = slicer.mrmlScene.AddObserver('ModifiedEvent', self.onTransformationsSentToTheScene) | |
def doNotListenToTransformationsSentToTheScene(self): | |
slicer.mrmlScene.RemoveObserver(self.sceneObserver) | |
def onTransformationsSentToTheScene(self, caller, event): | |
image_Reference = slicer.util.getNode("Image_Reference") | |
if image_Reference is not None: | |
self.doNotListenToTransformationsSentToTheScene() | |
self.logic.associateTransformations() | |
self.startListeningToTransformationsModifications() | |
slicer.util.resetSliceViews() | |
slicer.util.resetThreeDViews() | |
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
''' | |
Created on 28/03/2013 | |
@author: Usuario | |
''' | |
import os | |
from VolumeRenderingPropertiesMenu import * | |
from __main__ import vtk, qt, ctk, slicer | |
class VolumeRenderingViewer(): | |
''' | |
classdocs | |
''' | |
def __init__(self): | |
''' | |
Constructor | |
''' | |
""" | |
path=slicer.modules.usguidedprocedure.path | |
modulePath=os.path.dirname(path) | |
loadedDataGUIfile=os.path.join(modulePath,"USGuidedWizard/loadedData.ui") | |
f = qt.QFile(loadedDataGUIfile) | |
#f = qt.QFile('C:/Users/Usuario/devel/slicelets/USGuidedProcedure/USGuidedWizard/fiducials.ui') | |
f.open(qt.QFile.ReadOnly) | |
loader = qt.QUiLoader() | |
self.loadedDataWidget = loader.load(f) | |
f.close() | |
""" | |
self.volumesFrame= qt.QFrame() | |
self.volumesFrame.setLayout(qt.QHBoxLayout()) | |
self.volumesFrameLayout=self.volumesFrame.layout() | |
self.listWidget = qt.QListWidget() | |
self.renderingLabel=qt.QLabel("Renderings:") | |
print("Constructor of VolumeRenderingViewer executed") | |
#self.listWidget.show() | |
self.currentItem=None | |
self.volumeButtonsFrame=qt.QFrame() | |
self.volumeButtonsFrame.setLayout(qt.QVBoxLayout()) | |
self.volumeButtonsLayout=self.volumeButtonsFrame.layout() | |
self.showVolumeRenderingButton = qt.QPushButton("Show") | |
self.showVolumeRenderingButton.toolTip = "Show the volume rendering" | |
self.showVolumeRenderingButton.setEnabled(False) | |
self.showVolumeRenderingButton.connect('clicked(bool)', self.onShowVolumeRenderingButtonClicked) | |
self.hideVolumeRenderingButton = qt.QPushButton("Hide") | |
self.hideVolumeRenderingButton.toolTip = "Hide the volume rendering" | |
self.hideVolumeRenderingButton.setEnabled(False) | |
self.hideVolumeRenderingButton.connect('clicked(bool)', self.onHideVolumeRenderingButtonClicked) | |
self.modifyVolumeRenderingButton = qt.QPushButton("Modify") | |
self.modifyVolumeRenderingButton.toolTip = "Modify the properties of the volume rendering" | |
self.modifyVolumeRenderingButton.setEnabled(False) | |
self.modifyVolumeRenderingButton.connect('clicked(bool)', self.onModifyVolumeRenderingButtonClicked) | |
self.volumeButtonsLayout.addWidget(self.renderingLabel ) | |
self.volumeButtonsLayout.addWidget(self.showVolumeRenderingButton) | |
self.volumeButtonsLayout.addWidget(self.hideVolumeRenderingButton) | |
self.volumeButtonsLayout.addWidget(self.modifyVolumeRenderingButton) | |
self.volumesFrameLayout.addWidget(self.listWidget) | |
self.volumesFrameLayout.addWidget(self.volumeButtonsFrame) | |
self.volumeRenderingPropertiesMenu = VolumeRenderingPropertiesMenu() | |
self.volumeRenderingPropertiesMenu.threshold.connect('valuesChanged(double,double)', self.onThresholdSliderMoved) | |
self.volumeRenderingPropertiesMenu.colorRangeSlider.connect('valuesChanged(double,double)', self.onColorSliderMoved) | |
self.volumeRenderingPropertiesMenu.checkBoxVisible3D.connect("stateChanged(int)",self.onVisible3DChanged) | |
self.scalarRange = [0., 255.] | |
def getVolumeRenderingViewerWidget(self): | |
return self.volumesFrame | |
def setModuleLogic(self,logic): | |
self.logic=logic | |
def listenToScene(self): | |
vr=slicer.modules.volumerendering | |
vrl=vr.logic() | |
vrl.SetMRMLScene(slicer.mrmlScene) | |
self.sceneObserver = vrl.AddObserver('ModifiedEvent', self.onVolumeRenderingAdded) | |
#self.sceneObserver = slicer.mrmlScene.AddObserver('ModifiedEvent', self.onVolumeAdded) | |
def onVolumeRenderingAdded(self, caller, event): | |
print("A volume rendering was modified") | |
self.showVolumeRenderingButton.setEnabled(True) | |
self.hideVolumeRenderingButton.setEnabled(True) | |
self.modifyVolumeRenderingButton.setEnabled(True) | |
numVolumes=slicer.mrmlScene.GetNumberOfNodesByClass("vtkMRMLScalarVolumeNode") | |
print("Number of volumes: " + str(numVolumes)) | |
#print('A model was added to the scene !') | |
if numVolumes>0: | |
for i in xrange(0,numVolumes): | |
node = slicer.mrmlScene.GetNthNodeByClass(i, "vtkMRMLScalarVolumeNode") | |
if not (node==None): | |
if (not (node.GetName() == "Image_Reference")): | |
print(node.GetName()) | |
isAlreadyInList=False | |
j=0 | |
while ((j < self.listWidget.count) and (not isAlreadyInList)): | |
isAlreadyInList=node.GetName()+"Rendering"==self.listWidget.item(j).text() | |
j=j+1 | |
if not isAlreadyInList: | |
print('A volume rendering was added to the scene !') | |
self.listWidget.addItem(node.GetName()+"Rendering") | |
def addItem(self,item): | |
self.listWidget.addItem(item) | |
def onShowVolumeRenderingButtonClicked(self): | |
item = self.listWidget.currentItem() | |
if item==None: | |
ret=qt.QMessageBox.warning(self.listWidget, 'Volume Rendering List', 'You must select a volume rendering to show.', qt.QMessageBox.Ok , qt.QMessageBox.Ok ) | |
return | |
vrDisplayNode=slicer.util.getNode(item.text()) | |
if vrDisplayNode.GetVisibility()==True: | |
vrDisplayNode.SetVisibility(False) | |
vrDisplayNode.SetVisibility(True) | |
def onHideVolumeRenderingButtonClicked(self): | |
item = self.listWidget.currentItem() | |
if item==None: | |
ret=qt.QMessageBox.warning(self.listWidget, 'Volume Rendering List', 'You must select a volume rendering to show.', qt.QMessageBox.Ok , qt.QMessageBox.Ok ) | |
return | |
vrDisplayNode=slicer.util.getNode(item.text()) | |
vrDisplayNode.SetVisibility(False) | |
def onModifyVolumeRenderingButtonClicked(self): | |
item = self.listWidget.currentItem() | |
if item==None: | |
ret=qt.QMessageBox.warning(self.listWidget, 'Volume Rendering List', 'You must select a volume rendering to show.', qt.QMessageBox.Ok , qt.QMessageBox.Ok ) | |
return | |
vrDisplayNode=slicer.util.getNode(item.text()) | |
self.currentVolumeRendering=vrDisplayNode | |
self.volumeRenderingPropertiesMenu.show() | |
def onRemoveActionTriggered(self): | |
item = self.listWidget.currentItem() | |
node=slicer.util.getNode(item.text()) | |
node=slicer.vtkMRMLModelNode.SafeDownCast(node) | |
currentDisplayNode=node.GetDisplayNode() | |
slicer.mrmlScene.RemoveNode(currentDisplayNode) | |
slicer.mrmlScene.RemoveNode(node) | |
# Delete the item | |
self.listWidget.takeItem(self.listWidget.row(item)) | |
def onThresholdSliderMoved(self,minValue,maxValue): | |
# Get the current display node | |
print("Opacity Slider movement captured!") | |
#print(opacity) | |
volumePropertyNode=self.currentVolumeRendering.GetVolumePropertyNode() | |
scalarOpacity=volumePropertyNode.GetScalarOpacity() | |
scalarOpacity.RemoveAllPoints() | |
scalarOpacity.AddPoint(self.scalarRange[0], 0.) | |
scalarOpacity.AddPoint(minValue, 0.) | |
scalarOpacity.AddPoint(maxValue, 1.) | |
scalarOpacity.AddPoint(self.scalarRange[1], 1.) | |
#colorTransfer=volumePropertyNode.GetColor() | |
def onColorSliderMoved(self,minValue,maxValue): | |
# Get the current display node | |
print("Color Slider movement captured!") | |
#print(opacity) | |
volumePropertyNode=self.currentVolumeRendering.GetVolumePropertyNode() | |
colorTransfer=volumePropertyNode.GetColor() | |
colorTransfer.RemoveAllPoints() | |
black = [0., 0., 0.] | |
white = [1., 1., 1.] | |
colorTransfer.AddRGBPoint(self.scalarRange[0], black[0], black[1], black[2]) | |
colorTransfer.AddRGBPoint(minValue, black[0], black[1], black[2]) | |
colorTransfer.AddRGBPoint(maxValue, white[0], white[1], white[2]); | |
colorTransfer.AddRGBPoint(self.scalarRange[1], white[0], white[1], white[2]); | |
def onVisible3DChanged(self,isVisible): | |
#print(isVisible) | |
self.currentVolumeRendering.SetVisibility(isVisible) |
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
''' | |
Created on 28/03/2013 | |
@author: Usuario | |
''' | |
import os | |
from __main__ import vtk, qt, ctk, slicer | |
class VolumesViewer(): | |
''' | |
classdocs | |
''' | |
def __init__(self): | |
''' | |
Constructor | |
''' | |
""" | |
path=slicer.modules.usguidedprocedure.path | |
modulePath=os.path.dirname(path) | |
loadedDataGUIfile=os.path.join(modulePath,"USGuidedWizard/loadedData.ui") | |
f = qt.QFile(loadedDataGUIfile) | |
#f = qt.QFile('C:/Users/Usuario/devel/slicelets/USGuidedProcedure/USGuidedWizard/fiducials.ui') | |
f.open(qt.QFile.ReadOnly) | |
loader = qt.QUiLoader() | |
self.loadedDataWidget = loader.load(f) | |
f.close() | |
""" | |
self.volumesFrame= qt.QFrame() | |
self.volumesFrame.setLayout(qt.QHBoxLayout()) | |
self.volumesFrameLayout=self.volumesFrame.layout() | |
self.listWidget = qt.QListWidget() | |
self.volumesLabel=qt.QLabel("Volumes:") | |
print("Constructor of VolumeRenderingViewer executed") | |
#self.listWidget.show() | |
self.currentItem=None | |
self.volumeButtonsFrame=qt.QFrame() | |
self.volumeButtonsFrame.setLayout(qt.QVBoxLayout()) | |
self.volumeButtonsLayout=self.volumeButtonsFrame.layout() | |
self.exploreVolumeButton = qt.QPushButton("Explore") | |
self.exploreVolumeButton.toolTip = "Show the selected volume" | |
self.exploreVolumeButton.setEnabled(False) | |
self.exploreVolumeButton.connect('clicked(bool)', self.onExploreVolumeClicked) | |
self.hideVolumeButton = qt.QPushButton("Hide") | |
self.hideVolumeButton.toolTip = "Hide the volume" | |
self.hideVolumeButton.setEnabled(False) | |
self.hideVolumeButton.connect('clicked(bool)', self.onHideVolumeClicked) | |
self.resliceVolumeButton = qt.QPushButton("Reslice") | |
self.resliceVolumeButton.toolTip = "Reslice the volume with a driver" | |
self.resliceVolumeButton.setEnabled(False) | |
self.resliceVolumeButton.connect('clicked(bool)', self.onResliceVolumeClicked) | |
self.volumeButtonsLayout.addWidget(self.volumesLabel) | |
self.volumeButtonsLayout.addWidget(self.exploreVolumeButton) | |
self.volumeButtonsLayout.addWidget(self.hideVolumeButton) | |
self.volumeButtonsLayout.addWidget(self.resliceVolumeButton) | |
self.volumesFrameLayout.addWidget(self.listWidget) | |
self.volumesFrameLayout.addWidget(self.volumeButtonsFrame) | |
def getVolumesViewerWidget(self): | |
return self.volumesFrame | |
def setModuleLogic(self,logic): | |
self.logic=logic | |
def listenToScene(self): | |
vl=slicer.modules.volumes | |
vl=vl.logic() | |
vl.SetMRMLScene(slicer.mrmlScene) | |
self.sceneObserver = vl.AddObserver('ModifiedEvent', self.onVolumeAdded) | |
#self.sceneObserver = slicer.mrmlScene.AddObserver('ModifiedEvent', self.onVolumeAdded) | |
def onVolumeAdded(self, caller, event): | |
print("Volumes module was modified") | |
numVolumes=slicer.mrmlScene.GetNumberOfNodesByClass("vtkMRMLScalarVolumeNode") | |
print("Number of volumes: " + str(numVolumes)) | |
#print('A model was added to the scene !') | |
if numVolumes>0: | |
for i in xrange(0,numVolumes): | |
node = slicer.mrmlScene.GetNthNodeByClass(i, "vtkMRMLScalarVolumeNode") | |
if not (node==None): | |
if (not (node.GetName() == "Image_Reference")): | |
print(node.GetName()) | |
isAlreadyInList=False | |
j=0 | |
while ((j < self.listWidget.count) and (not isAlreadyInList)): | |
isAlreadyInList=node.GetName()==self.listWidget.item(j).text() | |
j=j+1 | |
if not isAlreadyInList: | |
print('A volume was added to the scene !') | |
self.listWidget.addItem(node.GetName()) | |
node=slicer.util.getNode(node.GetName()) | |
node=slicer.vtkMRMLScalarVolumeNode.SafeDownCast(node) | |
self.logic.onVolumeAdded(node) | |
self.exploreVolumeButton.setEnabled(True) | |
self.hideVolumeButton.setEnabled(True) | |
self.resliceVolumeButton.setEnabled(True) | |
#print("Info of added node:") | |
def addItem(self,item): | |
self.listWidget.addItem(item) | |
def onExploreVolumeClicked(self): | |
print("Explore volume button clicked") | |
item = self.listWidget.currentItem() | |
if item==None: | |
ret=qt.QMessageBox.warning(self.listWidget, 'Volumes List', 'You must select a volume to explore.', qt.QMessageBox.Ok , qt.QMessageBox.Ok ) | |
return | |
node=slicer.util.getNode(item.text()) | |
self.logic.disconnectDriverForSlice() | |
self.logic.showReconstructedVolume(node.GetName()) | |
def onHideVolumeClicked(self): | |
self.logic.showRedSliceIn3D(True) | |
greenWidgetCompNode=slicer.mrmlScene.GetNodeByID("vtkMRMLSliceCompositeNodeGreen") | |
greenWidgetCompNode.SetBackgroundVolumeID(None) | |
yellowWidgetCompNode=slicer.mrmlScene.GetNodeByID("vtkMRMLSliceCompositeNodeYellow") | |
yellowWidgetCompNode.SetBackgroundVolumeID(None) | |
def onResliceVolumeClicked(self): | |
print("Reslice volume button clicked") | |
item = self.listWidget.currentItem() | |
if item==None: | |
ret=qt.QMessageBox.warning(self.listWidget, 'Volumes List', 'You must select a volume to reslice.', qt.QMessageBox.Ok , qt.QMessageBox.Ok ) | |
return | |
node=slicer.util.getNode(item.text()) | |
self.logic.disconnectDriverForSlice() | |
self.logic.showRedSliceIn3D(True) | |
self.logic.resliceVolumeWithDriver(node) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment