Created
June 19, 2017 03:00
-
-
Save patmo141/1878acf70d45e4048699417a1238f053 to your computer and use it in GitHub Desktop.
Slicer Scripted Module for Undercut Removal
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
from __main__ import vtk, qt, ctk, slicer | |
import os | |
import math | |
class ModelUndercutRemoval: | |
def __init__(self, parent): | |
parent.title = "Model Undercut Removal" | |
parent.categories = ["Examples"] | |
parent.dependencies = [] | |
parent.contributors = ["Patrick Moore"] # replace with "Firstname Lastname (Org)" | |
parent.helpText = """ | |
Example of scripted loadable extension for the HelloPython tutorial. | |
""" | |
parent.acknowledgementText = """Independently developed for the good of the world""" # replace with organization, grant and thanks. | |
self.parent = parent | |
# | |
# qHelloPythonWidget | |
# | |
class ModelUndercutRemovalWidget: | |
def __init__(self, parent = None): | |
if not parent: | |
self.parent = slicer.qMRMLWidget() | |
self.parent.setLayout(qt.QVBoxLayout()) | |
self.parent.setMRMLScene(slicer.mrmlScene) | |
else: | |
self.parent = parent | |
self.layout = self.parent.layout() | |
if not parent: | |
self.setup() | |
self.parent.show() | |
def setup(self): | |
# Instantiate and connect widgets ... | |
# Collapsible button | |
self.sampleCollapsibleButton = ctk.ctkCollapsibleButton() | |
self.sampleCollapsibleButton.text = "A collapsible button" | |
self.layout.addWidget(self.sampleCollapsibleButton) | |
# Layout within the sample collapsible button | |
self.sampleFormLayout = qt.QFormLayout(self.sampleCollapsibleButton) | |
# HelloWorld button | |
helloWorldButton = qt.QPushButton("Remove Undercuts") | |
helloWorldButton.toolTip = "Print 'Hello world' in standard output." | |
self.sampleFormLayout.addWidget(helloWorldButton) | |
helloWorldButton.connect('clicked(bool)', self.onHelloWorldButtonClicked) | |
# Add vertical spacer | |
self.layout.addStretch(1) | |
#Input Model | |
# the volume selectors | |
self.inputFrame = qt.QFrame(self.sampleCollapsibleButton) | |
self.inputFrame.setLayout(qt.QHBoxLayout()) | |
self.sampleFormLayout.addWidget(self.inputFrame) | |
self.inputSelector = qt.QLabel("Input Model: ", self.inputFrame) | |
self.inputFrame.layout().addWidget(self.inputSelector) | |
self.inputSelector = slicer.qMRMLNodeComboBox(self.inputFrame) | |
self.inputSelector.nodeTypes = ( ("vtkMRMLModelNode"), "" ) | |
self.inputSelector.addEnabled = False | |
self.inputSelector.removeEnabled = False | |
self.inputSelector.setMRMLScene( slicer.mrmlScene ) | |
self.inputFrame.layout().addWidget(self.inputSelector) | |
# Set local var as instance attribute | |
self.helloWorldButton = helloWorldButton | |
#TODO, slice Z thickness | |
#TODO, slice X,Y thickness | |
def onHelloWorldButtonClicked(self): | |
scene = slicer.mrmlScene | |
inputModel = self.inputSelector.currentNode() | |
bounds = [0,0,0,0,0,0] | |
inputModel.GetBounds(bounds) | |
X = bounds[1] - bounds[0] | |
Y = bounds[3] - bounds[2] | |
Z = bounds[5] - bounds[4] | |
mid = (bounds[0] + X/2, bounds[2] + Y/2, bounds[4] + Z/2) | |
X_thick = .1 #TODO resolution input | |
Y_thick = .1 #TODO resolution input | |
Z_thick = .1 #TODO resolution input | |
z_slices = int(math.ceil(Z/Z_thick)) | |
y_slices = int(math.ceil(Y/Y_thick)) | |
x_slices = int(math.ceil(X/X_thick)) | |
x_thick = X/x_slices | |
y_thick = Y/y_slices | |
z_thick = Z/z_slices | |
imageSize=[x_slices, y_slices, z_slices] | |
imageSpacing=[x_thick, y_thick, z_thick] | |
voxelType=vtk.VTK_UNSIGNED_CHAR | |
imageData=vtk.vtkImageData() | |
imageData.SetDimensions(imageSize) | |
imageData.AllocateScalars(voxelType, 1) | |
thresholder=vtk.vtkImageThreshold() | |
thresholder.SetInputData(imageData) | |
thresholder.SetInValue(1) | |
thresholder.SetOutValue(1) | |
# Create volume node | |
volumeNode=slicer.vtkMRMLScalarVolumeNode() | |
volumeNode.SetSpacing(imageSpacing) | |
volumeNode.SetImageDataConnection(thresholder.GetOutputPort()) | |
# Add volume to scene | |
slicer.mrmlScene.AddNode(volumeNode) | |
displayNode=slicer.vtkMRMLScalarVolumeDisplayNode() | |
slicer.mrmlScene.AddNode(displayNode) | |
colorNode = slicer.util.getNode('Grey') | |
displayNode.SetAndObserveColorNodeID(colorNode.GetID()) | |
volumeNode.SetAndObserveDisplayNodeID(displayNode.GetID()) | |
volumeNode.CreateDefaultStorageNode() | |
#Transform the Volume to Fit Around the Model | |
transform = slicer.vtkMRMLLinearTransformNode() | |
scene.AddNode(transform) | |
volumeNode.SetAndObserveTransformNodeID(transform.GetID()) | |
vTransform = vtk.vtkTransform() | |
vTransform.Translate((-X/2 + mid[0], -Y/2 + mid[1], -Z/2 + mid[2])) | |
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment