Difference between revisions of "Documentation/Nightly/ScriptRepository"

From Slicer Wiki
Jump to: navigation, search
(Moved page to readthedocs)
Tags: 2017 source edit, Replaced
 
(285 intermediate revisions by 11 users not shown)
Line 1: Line 1:
 
<noinclude>{{documentation/versioncheck}}</noinclude>
 
<noinclude>{{documentation/versioncheck}}</noinclude>
__TOC__
 
  
 
+
{{documentation/banner
=Community-contributed modules=
+
| text  = [https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html This page has been moved to read-the-docs.]
 
+
| background-color = 8FBC8F }}
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==
 
* [https://raw.github.com/pieper/VolumeMasker/master/VolumeMasker.py 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==
 
* [https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.
 
* [https://subversion.assembla.com/svn/slicerrt/trunk/SlicerRt/src/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.
 
 
 
==Informatics==
 
* [https://subversion.assembla.com/svn/slicerrt/trunk/SlicerRt/sandbox/MarkupsInfoModule/MarkupsInfo.py MarkupsInfo.py]: Compute the total length between all the points of a markup list.
 
* [https://subversion.assembla.com/svn/slicerrt/trunk/SlicerRt/sandbox/LineProfile/LineProfile.py 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')
 
* [https://subversion.assembla.com/svn/slicerrt/trunk/SlicerRt/sandbox/CaptureRotationVideo/CaptureRotationVideo.py 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.
 
<pre>
 
[success, loadedVolumeNode] = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd', returnNode=True)
 
</pre>
 
 
 
==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)
 
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
 
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)
 
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, '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.
 
 
 
<pre>
 
# 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)
 
</pre>
 
 
 
== 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
 
<pre>
 
# 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())
 
</pre>
 
 
 
 
 
== Export a model to Blender, including color ==
 
 
 
<pre>
 
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()
 
</pre>
 
 
 
== Clone a volume ==
 
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.
 
<pre>
 
sourceVolumeNode = slicer.util.getNode('MRHead')
 
volumesLogic = slicer.modules.volumes.logic()
 
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')
 
</pre>
 
 
 
== Create a new volume ==
 
This example shows how to create a new empty volume.
 
<pre>
 
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()
 
</pre>
 
 
 
== 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.
 
<pre>
 
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()
 
</pre>
 
 
 
== 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:
 
 
 
<pre>
 
tensors = array('Output DTI Volume')
 
</pre>
 
 
 
Type the following code into the Python window to access all tensor components using vtk commands:
 
 
 
<pre>
 
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
 
</pre>
 
 
 
== Change window/level (brightness/contrast) or colormap of a volume ==
 
This example shows how to change window/level of the MRHead sample volume.
 
<pre>
 
volumeNode = getNode('MRHead')
 
displayNode = volumeNode.GetDisplayNode()
 
displayNode.AutoWindowLevelOff()
 
displayNode.SetWindow(50)
 
displayNode.SetLevel(100)
 
</pre>
 
 
 
Change color mapping from grayscale to rainbow:
 
<pre>
 
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')
 
</pre>
 
 
 
== Manipulate a Slice View ==
 
 
 
<pre>
 
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)
 
</pre>
 
 
 
== 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')"
 
 
 
<pre>
 
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)
 
</pre>
 
 
 
== Save the scene into a new directory ==
 
 
 
<pre>
 
# 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")
 
</pre>
 
 
 
== Save the scene into a single MRB file ==
 
<pre>
 
# 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")
 
</pre>
 
 
 
== Show a volume in the Slice Views ==
 
 
 
<pre>
 
volumeNode = slicer.util.getNode('YourVolumeNode')
 
applicationLogic = slicer.app.applicationLogic()
 
selectionNode = applicationLogic.GetSelectionNode()
 
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())
 
applicationLogic.PropagateForegroundVolumeSelection(0)
 
</pre>
 
 
 
or
 
 
 
<pre>
 
n =  slicer.util.getNode('YourVolumeNode')
 
for color in ['Red', 'Yellow', 'Green']:
 
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())
 
</pre>
 
 
 
== Change opacity of foreground volume in the Slice Views ==
 
 
 
<pre>
 
lm = slicer.app.layoutManager()
 
sliceLogic = lm.sliceWidget('Red').sliceLogic()
 
compositeNode = sliceLogic.GetSliceCompositeNode()
 
compositeNode.SetForegroundOpacity(0.4)
 
</pre>
 
 
 
== Center the 3D View on the Scene ==
 
<pre>
 
layoutManager = slicer.app.layoutManager()
 
threeDWidget = layoutManager.threeDWidget(0)
 
threeDView = threeDWidget.threeDView()
 
threeDView.resetFocalPoint()
 
</pre>
 
 
 
== Display text in a 3D view or slice view ==
 
 
 
The easiest way to show information overlaid on a viewer is to use corner annotations.
 
 
 
