Documentation/Nightly/ScriptRepository
For the latest Slicer documentation, visit the read-the-docs. |
Contents
- 1 Community-contributed modules
- 2 Community-contributed examples
- 2.1 Capture
- 2.2 Launching Slicer
- 2.3 Load volume from file
- 2.4 DICOM
- 2.4.1 How to access tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' "0020,0032" field:
- 2.4.2 How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:
- 2.4.3 How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:
- 2.4.4 How can I convert DICOM to NRRD on the command line?
- 2.5 Toolbar functions
- 2.6 Manipulating objects in the slice viewer
- 2.7 Add a texture mapped plane to the scene as a model
- 2.8 Export a model to Blender, including color
- 2.9 Clone a volume
- 2.10 Create a new volume
- 2.11 Modify voxels in a volume
- 2.12 Access values in a DTI tensor volume
- 2.13 Change window/level (brightness/contrast) or colormap of a volume
- 2.14 Manipulate a Slice View
- 2.15 Save a series of images from a Slice View
- 2.16 Save the scene into a new directory
- 2.17 Save the scene into a single MRB file
- 2.18 Show a volume in the Slice Views
- 2.19 Change opacity of foreground volume in the Slice Views
- 2.20 Center the 3D View on the Scene
- 2.21 Display text in a 3D view or slice view
- 2.22 Turning off interpolation
- 2.23 Customize viewer layout
- 2.24 Running an ITK filter in Python using SimpleITK
- 2.25 Get current mouse coordinates in a slice view
- 2.26 Thick slab reconstruction and maximum/minimum intensity volume projections
- 2.27 Change default file type for nodes (that have never been saved yet)
- 2.28 Change file type for saving for all volumes (with already existing storage nodes)
- 2.29 Segmentations
Community-contributed modules
Usage: save the .py file to a directory, add the directory to the additional module paths in the Slicer application settings (choose in the menu: Edit / Application settings, click Modules, click >> next to Additional module paths, click Add, and choose the .py file's location).
Filters
- VolumeMasker.py: Update a target volume with the results of setting all input volume voxels to 0 except for those that correspond to a selected label value in an input label map (Used for example in the volume rendering in [https://www.youtube.com/watch?v=dfu2gugHLHs this video).
DICOM
- dicom header browser to easily scroll through dicom files using dcmdump.
- SlicerRT batch processing to batch convert RT structure sets to labelmap NRRD files.
Informatics
- MarkupsInfo.py: Compute the total length between all the points of a markup list.
- LineProfile.py: Compute intensity profile in a volume along a line.
Community-contributed examples
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.
Capture
- Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:
vol=slicer.util.getNode('MR*') vol.GetImageData().GetDimensions()
- Capture the full Slicer screen and save it into a file
img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage() img.save('c:/tmp/test.png')
- CaptureRotationVideo.py: Capture a video of the scene rotating in the 3D view
Launching Slicer
- How to open an .mrb file with Slicer at the command line?
Slicer.exe --python-code "slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )"
- How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?
Slicer.exe --python-code "doSomething; doSomethingElse; etc." --testing --no-splash --no-main-window
Load volume from file
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.
[success, loadedVolumeNode] = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd', returnNode=True)
DICOM
How to access tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' "0020,0032" field:
db=slicer.dicomDatabase patientList=db.patients() studyList=db.studiesForPatient(patientList[0]) seriesList=db.seriesForStudy(studyList[0]) fileList=db.filesForSeries(seriesList[0]) print db.fileValue(fileList[0],'0020,0032')
How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:
volumeName='2: ENT IMRT' n=slicer.util.getNode(volumeName) instUids=n.GetAttribute('DICOM.instanceUIDs').split() filename=slicer.dicomDatabase.fileForInstance(instUids[0]) print slicer.dicomDatabase.fileValue(filename,'0018,5100')
How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:
rtStructName = '3: RTSTRUCT: PROS' rtStructNode = slicer.util.getNode(rtStructName) rtStructSubjectHierarchyNode = slicer.vtkMRMLSubjectHierarchyNode.GetAssociatedSubjectHierarchyNode(rtStructNode) ctSliceInstanceUids = rtStructSubjectHierarchyNode.GetAttribute('DICOM.ReferencedInstanceUIDs').split() filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0]) print slicer.dicomDatabase.fileValue(filename,'0008,0033')
How can I convert DICOM to NRRD on the command line?
/Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code "node=slicer.util.loadVolume('/tmp/series/im0.dcm', returnNode=True)[1]; slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()"
The same can be done on windows by using the top level Slicer.exe. Be sure to use forward slashes in the pathnames within quotes on the command line.
Toolbar functions
- How to turn on slice intersections in the crosshair menu on the toolbar:
viewNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLSliceCompositeNode') viewNodes.UnRegister(slicer.mrmlScene) viewNodes.InitTraversal() viewNode = viewNodes.GetNextItemAsObject() while viewNode: viewNode.SetSliceIntersectionVisibility(1) viewNode = viewNodes.GetNextItemAsObject()
How to find similar functions? For this one I searched for "slice intersections" text in the whole slicer source code, found that the function is implemented in Base\QTGUI\qSlicerViewersToolBar.cxx, then translated the qSlicerViewersToolBarPrivate::setSliceIntersectionVisible(bool visible) method to Python.
Manipulating objects in the slice viewer
- How to define/edit a circular region of interest in a slice viewer?
Drop two markup points on a slice view and copy-paste the code below into the Python console. After this, as you move the markups you’ll see a circle following the markups.
# Update the sphere from the fiducial points def UpdateSphere(param1, param2): import math centerPointCoord = [0.0, 0.0, 0.0] markups.GetNthFiducialPosition(0,centerPointCoord) circumferencePointCoord = [0.0, 0.0, 0.0] markups.GetNthFiducialPosition(1,circumferencePointCoord) sphere.SetCenter(centerPointCoord) radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2) sphere.SetRadius(radius) sphere.SetPhiResolution(30) sphere.SetThetaResolution(30) sphere.Update() # Get markup node from scene markups=slicer.util.getNode('F') sphere = vtk.vtkSphereSource() UpdateSphere(0,0) # Create model node and add to scene modelsLogic = slicer.modules.models.logic() model = modelsLogic.AddModel(sphere.GetOutput()) model.GetDisplayNode().SetSliceIntersectionVisibility(True) model.GetDisplayNode().SetSliceIntersectionThickness(3) model.GetDisplayNode().SetColor(1,1,0) # Call UpdateSphere whenever the fiducials are changed markups.AddObserver("ModifiedEvent", UpdateSphere, 2)
Add a texture mapped plane to the scene as a model
Note that model textures are not exposed in the GUI and are not saved in the scene
# use dummy image data here e = vtk.vtkImageEllipsoidSource() scene = slicer.mrmlScene # Create model node model = slicer.vtkMRMLModelNode() model.SetScene(scene) model.SetName(scene.GenerateUniqueName("2DImageModel")) planeSource = vtk.vtkPlaneSource() model.SetAndObservePolyData(planeSource.GetOutput()) # Create display node modelDisplay = slicer.vtkMRMLModelDisplayNode() modelDisplay.SetColor(1,1,0) # yellow modelDisplay.SetBackfaceCulling(0) modelDisplay.SetScene(scene) scene.AddNode(modelDisplay) model.SetAndObserveDisplayNodeID(modelDisplay.GetID()) # Add to scene modelDisplay.SetAndObserveTextureImageData(e.GetOutput()) scene.AddNode(model) transform = slicer.vtkMRMLLinearTransformNode() scene.AddNode(transform) model.SetAndObserveTransformNodeID(transform.GetID()) vTransform = vtk.vtkTransform() vTransform.Scale(50,50,50) vTransform.RotateX(30) transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())
Export a model to Blender, including color
plyFilePath = "/tmp/fibers.ply" lineDisplayNode = getNode("*LineDisplay*") tuber = vtk.vtkTubeFilter() tuber.SetInput(lineDisplayNode.GetOutputPolyData()) tubes = tuber.GetOutput() tubes.Update() scalars = tubes.GetPointData().GetArray(0) scalars.SetName("scalars") triangles = vtk.vtkTriangleFilter() triangles.SetInput(tubes) colorNode = lineDisplayNode.GetColorNode() lookupTable = vtk.vtkLookupTable() lookupTable.DeepCopy(colorNode.GetLookupTable()) lookupTable.SetTableRange(0,1) plyWriter = vtk.vtkPLYWriter() plyWriter.SetInput(triangles.GetOutput()) plyWriter.SetLookupTable(lookupTable) plyWriter.SetArrayName("scalars") plyWriter.SetFileName(plyFilePath) plyWriter.Write()
Clone a volume
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.
sourceVolumeNode = slicer.util.getNode('MRHead') volumesLogic = slicer.modules.volumes.logic() clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')
Create a new volume
This example shows how to create a new empty volume.
imageSize=[512, 512, 512] imageSpacing=[1.0, 1.0, 1.0] voxelType=vtk.VTK_UNSIGNED_CHAR # Create an empty image volume imageData=vtk.vtkImageData() imageData.SetDimensions(imageSize) imageData.AllocateScalars(voxelType, 1) thresholder=vtk.vtkImageThreshold() thresholder.SetInputData(imageData) thresholder.SetInValue(0) thresholder.SetOutValue(0) # 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()
Modify voxels in a volume
This example shows how to change voxels values of the MRHead sample volume. The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.
volumeNode=slicer.util.getNode('MRHead') ijkToRas = vtk.vtkMatrix4x4() volumeNode.GetIJKToRASMatrix(ijkToRas) imageData=volumeNode.GetImageData() extent = imageData.GetExtent() for k in xrange(extent[4], extent[5]+1): for j in xrange(extent[2], extent[3]+1): for i in xrange(extent[0], extent[1]+1): position_Ijk=[i, j, k, 1] position_Ras=ijkToRas.MultiplyPoint(position_Ijk) r=position_Ras[0] a=position_Ras[1] s=position_Ras[2] functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue) imageData.SetScalarComponentFromFloat(distortionVectorPosition_Ijk[0], distortionVectorPosition_Ijk[1], distortionVectorPosition_Ijk[2], 0, fillValue) imageData.Modified()
Access values in a DTI tensor volume
This example shows how to access individual tensors at the voxel level.
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’
Then open the python window: View->Python interactor
Use this command to access tensors through numpy:
tensors = array('Output DTI Volume')
Type the following code into the Python window to access all tensor components using vtk commands:
volumeNode=slicer.util.getNode('Output DTI Volume') imageData=volumeNode.GetImageData() tensors = imageData.GetPointData().GetTensors() extent = imageData.GetExtent() idx = 0 for k in xrange(extent[4], extent[5]+1): for j in xrange(extent[2], extent[3]+1): for i in xrange(extent[0], extent[1]+1): tensors.GetTuple9(idx) idx += 1
Change window/level (brightness/contrast) or colormap of a volume
This example shows how to change window/level of the MRHead sample volume.
volumeNode = getNode('MRHead') displayNode = volumeNode.GetDisplayNode() displayNode.AutoWindowLevelOff() displayNode.SetWindow(50) displayNode.SetLevel(100)
Change color mapping from grayscale to rainbow:
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')
Manipulate a Slice View
lm = slicer.app.layoutManager() red = lm.sliceWidget('Red') redLogic = red.sliceLogic() # Print current slice offset position print redLogic.GetSliceOffset() # Change slice position redLogic.SetSliceOffset(20)
Save a series of images from a Slice View
You can use ScreenCapture module to capture series of images. To do it programmatically, save the following into a file such as '/tmp/record.py' and then in the slicer python console type "execfile('/tmp/record.py')"
layoutName = 'Green' imagePathPattern = '/tmp/image-%03d.png' steps = 10 widget = slicer.app.layoutManager().sliceWidget(layoutName) view = widget.sliceView() logic = widget.sliceLogic() bounds = [0,]*6 logic.GetSliceBounds(bounds) for step in range(steps): offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4]) logic.SetSliceOffset(offset) view.forceRender() image = qt.QPixmap.grabWidget(view).toImage() image.save(imagePathPattern % step)
Save the scene into a new directory
# Create a new directory where the scene will be saved into import time sceneSaveDirectory = slicer.app.temporaryPath + "/saved-scene-" + time.strftime("%Y%m%d-%H%M%S") if not os.access(sceneSaveDirectory, os.F_OK): os.makedirs(sceneSaveDirectory) # Save the scene if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None): logging.info("Scene saved to: {0}".format(sceneSaveDirectory)) else: logging.error("Scene saving failed")
Save the scene into a single MRB file
# Generate file name import time sceneSaveFilename = slicer.app.temporaryPath + "/saved-scene-" + time.strftime("%Y%m%d-%H%M%S") + ".mrb" # Save scene if slicer.util.saveScene(sceneSaveFilename): logging.info("Scene saved to: {0}".format(sceneSaveFilename)) else: logging.error("Scene saving failed")
Show a volume in the Slice Views
volumeNode = slicer.util.getNode('YourVolumeNode') applicationLogic = slicer.app.applicationLogic() selectionNode = applicationLogic.GetSelectionNode() selectionNode.SetSecondaryVolumeID(volumeNode.GetID()) applicationLogic.PropagateForegroundVolumeSelection(0)
or
n = slicer.util.getNode('YourVolumeNode') for color in ['Red', 'Yellow', 'Green']: slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())
Change opacity of foreground volume in the Slice Views
lm = slicer.app.layoutManager() sliceLogic = lm.sliceWidget('Red').sliceLogic() compositeNode = sliceLogic.GetSliceCompositeNode() compositeNode.SetForegroundOpacity(0.4)
Center the 3D View on the Scene
layoutManager = slicer.app.layoutManager() threeDWidget = layoutManager.threeDWidget(0) threeDView = threeDWidget.threeDView() threeDView.resetFocalPoint()
Display text in a 3D view or slice view
The easiest way to show information overlaid on a viewer is to use corner annotations.
view=slicer.app.layoutManager().threeDWidget(0).threeDView() # Set text to "Something" view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,"Something") # Set color to red view.cornerAnnotation().GetTextProperty().SetColor(1,0,0) # Update the view view.forceRender()
Turning off interpolation
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.
def NoInterpolate(caller,event): for node in slicer.util.getNodes('*').values(): if node.IsA('vtkMRMLScalarVolumeDisplayNode'): node.SetInterpolate(0) slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)
The below link explains how to put this in your startup script.
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc
Customize viewer layout
Show a custom layout of a 3D view on top of the red slice view:
customLayout = ("<layout type=\"vertical\" split=\"true\" >" " <item>" " <view class=\"vtkMRMLViewNode\" singletontag=\"1\">" " <property name=\"viewlabel\" action=\"default\">1</property>" " </view>" " </item>" " <item>" " <view class=\"vtkMRMLSliceNode\" singletontag=\"Red\">" " <property name=\"orientation\" action=\"default\">Axial</property>" " <property name=\"viewlabel\" action=\"default\">R</property>" " <property name=\"viewcolor\" action=\"default\">#F34A33</property>" " </view>" " </item>" "</layout>") customLayoutId=501 layoutManager = slicer.app.layoutManager() layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout) layoutManager.setLayout(customLayoutId)
See description of standard layouts (that can be used as examples) here: https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx
Running an ITK filter in Python using SimpleITK
Open the "Sample Data" module and download "MR Head", then paste the following snippet in Python interactor:
import SimpleITK as sitk import sitkUtils inputImage = sitkUtils.PullFromSlicer('MRHead') filter = sitk.SignedMaurerDistanceMapImageFilter() outputImage = filter.Execute(inputImage) sitkUtils.PushToSlicer(outputImage,'outputImage')
More information:
- See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html
- sitkUtils in Slicer is used for pushing and pulling images from Slicer to SimpleITK: https://github.com/Slicer/Slicer/blob/master/Base/Python/sitkUtils.py
Get current mouse coordinates in a slice view
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:
def onMouseMoved(observer,eventid): ras=[0,0,0] crosshairNode.GetCursorPositionRAS(ras) print(ras) crosshairNode=slicer.util.getNode('Crosshair') crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)
Thick slab reconstruction and maximum/minimum intensity volume projections
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed') appLogic = slicer.app.applicationLogic() sliceLogic = appLogic.GetSliceLogic(sliceNode) sliceLayerLogic = sliceLogic.GetBackgroundLayer() reslice = sliceLayerLogic.GetReslice() reslice.SetSlabModeToMean() reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood) sliceNode.Modified()
Set up 'red' slice viewer to show maximum intensity projection (MIP):
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed') appLogic = slicer.app.applicationLogic() sliceLogic = appLogic.GetSliceLogic(sliceNode) sliceLayerLogic = sliceLogic.GetBackgroundLayer() reslice = sliceLayerLogic.GetReslice() reslice.SetSlabModeToMax() reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts) sliceNode.Modified()
The projected image is available in a vtkImageData object by calling reslice.GetOutput().
Change default file type for nodes (that have never been saved yet)
Default node can be specified that will be used as a basis of all new storage nodes. This can be used for setting default file extension. For example, change file format to STL for model nodes:
msn=slicer.vtkMRMLModelStorageNode() msn.SetDefaultWriteFileExtension('stl') slicer.mrmlScene.AddDefaultNode(msn)
Change file type for saving for all volumes (with already existing storage nodes)
requiredFileExtension = '.nia' originalFileExtension = '.nrrd' volumeNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLScalarVolumeNode') volumeNodes.UnRegister(slicer.mrmlScene) volumeNodes.InitTraversal() volumeNode = volumeNodes.GetNextItemAsObject() while volumeNode: volumeStorageNode = volumeNode.GetStorageNode() if not volumeStorageNode: volumeStorageNode = volumeNode.CreateDefaultStorageNode() slicer.mrmlScene.AddNode(volumeStorageNode) volumeStorageNode.UnRegister(None) volumeNode.SetAndObserveStorageNodeID(volumeStorageNode.GetID()) volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension) else: volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension,requiredFileExtension)) volumeNode = volumeNodes.GetNextItemAsObject()
Segmentations
For all operations accessing or manupilating the internals of a segmentation will need this import!
import vtkSegmentationCorePython as vtkSegmentationCore
Get a segment
segmentation = segmentationNode.GetSegmentation() segment = segmentation.GetSegment(segmentID)
Get a representation of a segment
# Get representation from a single segment. If it does not exist, it will return None segment.GetRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName()) # This gets the binary labelmap, but same idea for all others # Get representation for a single segment. Convert temporarily for that particular segment if needed. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false) slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData) # Get labelmap slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentRepresentation(segmentationNode, segmentID, vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName(), outputPolyData) # Any representation
Convert using default path and conversion parameters
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName()) # This creates binary labelmap, but same idea for all others
Convert using custom path or conversion parameters
# Custom path TODO # Custom conversion parameter referenceGeometry=vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData) segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)
How to run segment editor effects from a script
Editor effects are complex because they need to handle changing master volumes, undo/redo, masking operations, etc. Therefore, instead of using a segment editor effect, it is simpler to run the underlying filters directly from script.
This example demonstrates how to perform auto-complete by growing from seeds (grow-cut segmentation) without GUI: