import sys
import slicer
if not 'sphinx' in sys.modules:
import ctk
import vtk
import SimpleITK as sitk
## This assumes that you have already loaded the 'MRHead1' data from the informatics module.
[docs]def GetSlicerITKReadWriteAddress( NodeName ):
""" This function will return the ITK FileIO formatted text address
so that the image can be read directly from the MRML scene
"""
#nodesList = slicer.util.getNodes('*vtkMRMLScalarVolumeNode*')
myNode = slicer.util.getNode(NodeName)
myNodeSceneAddress = myNode.GetScene().GetAddressAsString("").replace('Addr=','')
myNodeSceneID = myNode.GetID()
myNodeFullITKAddress = 'slicer:' + myNodeSceneAddress + '#' + myNodeSceneID
return myNodeFullITKAddress
[docs]def CloneSlicerNode( NodeName, NewNodeNamePrefix ):
""" Create a new node in slicer by cloning from an exising node.
"""
n = slicer.util.getNode(NodeName)
vl = slicer.modules.volumes.logic()
newvol = vl.CloneVolume(slicer.mrmlScene,n,NewNodeNamePrefix)
return newvol.GetName()
__sitk__VOLUME_TYPES__ = [ 'Scalar' ]
[docs]def checkVolumeNodeType(nodeType):
""" Raise an error if the node type is not a recognized volume node.
"""
volume_type = nodeType.rsplit('VolumeNode')[0].split('vtkMRML')[1]
if volume_type not in __sitk__VOLUME_TYPES__:
raise ValueError('Volume type %s is not valid' % volume_type )
[docs]def CreateNewVolumeNode(nodeName, nodeType='vtkMRMLScalarVolumeNode', overwrite=False):
""" Create a new volume node from scratch.
"""
scene = slicer.mrmlScene
checkVolumeNodeType(nodeType)
newNode = scene.CreateNodeByClass(nodeType)
newNode.UnRegister(scene)
AddNodeToMRMLScene(newNode, nodeName, overwrite)
return newNode
[docs]def CreateNewDisplayNode(nodeName='default'):
""" Create a new display node from scratch.
"""
scene = slicer.mrmlScene
nodeType='vtkMRMLScalarVolumeDisplayNode'
newNode = scene.CreateNodeByClass(nodeType)
newNode.UnRegister(scene)
AddNodeToMRMLScene(newNode, nodeName + '_Display', False)
return newNode
[docs]def removeOldMRMLNode(node):
""" Overwrite a MRML node with the same name and class as the given node.
"""
scene = slicer.mrmlScene
collection = scene.GetNodesByClassByName(node.GetClassName(), node.GetName())
if collection.GetNumberOfItems() == 1:
oldNode = collection.GetItemAsObject(0)
scene.RemoveNode(oldNode)
elif collection.GetNumberOfItems() > 1:
# This should never happen
raise Exception("Too many existing nodes in MRML Scene: Unable to determine node to replace!")
else:
# There was no node to overwrite
return 1
return 0
[docs]def AddNodeToMRMLScene(newNode, nodeName='default', overwrite=False):
scene = slicer.mrmlScene
if not overwrite:
nodeName = scene.GetUniqueNameByString(nodeName)
newNode.SetName(nodeName)
if overwrite:
removeOldMRMLNode(newNode)
scene.AddNode(newNode)
[docs]def EnsureRegistration():
"""This is a complete hack, but attempting to read
a dummy file with AddArchetypeVolume
has a side effect of registering
the MRMLImageIO file reader.
"""
vl = slicer.modules.volumes.logic()
volumeNode = vl.AddArchetypeVolume('_DUMMY_DOES_NOT_EXISTS__','invalidRead')
[docs]def PullFromSlicer( NodeName ):
""" Given a slicer MRML image name, return the SimpleITK image object.
"""
EnsureRegistration()
myNodeFullITKAddress = GetSlicerITKReadWriteAddress( NodeName )
sitkimage = sitk.ReadImage(myNodeFullITKAddress)
return sitkimage
[docs]def PushToSlicer(sitkimage, NodeName, compositeView=0, overwrite=False):
""" Given a SimpleITK image, push it back to slicer for viewing.
Viewing options:
**bit 0**:
Set as background image
**bit 1**:
Set as foreground image
**bit 2**:
Set as label image
"""
from sitkUtils import EnsureRegistration, CreateNewVolumeNode, CreateNewDisplayNode, GetSlicerITKReadWriteAddress
scene = slicer.mrmlScene
compositeViewMap = {0:'background',
1:'foreground',
2:'label'}
if compositeView in compositeViewMap.keys():
imageType = compositeViewMap[compositeView]
else:
raise Exception('Unknown view option given: {0}. See help'.format(compositeView))
EnsureRegistration()
newNode = CreateNewVolumeNode(NodeName,'vtkMRMLScalarVolumeNode', overwrite)
if not overwrite:
newDisplayNode = CreateNewDisplayNode(NodeName)
else:
nodeCollection = scene.GetNodesByClassByName('vtkMRMLScalarVolumeDisplayNode', NodeName + '_Display')
count = nodeCollection.GetNumberOfItems()
if count == 0:
newDisplayNode = CreateNewDisplayNode(NodeName)
elif count == 1:
newDisplayNode = nodeCollection.GetItemAsObject(0)
else:
Exception( "Too many display nodes for %s!" % NodeName )
newNode.SetAndObserveDisplayNodeID(newDisplayNode.GetID())
myNodeFullITKAddress = GetSlicerITKReadWriteAddress(newNode.GetName())
sitk.WriteImage(sitkimage, myNodeFullITKAddress)
compositeNodes = slicer.util.getNodes("vtkMRMLSliceCompositeNode*")
for node in compositeNodes.values():
if imageType == 'foreground':
node.SetForegroundVolumeID(newNode.GetID())
newDisplayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeGrey')
elif imageType == 'background':
node.SetBackgroundVolumeID(newNode.GetID())
newDisplayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeGrey')
elif imageType == 'label':
newNode.SetLabelMap(True)
node.SetLabelVolumeID(newNode.GetID())
node.SetLabelOpacity(1.0)
newDisplayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeFileGenericColors.txt')
applicationLogic = slicer.app.applicationLogic()
applicationLogic.FitSliceToAll()
# Helper functions
[docs]def PushBackground(sitkImage, nodeName, overwrite=False):
PushToSlicer(sitkImage, nodeName, 0, overwrite)
[docs]def PushForeground(sitkImage, nodeName, overwrite=False):
PushToSlicer(sitkImage, nodeName, 1, overwrite)
[docs]def PushLabel(sitkImage, nodeName, overwrite=False):
PushToSlicer(sitkImage, nodeName, 2, overwrite)
###############
############### The real work starts here
###############
[docs]def slicerNotes_UnitTest():
newPointSource = sitk.Image(128,128,128,sitk.sitkFloat32)
newPointSource[64,64,64]=1
for sigma in range(1,12,3):
outputName = "sigmaImage_"+str(sigma)
smoothimage = sitk.SmoothingRecursiveGaussian(newPointSource,sigma)
PushToSlicer(smoothimage,outputName,True)
# To show image in external ImageJ program sitk.Show(smoothimage)