<pre>
 
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()
 
</pre>
 
 
 
== Turning off interpolation ==
 
 
 
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.
 
 
 
<pre>
 
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)
 
</pre>
 
 
 
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:
 
 
 
<pre>
 
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)
 
</pre>
 
 
 
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:
 
<pre>
 
import SimpleITK as sitk
 
import sitkUtils
 
inputImage = sitkUtils.PullFromSlicer('MRHead')
 
filter = sitk.SignedMaurerDistanceMapImageFilter()
 
outputImage = filter.Execute(inputImage)
 
sitkUtils.PushToSlicer(outputImage,'outputImage')
 
</pre>
 
 
 
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:
 
 
 
<pre>
 
def onMouseMoved(observer,eventid): 
 
  ras=[0,0,0]
 
  crosshairNode.GetCursorPositionRAS(ras)
 
  print(ras)
 
 
 
crosshairNode=slicer.util.getNode('Crosshair')
 
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)
 
</pre>
 
 
 
== Thick slab reconstruction and maximum/minimum intensity volume projections ==
 
 
 
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:
 
<pre>
 
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()
 
</pre>
 
 
 
Set up 'red' slice viewer to show maximum intensity projection (MIP):
 
<pre>
 
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()
 
</pre>
 
 
 
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:
 
<pre>
 
msn=slicer.vtkMRMLModelStorageNode()
 
msn.SetDefaultWriteFileExtension('stl')
 
slicer.mrmlScene.AddDefaultNode(msn)
 
</pre>
 
 
 
== Change file type for saving for all volumes (with already existing storage nodes) ==
 
<pre>
 
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()
 
</pre>
 
 
 
== Segmentations ==
 
 
 
For all operations accessing or manupilating the internals of a segmentation will need this import!
 
<pre>
 
import vtkSegmentationCorePython as vtkSegmentationCore
 
</pre>
 
 
 
=== Get a segment ===
 
<pre>
 
segmentation = segmentationNode.GetSegmentation()
 
segment = segmentation.GetSegment(segmentID)
 
</pre>
 
 
 
=== Get a representation of a segment ===
 
<pre>
 
# 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
 
</pre>
 
 
 
=== Convert using default path and conversion parameters ===
 
<pre>
 
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName()) # This creates binary labelmap, but same idea for all others
 
</pre>
 
 
 
=== Convert using custom path or conversion parameters ===
 
<pre>
 
# Custom path
 
TODO
 
 
 
# Custom conversion parameter
 
referenceGeometry=vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)
 
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)
 
</pre>
 
 
 
=== Re-convert using a modified conversion parameter ===
 
<pre>
 
import vtkSegmentationCorePython as vtkSegmentationCore
 
segmentation = getNode('Segmentation').GetSegmentation()
 
 
 
# Turn of surface smoothing
 
segmentation.SetConversionParameter('Smoothing factor','0.0')
 
 
 
# Re-convert using default conversion path
 
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())
 
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())
 
</pre>
 
 
 
=== 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:
 
 
 
https://subversion.assembla.com/svn/slicerrt/trunk/SlicerRt/samples/PythonScripts/SegmentGrowCut/SegmentGrowCut.py
 
 
 
== Subject hierarchy ==
 
==== Get the pseudo-singleton subject hierarchy node ====
 
It manages the whole hierarchy and provides functions to access and manipulate
 
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
 
 
 
==== Create subject hierarchy item ====
 
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:
 
  shNode.CreateItem(parentItemID, dataNode)
 
  # If it is a hierarchy item without a data node, then the create function must be used:
 
  shNode.CreateSubjectItem(parentItemID, name)
 
  shNode.CreateFolderItem(parentItemID, name)
 
  shNode.CreateHierarchyItem(parentItemID, name, level) # Advanced method to set level attribute manually (usually subject, study, or folder, but it can be a virtual branch for example)
 
 
 
==== Get subject hierarchy item ====
 
Items in subject hierarchy are uniquely identified by integer IDs
 
  # Get scene item ID first because it is the root item:
 
  sceneItemID = shNode.GetSceneItemID()
 
  # Get direct child by name
 
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')
 
  # Get item for data node
 
  itemID = shNode.GetItemByDataNode(dataNode)
 
  # Get item by UID (such as DICOM)
 
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)
 
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)
 
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)
 
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()
 
 
 
=== Manipulate subject hierarchy item ===
 
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.
 
  # Set item name
 
  shNode.SetItemName(itemID, 'NewName')
 
  # Set item parent (reparent)
 
  shNode.SetItemParent(itemID, newParentItemID)
 
  # Set visibility of data nodes associated to items in a branch (or a leaf item)
 
  shNode.SetDisplayVisibilityForBranch(itemID, 1)
 

Latest revision as of 04:06, 24 April 2021

Home < Documentation < Nightly < ScriptRepository