<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.slicer.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Pinter</id>
	<title>Slicer Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.slicer.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Pinter"/>
	<link rel="alternate" type="text/html" href="https://www.slicer.org/wiki/Special:Contributions/Pinter"/>
	<updated>2026-04-16T07:23:45Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.33.0</generator>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/ExternalBeamPlanning&amp;diff=63595</id>
		<title>Documentation/Nightly/Modules/ExternalBeamPlanning</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/ExternalBeamPlanning&amp;diff=63595"/>
		<updated>2021-06-21T16:08:17Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Fix broken links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
This work was in part funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health and Long-Term Care and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&amp;lt;br&amp;gt;&lt;br /&gt;
Author: Csaba Pinter (PerkLab, Queen's University), Greg Sharp (Massachusetts General Hospital)&amp;lt;br&amp;gt;&lt;br /&gt;
Contact: Csaba Pinter, &amp;lt;email&amp;gt;csaba.pinter@queensu.ca&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Documentation/Nightly/Extensions/SlicerRT|Back to SlicerRT home]]&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
|{{collaborator|logo|ocairo}}|{{collaborator|longname|ocairo}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
The {{documentation/modulename}} module is a generic, extensible module for forward planning of external beam radiation therapy treatments.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
&lt;br /&gt;
*Proton dose calculation&lt;br /&gt;
*Any dose engine can be integrated (C++, Python, Matlab)&lt;br /&gt;
&lt;br /&gt;
{| align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20171019_EBP_ProstateProton_Planning.png|thumb|820px|External Beam Planning module UI with a prostate proton plan]]&lt;br /&gt;
|[[File:20171019_EBP_ProstateProton_Dose.png|thumb|700px|Output dose of the plan above]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_OrthovoltageDoseEngine.pptx Orthovoltage RT treatment planning tutorial] (uses EGSnrc)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
&lt;br /&gt;
*External Beam Planning module&lt;br /&gt;
**Basic plan data: Reference volume, Structure set, Isocenter, Target volume, Dose engine, Prescription dose&lt;br /&gt;
**Beam list&lt;br /&gt;
*Beams module: edit parameters of individual beams&lt;br /&gt;
**Geometry&lt;br /&gt;
&lt;br /&gt;
{| align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20171019_EBP_BeamParameters_Geometry.png|thumb|484px|Beam geometry parameters]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
**Energy (extensible by plugins)&lt;br /&gt;
&lt;br /&gt;
{| align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20171019_EBP_ProtonBeamParameters_Energy.png|thumb|483px|Beam energy parameters (including proton-specific parameters)]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
**Beam model (extensible by plugins)&lt;br /&gt;
&lt;br /&gt;
{| align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20171019_EBP_ProtonBeamParameters_BeamModel.png|thumb|484px|Beam model parameters (including proton-specific parameters)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{documentation/{{documentation/version}}/module-parametersdescription}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
&lt;br /&gt;
*N/A&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
&lt;br /&gt;
*Sharp, G., Pinter, C., Unkelbach, J., Fichtinger, G. (2017). Open Source Proton Treatment Planning in 3D Slicer: Status Update. Proceedings to the 56 Annual Meeting of the Particle Therapy Cooperative Group (PTCOG), 8-13 May 2017. International Journal of Particle Therapy: Summer 2017, Vol. 4, No. 1, pp. 14-83.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
&lt;br /&gt;
*Sample C++ dose engine: https://github.com/SlicerRt/SlicerRT/blob/master/ExternalBeamPlanning/Widgets/qSlicerMockDoseEngine.h&lt;br /&gt;
*Sample Python dose engine: https://github.com/SlicerRt/SlicerRT/blob/master/ExternalBeamPlanning/Widgets/Python/MockPythonDoseEngine.py&lt;br /&gt;
*Future plans&lt;br /&gt;
**Inverse planning capabilities&lt;br /&gt;
**Matlab plugin adapter&lt;br /&gt;
**Ports module (apertures, MLC, target volume)&lt;br /&gt;
**Beam groups (common parameters for a group of beams)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=63509</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=63509"/>
		<updated>2021-01-05T19:16:43Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Traverse children of a subject hierarchy item */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=  &lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the[[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
&lt;br /&gt;
*[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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
*[https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Get node object from the scene from node name or ID==&lt;br /&gt;
&lt;br /&gt;
Examples in the script repository commonly use &amp;lt;code&amp;gt;slicer.util.getNode()&amp;lt;/code&amp;gt; function for getting a node object from the scene. This method is only recommended for testing and interactive debugging. &lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;slicer.util.getNode()&amp;lt;/code&amp;gt; is recommended **only for interactive debugging** in the Python console/Jupyter notebook&lt;br /&gt;
**its input is intentionally defined vaguely (it can be either node ID or name and you can use wildcards such as &amp;lt;code&amp;gt;*&amp;lt;/code&amp;gt;), which is good because it make it simpler to use, but the uncertain behavior is not good for general-purpose use in a module&lt;br /&gt;
**throws an exception so that the developer knows immediately that there was a typo or other unexpected error&lt;br /&gt;
*&amp;lt;code&amp;gt;slicer.mrmlScene.GetNodeByID()&amp;lt;/code&amp;gt; is optimized for usage in modules:&lt;br /&gt;
**its behavior is more predictable: it only accepts node ID as input. &amp;lt;code&amp;gt;slicer.mrmlScene.GetFirstNodeByName()&amp;lt;/code&amp;gt; can be used to get a node by its name, but since multiple nodes in the scene can have the same name, it is not recommended to keep reference to a node by its name.&lt;br /&gt;
**if node is not found it returns &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; (instead of throwing an exception), because this is often not considered an error in module code (it is just used to check existence of a node) and using return value for not-found nodes allows simpler syntax&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
&lt;br /&gt;
*Capture the full Slicer screen and save it into a file&lt;br /&gt;
&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
&lt;br /&gt;
*Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
*Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
&lt;br /&gt;
*How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loadedVolumeNode = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional options may be specified in &amp;lt;code&amp;gt;properties&amp;lt;/code&amp;gt; argument. For example, load an image stack by disabling &amp;lt;code&amp;gt;singleFile&amp;lt;/code&amp;gt; option:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loadedVolumeNode = slicer.util.loadVolume('c:/Users/abc/Documents/SomeImage/file001.png', {'singleFile': False})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Load volume from URL==&lt;br /&gt;
&lt;br /&gt;
Download a volume from a URL and load it into the scene using the code snippet below. Downloaded data is temporarily preserved in the application's cache folder and if the checksum of the already downloaded data matches the specified checksum (&amp;lt;algo&amp;gt;:&amp;lt;digest&amp;gt;) then the file is retrieved from the cache instead of being downloaded again. To compute digest with algo ''SHA256'', you can run &amp;lt;code&amp;gt;slicer.util.computeChecksum(&amp;quot;SHA256&amp;quot;, &amp;quot;path/to/file&amp;quot;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
sampleDataLogic = SampleData.SampleDataLogic()&lt;br /&gt;
loadedNodes = sampleDataLogic.downloadFromURL(&lt;br /&gt;
    nodeNames='MRHead',&lt;br /&gt;
    fileNames='MR-head25.nrrd',&lt;br /&gt;
    uris='https://github.com/Slicer/SlicerTestingData/releases/download/SHA256/cc211f0dfd9a05ca3841ce1141b292898b2dd2d3f08286affadf823a7e58df93',&lt;br /&gt;
    checksums='SHA256:cc211f0dfd9a05ca3841ce1141b292898b2dd2d3f08286affadf823a7e58df93')[0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With interruptible progress reporting using a progress bar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
&lt;br /&gt;
def reportProgress(msg, level=None):&lt;br /&gt;
    # Print progress in the console&lt;br /&gt;
    print(&amp;quot;Loading... {0}%&amp;quot;.format(sampleDataLogic.downloadPercent))&lt;br /&gt;
    # Abort download if cancel is clicked in progress bar&lt;br /&gt;
    if slicer.progressWindow.wasCanceled:&lt;br /&gt;
        raise Exception('download aborted')&lt;br /&gt;
    # Update progress window&lt;br /&gt;
    slicer.progressWindow.show()&lt;br /&gt;
    slicer.progressWindow.activateWindow()&lt;br /&gt;
    slicer.progressWindow.setValue(int(sampleDataLogic.downloadPercent))&lt;br /&gt;
    slicer.progressWindow.setLabelText(&amp;quot;Downloading...&amp;quot;)&lt;br /&gt;
    # Process events to allow screen to refresh&lt;br /&gt;
    slicer.app.processEvents() &lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    volumeNode = None&lt;br /&gt;
    slicer.progressWindow = slicer.util.createProgressDialog()&lt;br /&gt;
    sampleDataLogic = SampleData.SampleDataLogic()&lt;br /&gt;
    sampleDataLogic.logMessage = reportProgress&lt;br /&gt;
    loadedNodes = sampleDataLogic.downloadFromURL(&lt;br /&gt;
        nodeNames='MRHead',&lt;br /&gt;
        fileNames='MR-head25.nrrd',&lt;br /&gt;
        uris='https://github.com/Slicer/SlicerTestingData/releases/download/SHA256/cc211f0dfd9a05ca3841ce1141b292898b2dd2d3f08286affadf823a7e58df93',&lt;br /&gt;
        checksums='SHA256:cc211f0dfd9a05ca3841ce1141b292898b2dd2d3f08286affadf823a7e58df93')&lt;br /&gt;
    volumeNode = loadedNodes[0]&lt;br /&gt;
finally:&lt;br /&gt;
    slicer.progressWindow.close()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Automatically load volumes that are copied into a folder==&lt;br /&gt;
&lt;br /&gt;
This example shows how to implement a simple background task by using a timer. The background task is to check for any new volume files in folder and if there is any then automatically load it.&lt;br /&gt;
&lt;br /&gt;
There are more efficient methods for file system monitoring or exchanging image data in real-time (for example, using OpenIGTLink), the example below is just for demonstration purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
incomingVolumeFolder = &amp;quot;c:/tmp/incoming&amp;quot;&lt;br /&gt;
incomingVolumesProcessed = []&lt;br /&gt;
&lt;br /&gt;
def checkForNewVolumes():&lt;br /&gt;
  # Check if there is a new file in the &lt;br /&gt;
  from os import listdir&lt;br /&gt;
  from os.path import isfile, join&lt;br /&gt;
  for f in listdir(incomingVolumeFolder):&lt;br /&gt;
    if f in incomingVolumesProcessed:&lt;br /&gt;
      # this is an incoming file, it was already there&lt;br /&gt;
      continue&lt;br /&gt;
    filePath = join(incomingVolumeFolder, f)&lt;br /&gt;
    if not isfile(filePath):&lt;br /&gt;
      # ignore directories&lt;br /&gt;
      continue&lt;br /&gt;
    logging.info(&amp;quot;Loading new file: &amp;quot;+f)&lt;br /&gt;
    incomingVolumesProcessed.append(f)&lt;br /&gt;
    slicer.util.loadVolume(filePath)&lt;br /&gt;
  # Check again in 3000ms&lt;br /&gt;
  qt.QTimer.singleShot(3000, checkForNewVolumes)&lt;br /&gt;
&lt;br /&gt;
# Start monitoring&lt;br /&gt;
checkForNewVolumes()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
===How to load DICOM files into the scene from a folder===&lt;br /&gt;
&lt;br /&gt;
This code loads all DICOM objects into the scene from a file folder. All the registered plugins are evaluated and the one with the highest confidence will be used to load the data. Files are imported into a temporary DICOM database, so the current Slicer DICOM database is not impacted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dicomDataDir = &amp;quot;c:/my/folder/with/dicom-files&amp;quot;  # input folder with DICOM files&lt;br /&gt;
loadedNodeIDs = []  # this list will contain the list of all loaded node IDs&lt;br /&gt;
  &lt;br /&gt;
from DICOMLib import DICOMUtils&lt;br /&gt;
with DICOMUtils.TemporaryDICOMDatabase() as db:&lt;br /&gt;
  DICOMUtils.importDicom(dicomDataDir, db)&lt;br /&gt;
  patientUIDs = db.patients()&lt;br /&gt;
  for patientUID in patientUIDs:&lt;br /&gt;
    loadedNodeIDs.extend(DICOMUtils.loadPatientByUID(patientUID))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to import DICOM files into the application's DICOM database===&lt;br /&gt;
&lt;br /&gt;
This code snippet uses Slicer DICOM browser built-in indexer to import DICOM files into the database. Images are not loaded into the scene, but they show up in the DICOM browser. After import, data sets can be loaded using DICOMUtils functions (e.g., loadPatientByUID) - see above for an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# instantiate a new DICOM browser&lt;br /&gt;
slicer.util.selectModule(&amp;quot;DICOM&amp;quot;)&lt;br /&gt;
dicomBrowser = slicer.modules.DICOMWidget.browserWidget.dicomBrowser&lt;br /&gt;
# use dicomBrowser.ImportDirectoryCopy to make a copy of the files (useful for importing data from removable storage)&lt;br /&gt;
dicomBrowser.importDirectory(dicomFilesDirectory, dicomBrowser.ImportDirectoryAddLink)&lt;br /&gt;
# wait for import to finish before proceeding (optional, if removed then import runs in the background)&lt;br /&gt;
dicomBrowser.waitForImportFinished()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to import DICOM files using DICOMweb===&lt;br /&gt;
&lt;br /&gt;
Download and import DICOM data set using DICOMweb from [https://kheops.online/ Kheops], Google Health API, etc.&lt;br /&gt;
&lt;br /&gt;
How to obtain accessToken:&lt;br /&gt;
&lt;br /&gt;
*Google Cloud: Execute &amp;lt;code&amp;gt;gcloud auth print-access-token&amp;lt;/code&amp;gt; once you have logged in&lt;br /&gt;
*Kheops: create an album, create a sharing link (somethin like &amp;lt;code&amp;gt;https://demo.kheops.online/view/TfYXwbKAW7JYbAgZ7MyISf&amp;lt;/code&amp;gt;), the token is the string after the last slash&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.selectModule(&amp;quot;DICOM&amp;quot;)  # ensure DICOM database is initialized and &lt;br /&gt;
slicer.app.processEvents()&lt;br /&gt;
from DICOMLib import DICOMUtils&lt;br /&gt;
DICOMUtils.importFromDICOMWeb(&lt;br /&gt;
    dicomWebEndpoint=&amp;quot;http://demo.kheops.online/api&amp;quot;,&lt;br /&gt;
    studyInstanceUID=&amp;quot;1.3.6.1.4.1.14519.5.2.1.8421.4009.985792766370191766692237040819&amp;quot;,&lt;br /&gt;
    accessToken=&amp;quot;TfYXwbKAW7JYbAgZ7MyISf&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to access top level tags of DICOM images imported into Slicer?===&lt;br /&gt;
&lt;br /&gt;
For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
db=slicer.dicomDatabase&lt;br /&gt;
patientList=db.patients()&lt;br /&gt;
studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
# Note, fileValue accesses the database of cached top level tags&lt;br /&gt;
# (nested tags are not included)&lt;br /&gt;
print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
# Get tag group,number from dicom dictionary&lt;br /&gt;
import pydicom as dicom&lt;br /&gt;
tagName = &amp;quot;StudyDate&amp;quot;&lt;br /&gt;
tagStr = str(dicom.tag.Tag(tagName))[1:-1].replace(' ','')&lt;br /&gt;
print(db.fileValue(fileList[0],tagStr))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to access DICOM tags nested in a sequence===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # use pydicom to access the full header, which requires&lt;br /&gt;
  # re-reading the dataset instead of using the database cache&lt;br /&gt;
  import pydicom&lt;br /&gt;
  pydicom.dcmread(fileList[0])&lt;br /&gt;
  ds.CTExposureSequence[0].ExposureModulationType&lt;br /&gt;
&lt;br /&gt;
===How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
===How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
===How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
===How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm'); slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
===Export a volume to DICOM file format===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Export a segmentation to DICOM segmentation object===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = ...&lt;br /&gt;
referenceVolumeNode = ...&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Associate segmentation node with a reference volume node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
referenceVolumeShItem = shNode.GetItemByDataNode(referenceVolumeNode)&lt;br /&gt;
studyShItem = shNode.GetItemParent(referenceVolumeShItem)&lt;br /&gt;
segmentationShItem = shNode.GetItemByDataNode(segmentationNode)&lt;br /&gt;
shNode.SetItemParent(segmentationShItem, studyShItem)&lt;br /&gt;
&lt;br /&gt;
# Export to DICOM&lt;br /&gt;
import DICOMSegmentationPlugin&lt;br /&gt;
exporter = DICOMSegmentationPlugin.DICOMSegmentationPluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(segmentationShItem)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
    exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Customize table columns in DICOM browser===&lt;br /&gt;
&lt;br /&gt;
Documentation of methods for changing DICOM browser columns: https://github.com/commontk/CTK/blob/master/Libs/DICOM/Core/ctkDICOMDatabase.h#L354-L375&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().browserWidget.dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database()&lt;br /&gt;
&lt;br /&gt;
# Print list of available columns&lt;br /&gt;
print(dicomDatabase.patientFieldNames)&lt;br /&gt;
print(dicomDatabase.studyFieldNames)&lt;br /&gt;
print(dicomDatabase.seriesFieldNames)&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsComments', True)&lt;br /&gt;
dicomDatabase.setWeightForField('Patients', 'PatientsComments', 8)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Change column width to manual&lt;br /&gt;
dicomDatabase.setFormatForField('Series', 'SeriesDescription', '{&amp;quot;resizeMode&amp;quot;:&amp;quot;interactive&amp;quot;}')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&lt;br /&gt;
# Force database views update&lt;br /&gt;
dicomDatabase.closeDatabase()&lt;br /&gt;
dicomDatabase.openDatabase(dicomBrowser.database().databaseFilename)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
&lt;br /&gt;
*How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
for viewNode in viewNodes:&lt;br /&gt;
  viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Switch to a different module==&lt;br /&gt;
&lt;br /&gt;
This utility function can be used to open a different module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.selectModule('DICOM')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
&lt;br /&gt;
===How to define/edit a circular region of interest in a slice viewer?===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Specify a sphere by multiple of markups points===&lt;br /&gt;
&lt;br /&gt;
Drop multiple markup points at the boundary of the spherical object and and copy-paste the code below into the Python console to get best-fit sphere. Minimum 4 points are required, it is recommended to place the points far from each other for most accurate fit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
from scipy.optimize import least_squares&lt;br /&gt;
import numpy&lt;br /&gt;
&lt;br /&gt;
def fit_sphere_least_squares(x_values, y_values, z_values, initial_parameters, bounds=((-numpy.inf, -numpy.inf, -numpy.inf, -numpy.inf),(numpy.inf, numpy.inf, numpy.inf, numpy.inf))):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Source: https://github.com/thompson318/scikit-surgery-sphere-fitting/blob/master/sksurgeryspherefitting/algorithms/sphere_fitting.py&lt;br /&gt;
    Uses scipy's least squares optimisor to fit a sphere to a set&lt;br /&gt;
    of 3D Points&lt;br /&gt;
    :return: x: an array containing the four fitted parameters&lt;br /&gt;
    :return: ier: int An integer flag. If it is equal to 1, 2, 3 or 4, the&lt;br /&gt;
             solution was found.&lt;br /&gt;
    :param: (x,y,z) three arrays of equal length containing the x, y, and z&lt;br /&gt;
            coordinates.&lt;br /&gt;
    :param: an array containing four initial values (centre, and radius)&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return least_squares(_calculate_residual_sphere, initial_parameters, bounds=bounds, method='trf', jac='3-point', args=(x_values, y_values, z_values))&lt;br /&gt;
&lt;br /&gt;
def _calculate_residual_sphere(parameters, x_values, y_values, z_values):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Source: https://github.com/thompson318/scikit-surgery-sphere-fitting/blob/master/sksurgeryspherefitting/algorithms/sphere_fitting.py&lt;br /&gt;
    Calculates the residual error for an x,y,z coordinates, fitted&lt;br /&gt;
    to a sphere with centre and radius defined by the parameters tuple&lt;br /&gt;
    :return: The residual error&lt;br /&gt;
    :param: A tuple of the parameters to be optimised, should contain [x_centre, y_centre, z_centre, radius]&lt;br /&gt;
    :param: arrays containing the x,y, and z coordinates.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    #extract the parameters&lt;br /&gt;
    x_centre, y_centre, z_centre, radius = parameters&lt;br /&gt;
    #use numpy's sqrt function here, which works by element on arrays&lt;br /&gt;
    distance_from_centre = numpy.sqrt((x_values - x_centre)**2 + (y_values - y_centre)**2 + (z_values - z_centre)**2)&lt;br /&gt;
    return distance_from_centre - radius&lt;br /&gt;
&lt;br /&gt;
# Fit a sphere to the markups fidicual points&lt;br /&gt;
markupsPositions = slicer.util.arrayFromMarkupsControlPoints(markups)&lt;br /&gt;
import numpy as np&lt;br /&gt;
# initial guess&lt;br /&gt;
center0 = np.mean(markupsPositions, 0)&lt;br /&gt;
radius0 = np.linalg.norm(np.amin(markupsPositions,0)-np.amax(markupsPositions,0))/2.0&lt;br /&gt;
fittingResult = fit_sphere_least_squares(markupsPositions[:,0], markupsPositions[:,1], markupsPositions[:,2], [center0[0], center0[1], center0[2], radius0])&lt;br /&gt;
[centerX, centerY, centerZ, radius] = fittingResult['x']&lt;br /&gt;
&lt;br /&gt;
# Create a sphere using the fitted parameters&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
sphere.SetPhiResolution(30)&lt;br /&gt;
sphere.SetThetaResolution(30)&lt;br /&gt;
sphere.SetCenter(centerX, centerY, centerZ)&lt;br /&gt;
sphere.SetRadius(radius)&lt;br /&gt;
sphere.Update()&lt;br /&gt;
 &lt;br /&gt;
# Add the sphere to the scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two slice planes==&lt;br /&gt;
&lt;br /&gt;
Measure angle between red and yellow slice nodes. Whenever any of the slice nodes are moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeIds = ['vtkMRMLSliceNodeRed', 'vtkMRMLSliceNodeYellow']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    sliceNormalVector = []&lt;br /&gt;
    for sliceNodeId in sliceNodeIds:&lt;br /&gt;
        sliceToRAS = slicer.mrmlScene.GetNodeByID(sliceNodeId).GetSliceToRAS()&lt;br /&gt;
        sliceNormalVector.append([sliceToRAS.GetElement(0,2), sliceToRAS.GetElement(1,2), sliceToRAS.GetElement(2,2)])&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(sliceNormalVector[0], sliceNormalVector[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between slice planes = {0:0.3f}'.format(angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe slice node changes&lt;br /&gt;
for sliceNodeId in sliceNodeIds:&lt;br /&gt;
    slicer.mrmlScene.GetNodeByID(sliceNodeId).AddObserver(vtk.vtkCommand.ModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two markup planes==&lt;br /&gt;
&lt;br /&gt;
Measure angle between two markup plane nodes. Whenever any of the plane nodes are moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
planeNodeNames = ['P', 'P_1']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    planeNormalVectors = []&lt;br /&gt;
    for planeNodeName in planeNodeNames:&lt;br /&gt;
        planeNode = slicer.util.getFirstNodeByClassByName('vtkMRMLMarkupsPlaneNode', planeNodeName)&lt;br /&gt;
        planeNormalVector = [0.0, 0.0, 0.0]&lt;br /&gt;
        planeNode.GetNormalWorld(planeNormalVector)&lt;br /&gt;
        planeNormalVectors.append(planeNormalVector)&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(planeNormalVectors[0], planeNormalVectors[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between planes {0} and {1} = {2:0.3f}'.format(planeNodeNames[0], planeNodeNames[1], angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe plane node changes&lt;br /&gt;
for planeNodeName in planeNodeNames:&lt;br /&gt;
    planeNode = slicer.util.getFirstNodeByClassByName('vtkMRMLMarkupsPlaneNode', planeNodeName)&lt;br /&gt;
    planeNode.AddObserver(slicer.vtkMRMLMarkupsPlaneNode.PointModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two markup lines==&lt;br /&gt;
&lt;br /&gt;
Measure angle between two markup line nodes. Whenever either line is moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineNodeNames = ['L', 'L_1']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    import numpy as np&lt;br /&gt;
    lineDirectionVectors = []&lt;br /&gt;
    for lineNodeName in lineNodeNames:&lt;br /&gt;
        lineNode = slicer.util.getFirstNodeByClassByName('vtkMRMLMarkupsLineNode', lineNodeName)&lt;br /&gt;
        lineStartPos = np.zeros(3)&lt;br /&gt;
        lineEndPos = np.zeros(3)&lt;br /&gt;
        lineNode.GetNthControlPointPositionWorld(0, lineStartPos)&lt;br /&gt;
        lineNode.GetNthControlPointPositionWorld(1, lineEndPos)&lt;br /&gt;
        lineDirectionVector = (lineEndPos-lineStartPos)/np.linalg.norm(lineEndPos-lineStartPos)&lt;br /&gt;
        lineDirectionVectors.append(lineDirectionVector)&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(lineDirectionVectors[0], lineDirectionVectors[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between lines {0} and {1} = {2:0.3f}'.format(lineNodeNames[0], lineNodeNames[1], angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe line node changes&lt;br /&gt;
for lineNodeName in lineNodeNames:&lt;br /&gt;
    lineNode = slicer.util.getFirstNodeByClassByName('vtkMRMLMarkupsLineNode', lineNodeName)&lt;br /&gt;
    lineNode.AddObserver(slicer.vtkMRMLMarkupsLineNode.PointModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from a normal vector and position==&lt;br /&gt;
&lt;br /&gt;
This code snippet shows how to display a slice view defined by a normal vector and position in an anatomically sensible way: rotating slice view so that &amp;quot;up&amp;quot; direction (or &amp;quot;right&amp;quot; direction) is towards an anatomical axis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition, defaultViewUpDirection=None, backupViewRightDirection=None):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Set slice pose from the provided plane normal and position. View up direction is determined automatically,&lt;br /&gt;
    to make view up point towards defaultViewUpDirection.&lt;br /&gt;
    :param defaultViewUpDirection Slice view will be spinned in-plane to match point approximately this up direction. Default: patient superior.&lt;br /&gt;
    :param backupViewRightDirection Slice view will be spinned in-plane to match point approximately this right direction&lt;br /&gt;
        if defaultViewUpDirection is too similar to sliceNormal. Default: patient left.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Fix up input directions&lt;br /&gt;
    if defaultViewUpDirection is None:&lt;br /&gt;
        defaultViewUpDirection = [0,0,1]&lt;br /&gt;
    if backupViewRightDirection is None:&lt;br /&gt;
        backupViewRightDirection = [-1,0,0]&lt;br /&gt;
    if sliceNormal[1]&amp;gt;=0:&lt;br /&gt;
        sliceNormalStandardized = sliceNormal&lt;br /&gt;
    else:&lt;br /&gt;
        sliceNormalStandardized = [-sliceNormal[0], -sliceNormal[1], -sliceNormal[2]]&lt;br /&gt;
    # Compute slice axes&lt;br /&gt;
    sliceNormalViewUpAngle = vtk.vtkMath.AngleBetweenVectors(sliceNormalStandardized, defaultViewUpDirection)&lt;br /&gt;
    angleTooSmallThresholdRad = 0.25 # about 15 degrees&lt;br /&gt;
    if sliceNormalViewUpAngle &amp;gt; angleTooSmallThresholdRad and sliceNormalViewUpAngle &amp;lt; vtk.vtkMath.Pi() - angleTooSmallThresholdRad:&lt;br /&gt;
        viewUpDirection = defaultViewUpDirection&lt;br /&gt;
        sliceAxisY = viewUpDirection&lt;br /&gt;
        sliceAxisX = [0, 0, 0]&lt;br /&gt;
        vtk.vtkMath.Cross(sliceAxisY, sliceNormalStandardized, sliceAxisX)&lt;br /&gt;
    else:&lt;br /&gt;
        sliceAxisX = backupViewRightDirection&lt;br /&gt;
    # Set slice axes&lt;br /&gt;
    sliceNode.SetSliceToRASByNTP(sliceNormalStandardized[0], sliceNormalStandardized[1], sliceNormalStandardized[2],&lt;br /&gt;
        sliceAxisX[0], sliceAxisX[1], sliceAxisX[2],&lt;br /&gt;
        slicePosition[0], slicePosition[1], slicePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Example usage:&lt;br /&gt;
sliceNode = getNode('vtkMRMLSliceNodeRed')&lt;br /&gt;
transformNode = getNode('Transform_3')&lt;br /&gt;
transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
transformNode.GetMatrixTransformToParent(transformMatrix)&lt;br /&gt;
sliceNormal = [transformMatrix.GetElement(0,2), transformMatrix.GetElement(1,2), transformMatrix.GetElement(2,2)]&lt;br /&gt;
slicePosition = [transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)]&lt;br /&gt;
setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Extract randomly oriented slabs of given shape from a volume==&lt;br /&gt;
&lt;br /&gt;
Returns a numpy array of sliceCount random tiles.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def randomSlices(volume, sliceCount, sliceShape):&lt;br /&gt;
    layoutManager = slicer.app.layoutManager()&lt;br /&gt;
    redWidget = layoutManager.sliceWidget('Red')&lt;br /&gt;
    sliceNode = redWidget.mrmlSliceNode()&lt;br /&gt;
    sliceNode.SetDimensions(*sliceShape, 1)&lt;br /&gt;
    sliceNode.SetFieldOfView(*sliceShape, 1)&lt;br /&gt;
    bounds = [0]*6&lt;br /&gt;
    volume.GetRASBounds(bounds)&lt;br /&gt;
    imageReslice = redWidget.sliceLogic().GetBackgroundLayer().GetReslice()&lt;br /&gt;
&lt;br /&gt;
    sliceSize = sliceShape[0] * sliceShape[1]&lt;br /&gt;
    X = numpy.zeros([sliceCount, sliceSize])&lt;br /&gt;
&lt;br /&gt;
    for sliceIndex in range(sliceCount):&lt;br /&gt;
        position = numpy.random.rand(3) * 2 - 1&lt;br /&gt;
        position = [bounds[0] + bounds[1]-bounds[0] * position[0],&lt;br /&gt;
                    bounds[2] + bounds[3]-bounds[2] * position[1],&lt;br /&gt;
                    bounds[4] + bounds[5]-bounds[4] * position[2]]&lt;br /&gt;
        normal = numpy.random.rand(3) * 2 - 1&lt;br /&gt;
        normal = normal / numpy.linalg.norm(normal)&lt;br /&gt;
        transverse = numpy.cross(normal, [0,0,1])&lt;br /&gt;
        orientation = 0&lt;br /&gt;
        sliceNode.SetSliceToRASByNTP( normal[0], normal[1], normal[2], &lt;br /&gt;
                                      transverse[0], transverse[1], transverse[2], &lt;br /&gt;
                                      position[0], position[1], position[2],&lt;br /&gt;
                                      orientation) &lt;br /&gt;
        if sliceIndex % 100 == 0:&lt;br /&gt;
            slicer.app.processEvents()&lt;br /&gt;
        imageReslice.Update()&lt;br /&gt;
        imageData = imageReslice.GetOutputDataObject(0)&lt;br /&gt;
        array = vtk.util.numpy_support.vtk_to_numpy(imageData.GetPointData().GetScalars())&lt;br /&gt;
        X[sliceIndex] = array&lt;br /&gt;
    return X&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Switching to markup fiducial placement mode==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change markup fiducial display properties==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get a notification if a markup point position is modified==&lt;br /&gt;
&lt;br /&gt;
Event management of Slicer-4.11 version is still subject to change. The example below shows how point manipulation can be observed now.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupChanged(caller,event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    if movingMarkupIndex &amp;gt;= 0:&lt;br /&gt;
        pos = [0,0,0]&lt;br /&gt;
        markupsNode.GetNthFiducialPosition(movingMarkupIndex, pos)&lt;br /&gt;
        isPreview = markupsNode.GetNthControlPointPositionStatus(movingMarkupIndex) == slicer.vtkMRMLMarkupsNode.PositionPreview&lt;br /&gt;
        if isPreview:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} is previewed at {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
        else:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} was moved {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
    else:&lt;br /&gt;
        logging.info(&amp;quot;Points modified: slice view = {0}&amp;quot;.format(sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupStartInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()    &lt;br /&gt;
    logging.info(&amp;quot;Start interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupEndInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    logging.info(&amp;quot;End interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, onMarkupChanged)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointStartInteractionEvent, onMarkupStartInteraction)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointEndInteractionEvent, onMarkupEndInteraction)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get a notification if a transform is modified==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate a node around a specified point==&lt;br /&gt;
&lt;br /&gt;
Set up the scene:&lt;br /&gt;
&lt;br /&gt;
*Add a markup fiducial node (centerOfRotationMarkupsNode) with a single point to specify center of rotation.&lt;br /&gt;
*Add a rotation transform (rotationTransformNode) that will be edited in Transforms module to specify rotation angles.&lt;br /&gt;
*Add a transform (finalTransformNode) and apply it (not harden) to those nodes (images, models, etc.) that you want to rotate around the center of rotation point.&lt;br /&gt;
&lt;br /&gt;
Then run the script below, go to Transforms module, select rotationTransformNode, and move rotation sliders.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# This markups fiducial node specifies the center of rotation&lt;br /&gt;
centerOfRotationMarkupsNode = getNode('F')&lt;br /&gt;
# This transform can be  edited in Transforms module&lt;br /&gt;
rotationTransformNode = getNode('LinearTransform_3')&lt;br /&gt;
# This transform has to be applied to the image, model, etc.&lt;br /&gt;
finalTransformNode = getNode('LinearTransform_4')&lt;br /&gt;
&lt;br /&gt;
def updateFinalTransform(unusedArg1=None, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
    rotationMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
    rotationTransformNode.GetMatrixTransformToParent(rotationMatrix)&lt;br /&gt;
    rotationCenterPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
    centerOfRotationMarkupsNode.GetNthControlPointPositionWorld(0, rotationCenterPointCoord)&lt;br /&gt;
    finalTransform = vtk.vtkTransform()&lt;br /&gt;
    finalTransform.Translate(rotationCenterPointCoord)&lt;br /&gt;
    finalTransform.Concatenate(rotationMatrix)&lt;br /&gt;
    finalTransform.Translate(-rotationCenterPointCoord[0], -rotationCenterPointCoord[1], -rotationCenterPointCoord[2])&lt;br /&gt;
    finalTransformNode.SetAndObserveMatrixTransformToParent(finalTransform.GetMatrix())&lt;br /&gt;
&lt;br /&gt;
# Manual initial update&lt;br /&gt;
updateFinalTransform()&lt;br /&gt;
&lt;br /&gt;
# Automatic update when point is moved or transform is modified&lt;br /&gt;
rotationTransformNodeObserver = rotationTransformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, updateFinalTransform)&lt;br /&gt;
centerOfRotationMarkupsNodeObserver = centerOfRotationMarkupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, updateFinalTransform)&lt;br /&gt;
&lt;br /&gt;
# Execute these lines to stop automatic updates:&lt;br /&gt;
# rotationTransformNode.RemoveObserver(rotationTransformNodeObserver)&lt;br /&gt;
# centerOfRotationMarkupsNode.RemoveObserver(centerOfRotationMarkupsNodeObserver)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate a node around a specified line==&lt;br /&gt;
&lt;br /&gt;
Set up the scene:&lt;br /&gt;
&lt;br /&gt;
*Add a markup line node (rotationAxisMarkupsNode) with 2 points to specify rotation axis.&lt;br /&gt;
*Add a rotation transform (rotationTransformNode) that will be edited in Transforms module to specify rotation angle.&lt;br /&gt;
*Add a transform (finalTransformNode) and apply it (not harden) to those nodes (images, models, etc.) that you want to rotate around the line.&lt;br /&gt;
&lt;br /&gt;
Then run the script below, go to Transforms module, select rotationTransformNode, and move Edit / Rotation / IS slider.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# This markups fiducial node specifies the center of rotation&lt;br /&gt;
rotationAxisMarkupsNode = getNode('L')&lt;br /&gt;
# This transform can be edited in Transforms module (Edit / Rotation / IS slider)&lt;br /&gt;
rotationTransformNode = getNode('LinearTransform_3')&lt;br /&gt;
# This transform has to be applied to the image, model, etc.&lt;br /&gt;
finalTransformNode = getNode('LinearTransform_4')&lt;br /&gt;
&lt;br /&gt;
def updateFinalTransform(unusedArg1=None, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
    import numpy as np&lt;br /&gt;
    rotationAxisPoint1_World = np.zeros(3)&lt;br /&gt;
    rotationAxisMarkupsNode.GetNthControlPointPositionWorld(0, rotationAxisPoint1_World)&lt;br /&gt;
    rotationAxisPoint2_World = np.zeros(3)&lt;br /&gt;
    rotationAxisMarkupsNode.GetNthControlPointPositionWorld(1, rotationAxisPoint2_World)&lt;br /&gt;
    axisDirectionZ_World = rotationAxisPoint2_World-rotationAxisPoint1_World&lt;br /&gt;
    axisDirectionZ_World = axisDirectionZ_World/np.linalg.norm(axisDirectionZ_World)&lt;br /&gt;
    # Get transformation between world coordinate system and rotation axis aligned coordinate system&lt;br /&gt;
    worldToRotationAxisTransform = vtk.vtkMatrix4x4()&lt;br /&gt;
    p=vtk.vtkPlaneSource()&lt;br /&gt;
    p.SetNormal(axisDirectionZ_World)&lt;br /&gt;
    axisOrigin = np.array(p.GetOrigin())&lt;br /&gt;
    axisDirectionX_World = np.array(p.GetPoint1())-axisOrigin&lt;br /&gt;
    axisDirectionY_World = np.array(p.GetPoint2())-axisOrigin&lt;br /&gt;
    rotationAxisToWorldTransform = np.row_stack((np.column_stack((axisDirectionX_World, axisDirectionY_World, axisDirectionZ_World, rotationAxisPoint1_World)), (0, 0, 0, 1)))&lt;br /&gt;
    rotationAxisToWorldTransformMatrix = slicer.util.vtkMatrixFromArray(rotationAxisToWorldTransform)&lt;br /&gt;
    worldToRotationAxisTransformMatrix = slicer.util.vtkMatrixFromArray(np.linalg.inv(rotationAxisToWorldTransform))&lt;br /&gt;
    # Compute transformation chain&lt;br /&gt;
    rotationMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
    rotationTransformNode.GetMatrixTransformToParent(rotationMatrix)&lt;br /&gt;
    finalTransform = vtk.vtkTransform()&lt;br /&gt;
    finalTransform.Concatenate(rotationAxisToWorldTransformMatrix)&lt;br /&gt;
    finalTransform.Concatenate(rotationMatrix)&lt;br /&gt;
    finalTransform.Concatenate(worldToRotationAxisTransformMatrix)&lt;br /&gt;
    finalTransformNode.SetAndObserveMatrixTransformToParent(finalTransform.GetMatrix())&lt;br /&gt;
&lt;br /&gt;
# Manual initial update&lt;br /&gt;
updateFinalTransform()&lt;br /&gt;
&lt;br /&gt;
# Automatic update when point is moved or transform is modified&lt;br /&gt;
rotationTransformNodeObserver = rotationTransformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, updateFinalTransform)&lt;br /&gt;
rotationAxisMarkupsNodeObserver = rotationAxisMarkupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, updateFinalTransform)&lt;br /&gt;
&lt;br /&gt;
# Execute these lines to stop automatic updates:&lt;br /&gt;
# rotationTransformNode.RemoveObserver(rotationTransformNodeObserver)&lt;br /&gt;
# rotationAxisMarkupsNode.RemoveObserver(rotationAxisMarkupsNodeObserver)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a context menu when a markup point is clicked in a slice or 3D view==&lt;br /&gt;
&lt;br /&gt;
Subject hierarchy plugins can offer actions in the view context menu when right-clicking objects that support such picking (such as Markups fiducials). A comprehensive [https://github.com/Slicer/Slicer/blob/master/Modules/Loadable/Annotations/SubjectHierarchyPlugins/AnnotationsSubjectHierarchyPlugin.py subject hierarchy plugin example] is for the Annotations module.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  def viewContextMenuActions(self):&lt;br /&gt;
    return [self.doSomething]&lt;br /&gt;
&lt;br /&gt;
  def showViewContextMenuActionsForItem(self, itemID, eventData):&lt;br /&gt;
    if not itemID:&lt;br /&gt;
      logging.error('Invalid item for view context menu ' + str(itemID))&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    pluginHandlerSingleton = slicer.qSlicerSubjectHierarchyPluginHandler.instance()&lt;br /&gt;
    shNode = pluginHandlerSingleton.subjectHierarchyNode()&lt;br /&gt;
    if shNode is None:&lt;br /&gt;
      logging.error('Failed to access subject hierarchy node')&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    associatedNode = shNode.GetItemDataNode(itemID)&lt;br /&gt;
    if not associatedNode or not associatedNode.IsA(&amp;quot;vtkMRMLMarkupsNode&amp;quot;):&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    self.viewMenuEventData = eventData&lt;br /&gt;
    self.viewMenuEventData['NodeID'] = associatedNode.GetID()&lt;br /&gt;
&lt;br /&gt;
  def onDoSomething(self):&lt;br /&gt;
    nodeID = self.viewMenuEventData['NodeID']&lt;br /&gt;
    markupsNode = slicer.mrmlScene.GetNodeByID(nodeID)&lt;br /&gt;
    if markupsNode is None or not markupsNode.IsA(&amp;quot;vtkMRMLMarkupsNode&amp;quot;):&lt;br /&gt;
      logging.error('Failed to get fiducial markups node by ID ' + str(nodeID))&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    componentIndex = self.viewMenuEventData['ComponentIndex']&lt;br /&gt;
    markupID = markupsNode.GetNthMarkupID(componentIndex)&lt;br /&gt;
    &lt;br /&gt;
    # Do something with the clicked fiducial&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Write markup positions to JSON file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Write annotation ROI to JSON file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a simple surface mesh as a model node==&lt;br /&gt;
&lt;br /&gt;
This example shows how to display a simple surface mesh (a box, created by a VTK source filter) as a model node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create and set up polydata source&lt;br /&gt;
box = vtk.vtkCubeSource()&lt;br /&gt;
box.SetXLength(30)&lt;br /&gt;
box.SetYLength(20)&lt;br /&gt;
box.SetZLength(15)&lt;br /&gt;
box.SetCenter(10,20,5)&lt;br /&gt;
&lt;br /&gt;
# Create a model node that displays output of the source&lt;br /&gt;
boxNode = slicer.modules.models.logic().AddModel(box.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Adjust display properties&lt;br /&gt;
boxNode.GetDisplayNode().SetColor(1,0,0)&lt;br /&gt;
boxNode.GetDisplayNode().SetOpacity(0.8)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure distance of points from surface==&lt;br /&gt;
&lt;br /&gt;
This example computes closest distance of points (markups fiducial 'F') from a surface (model node 'mymodel') and writes results into a table.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
modelNode = getNode('mymodel')&lt;br /&gt;
&lt;br /&gt;
# Transform model polydata to world coordinate system&lt;br /&gt;
if modelNode.GetParentTransformNode():&lt;br /&gt;
    transformModelToWorld = vtk.vtkGeneralTransform()&lt;br /&gt;
    slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(modelNode.GetParentTransformNode(), None, transformModelToWorld)&lt;br /&gt;
    polyTransformToWorld = vtk.vtkTransformPolyDataFilter()&lt;br /&gt;
    polyTransformToWorld.SetTransform(transformModelToWorld)&lt;br /&gt;
    polyTransformToWorld.SetInputData(modelNode.GetPolyData())&lt;br /&gt;
    polyTransformToWorld.Update()&lt;br /&gt;
    surface_World = polyTransformToWorld.GetOutput()&lt;br /&gt;
else:&lt;br /&gt;
    surface_World = modelNode.GetPolyData()&lt;br /&gt;
&lt;br /&gt;
# Create arrays to store results&lt;br /&gt;
indexCol = vtk.vtkIntArray()&lt;br /&gt;
indexCol.SetName(&amp;quot;Index&amp;quot;)&lt;br /&gt;
labelCol = vtk.vtkStringArray()&lt;br /&gt;
labelCol.SetName(&amp;quot;Name&amp;quot;)&lt;br /&gt;
distanceCol = vtk.vtkDoubleArray()&lt;br /&gt;
distanceCol.SetName(&amp;quot;Distance&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
distanceFilter = vtk.vtkImplicitPolyDataDistance()&lt;br /&gt;
distanceFilter.SetInput(surface_World);&lt;br /&gt;
nOfFiduciallPoints = markupsNode.GetNumberOfFiducials()&lt;br /&gt;
for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    point_World = [0,0,0]&lt;br /&gt;
    markupsNode.GetNthControlPointPositionWorld(i, point_World)&lt;br /&gt;
    closestPointOnSurface_World = [0,0,0]&lt;br /&gt;
    closestPointDistance = distanceFilter.EvaluateFunctionAndGetClosestPoint(point_World, closestPointOnSurface_World)&lt;br /&gt;
    indexCol.InsertNextValue(i)&lt;br /&gt;
    labelCol.InsertNextValue(markupsNode.GetNthControlPointLabel(i))&lt;br /&gt;
    distanceCol.InsertNextValue(closestPointDistance)&lt;br /&gt;
&lt;br /&gt;
# Create a table from result arrays&lt;br /&gt;
resultTableNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;, &amp;quot;Points from surface distance&amp;quot;)&lt;br /&gt;
resultTableNode.AddColumn(indexCol)&lt;br /&gt;
resultTableNode.AddColumn(labelCol)&lt;br /&gt;
resultTableNode.AddColumn(distanceCol)&lt;br /&gt;
&lt;br /&gt;
# Show table in view layout&lt;br /&gt;
slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpTableView)&lt;br /&gt;
slicer.app.applicationLogic().GetSelectionNode().SetReferenceActiveTableID(resultTableNode.GetID())&lt;br /&gt;
slicer.app.applicationLogic().PropagateTableSelection()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Add a texture mapped plane to the scene as a model==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create model node&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
planeSource.SetOrigin(-50.0, -50.0, 0.0)&lt;br /&gt;
planeSource.SetPoint1(50.0, -50.0, 0.0)&lt;br /&gt;
planeSource.SetPoint2(-50.0, 50.0, 0.0)&lt;br /&gt;
model = slicer.modules.models.logic().AddModel(planeSource.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Tune display properties&lt;br /&gt;
modelDisplay = model.GetDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
&lt;br /&gt;
# Add texture (just use image of an ellipsoid)&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
modelDisplay.SetTextureImageDataConnection(e.GetOutputPort())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get scalar values at surface of a model==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Select cells of a model using markups fiducial points==&lt;br /&gt;
&lt;br /&gt;
The following script selects cells of a model node that are closest to positions of markups fiducial points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get input nodes&lt;br /&gt;
modelNode = slicer.util.getNode('Segment_1') # select cells in this model&lt;br /&gt;
markupsNode = slicer.util.getNode('F') # points will be selected at positions specified by this markups fiducial node&lt;br /&gt;
&lt;br /&gt;
# Create scalar array that will store selection state&lt;br /&gt;
cellScalars = modelNode.GetMesh().GetCellData()&lt;br /&gt;
selectionArray = cellScalars.GetArray('selection')&lt;br /&gt;
if not selectionArray:&lt;br /&gt;
    selectionArray = vtk.vtkIntArray()&lt;br /&gt;
    selectionArray.SetName('selection')&lt;br /&gt;
    selectionArray.SetNumberOfValues(modelNode.GetMesh().GetNumberOfCells())&lt;br /&gt;
    selectionArray.Fill(0)&lt;br /&gt;
    cellScalars.AddArray(selectionArray)&lt;br /&gt;
&lt;br /&gt;
# Set up coloring by selection array&lt;br /&gt;
modelNode.GetDisplayNode().SetActiveScalar(&amp;quot;selection&amp;quot;, vtk.vtkAssignAttribute.CELL_DATA)&lt;br /&gt;
modelNode.GetDisplayNode().SetAndObserveColorNodeID(&amp;quot;vtkMRMLColorTableNodeWarm1&amp;quot;)&lt;br /&gt;
modelNode.GetDisplayNode().SetScalarVisibility(True)&lt;br /&gt;
&lt;br /&gt;
# Initialize cell locator&lt;br /&gt;
cell = vtk.vtkCellLocator()&lt;br /&gt;
cell.SetDataSet(modelNode.GetMesh())&lt;br /&gt;
cell.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onPointsModified(observer=None, eventid=None):&lt;br /&gt;
    global markupsNode, selectionArray&lt;br /&gt;
    selectionArray.Fill(0) # set all cells to non-selected by default&lt;br /&gt;
    markupPoints = slicer.util.arrayFromMarkupsControlPoints(markupsNode)&lt;br /&gt;
    closestPoint = [0.0, 0.0, 0.0]&lt;br /&gt;
    cellObj = vtk.vtkGenericCell()&lt;br /&gt;
    cellId = vtk.mutable(0)&lt;br /&gt;
    subId = vtk.mutable(0)&lt;br /&gt;
    dist2 = vtk.mutable(0.0)&lt;br /&gt;
    for markupPoint in markupPoints:&lt;br /&gt;
        cell.FindClosestPoint(markupPoint, closestPoint, cellObj, cellId, subId, dist2)&lt;br /&gt;
        closestCell = cellId.get()&lt;br /&gt;
        if closestCell &amp;gt;=0:&lt;br /&gt;
            selectionArray.SetValue(closestCell, 100) # set selected cell's scalar value to non-zero&lt;br /&gt;
    selectionArray.Modified()&lt;br /&gt;
&lt;br /&gt;
# Initial update&lt;br /&gt;
onPointsModified()&lt;br /&gt;
# Automatic update each time when a markup point is modified&lt;br /&gt;
markupsNodeObserverTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsFiducialNode.PointModifiedEvent, onPointsModified)&lt;br /&gt;
&lt;br /&gt;
# To stop updating selection, run this:&lt;br /&gt;
# markupsNode.RemoveObserver(markupsNodeObserverTag)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Load volume from .vti file==&lt;br /&gt;
&lt;br /&gt;
Slicer does not provide reader for VTK XML image data file format (as they are not commonly used for storing medical images and they cannot store image axis directions) but such files can be read by using this script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
reader=vtk.vtkXMLImageDataReader()&lt;br /&gt;
reader.SetFileName(&amp;quot;/path/to/file.vti&amp;quot;)&lt;br /&gt;
reader.Update()&lt;br /&gt;
imageData = reader.GetOutput()&lt;br /&gt;
spacing = imageData.GetSpacing()&lt;br /&gt;
origin = imageData.GetOrigin()&lt;br /&gt;
imageData.SetOrigin(0,0,0)&lt;br /&gt;
imageData.SetSpacing(1,1,1)&lt;br /&gt;
volumeNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
volumeNode.SetSpacing(spacing)&lt;br /&gt;
volumeNode.SetOrigin(origin)&lt;br /&gt;
slicer.util.setSliceViewerLayers(volumeNode, fit=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export entire scene as VRML==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export model to Blender, including color by scalar==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export a tract (FiberBundle) to Blender, including color==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Iterate over tract (FiberBundle) streamline points==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Clone a node==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Clone a volume==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create a new volume==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
imageData.GetPointData().GetScalars().Fill(fillVoxelValue)&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get value of a volume at specific voxel coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel value of &amp;quot;volumeNode&amp;quot; at &amp;quot;ijk&amp;quot; volume voxel coordinates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
ijk = [20,40,30]  # volume voxel coordinates&lt;br /&gt;
&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)  # get voxels as a numpy array&lt;br /&gt;
voxelValue = voxels[ijk[2], ijk[1], ijk[0]]  # note that numpy array index order is kji (not ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Modify voxels in a volume==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get volume voxel coordinates from markup fiducial RAS coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get markup fiducial RAS coordinates from volume voxel coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get the values of all voxels for a label value==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array('Volume')&lt;br /&gt;
label = array('Volume-label')&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt('values.txt', values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Access values in a DTI tensor volume==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change window/level (brightness/contrast) or colormap of a volume==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Make mouse left-click and drag on the image adjust window/level==&lt;br /&gt;
&lt;br /&gt;
In older Slicer versions, by default, left-click and drag in a slice view adjusted window/level of the displayed image. Window/level adjustment is now a new mouse mode that can be activated by clicking on its toolbar button or running this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.applicationLogic().GetInteractionNode().SetCurrentInteractionMode(slicer.vtkMRMLInteractionNode.AdjustWindowLevel)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create custom color table==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manipulate a Slice View==&lt;br /&gt;
&lt;br /&gt;
===Change slice offset===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Change slice orientation===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Show slice views in 3D window===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Reset field of view to show background volume maximized===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rotate slice views to volume plane===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Iterate over current visible slice views, and set foreground and background images===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     compositeNode = layoutManager.sliceWidget(sliceViewName).sliceLogic().GetSliceCompositeNode()&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a volume in slice views==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show comparison view of all model files a folder==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
modelDir = &amp;quot;c:/some/folder/containing/models&amp;quot;&lt;br /&gt;
modelFileExt = &amp;quot;stl&amp;quot;&lt;br /&gt;
numberOfColumns = 4&lt;br /&gt;
&lt;br /&gt;
import math&lt;br /&gt;
import os&lt;br /&gt;
modelFiles = list(f for f in os.listdir(modelDir) if f.endswith('.' + modelFileExt))&lt;br /&gt;
&lt;br /&gt;
# Create a custom layout&lt;br /&gt;
numberOfRows = int(math.ceil(len(modelFiles)/numberOfColumns))&lt;br /&gt;
customLayoutId=567  # we pick a random id that is not used by others&lt;br /&gt;
slicer.app.setRenderPaused(True)&lt;br /&gt;
customLayout = '&amp;lt;layout type=&amp;quot;vertical&amp;quot;&amp;gt;'&lt;br /&gt;
viewIndex = 0&lt;br /&gt;
for rowIndex in range(numberOfRows):&lt;br /&gt;
  customLayout += '&amp;lt;item&amp;gt;&amp;lt;layout type=&amp;quot;horizontal&amp;quot;&amp;gt;'&lt;br /&gt;
  for colIndex in range(numberOfColumns):&lt;br /&gt;
    name = os.path.basename(modelFiles[viewIndex]) if viewIndex &amp;lt; len(modelFiles) else &amp;quot;compare &amp;quot;+str(viewIndex)&lt;br /&gt;
    customLayout += '&amp;lt;item&amp;gt;&amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;'+name&lt;br /&gt;
    customLayout += '&amp;quot;&amp;gt;&amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;'+name+'&amp;lt;/property&amp;gt;&amp;lt;/view&amp;gt;&amp;lt;/item&amp;gt;'&lt;br /&gt;
    viewIndex += 1&lt;br /&gt;
  customLayout += '&amp;lt;/layout&amp;gt;&amp;lt;/item&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
customLayout += '&amp;lt;/layout&amp;gt;'&lt;br /&gt;
if not slicer.app.layoutManager().layoutLogic().GetLayoutNode().SetLayoutDescription(customLayoutId, customLayout):&lt;br /&gt;
    slicer.app.layoutManager().layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)&lt;br /&gt;
&lt;br /&gt;
slicer.app.layoutManager().setLayout(customLayoutId)&lt;br /&gt;
&lt;br /&gt;
# Load and show each model in a view&lt;br /&gt;
for modelIndex, modelFile in enumerate(modelFiles):&lt;br /&gt;
    # Show only one model in each view&lt;br /&gt;
    name = os.path.basename(modelFile)&lt;br /&gt;
    viewNode = slicer.mrmlScene.GetSingletonNode(name, &amp;quot;vtkMRMLViewNode&amp;quot;)&lt;br /&gt;
    viewNode.LinkedControlOn()&lt;br /&gt;
    modelNode = slicer.util.loadModel(modelDir+&amp;quot;/&amp;quot;+modelFile)&lt;br /&gt;
    modelNode.GetDisplayNode().AddViewNodeID(viewNode.GetID())&lt;br /&gt;
&lt;br /&gt;
slicer.app.setRenderPaused(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change opacity of foreground volume in slice views==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Fit slice plane to markup fiducials==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.zeros(3)&lt;br /&gt;
p2 = np.zeros(3)&lt;br /&gt;
p3 = np.zeros(3)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0.0, 0.0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save a series of images from a Slice View==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rasterize a model and save it to a series of image files==&lt;br /&gt;
&lt;br /&gt;
This example shows how to generate a stack of image files from an STL file:&lt;br /&gt;
&lt;br /&gt;
 inputModelFile = &amp;quot;/some/input/folder/SomeShape.stl&amp;quot;&lt;br /&gt;
 outputDir = &amp;quot;/some/output/folder&amp;quot;&lt;br /&gt;
 outputVolumeLabelValue = 100&lt;br /&gt;
 outputVolumeSpacingMm = [0.5, 0.5, 0.5]&lt;br /&gt;
 outputVolumeMarginMm = [10.0, 10.0, 10.0]&lt;br /&gt;
 &lt;br /&gt;
 # Read model&lt;br /&gt;
 inputModel = slicer.util.loadModel(inputModelFile)&lt;br /&gt;
 &lt;br /&gt;
 # Determine output volume geometry and create a corresponding reference volume&lt;br /&gt;
 import math&lt;br /&gt;
 import numpy as np&lt;br /&gt;
 bounds = np.zeros(6)&lt;br /&gt;
 inputModel.GetBounds(bounds)&lt;br /&gt;
 imageData = vtk.vtkImageData()&lt;br /&gt;
 imageSize = [ int((bounds[axis*2+1]-bounds[axis*2]+outputVolumeMarginMm[axis]*2.0)/outputVolumeSpacingMm[axis]) for axis in range(3) ]&lt;br /&gt;
 imageOrigin = [ bounds[axis*2]-outputVolumeMarginMm[axis] for axis in range(3) ]&lt;br /&gt;
 imageData.SetDimensions(imageSize)&lt;br /&gt;
 imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1)&lt;br /&gt;
 imageData.GetPointData().GetScalars().Fill(0)&lt;br /&gt;
 referenceVolumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
 referenceVolumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
 referenceVolumeNode.SetSpacing(outputVolumeSpacingMm)&lt;br /&gt;
 referenceVolumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
 referenceVolumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
 &lt;br /&gt;
 # Convert model to labelmap&lt;br /&gt;
 seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
 seg.SetReferenceImageGeometryParameterFromVolumeNode(referenceVolumeNode)&lt;br /&gt;
 slicer.modules.segmentations.logic().ImportModelToSegmentationNode(inputModel, seg)&lt;br /&gt;
 seg.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
 outputLabelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
 slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(seg, outputLabelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
 outputLabelmapVolumeArray = (slicer.util.arrayFromVolume(outputLabelmapVolumeNode) * outputVolumeLabelValue).astype('int8')&lt;br /&gt;
 &lt;br /&gt;
 # Write labelmap volume to series of TIFF files&lt;br /&gt;
 pip_install(&amp;quot;imageio&amp;quot;)&lt;br /&gt;
 import imageio&lt;br /&gt;
 for i in range(len(outputLabelmapVolumeArray)):&lt;br /&gt;
     imageio.imwrite(f'{outputDir}/image_{i:03}.tiff', outputLabelmapVolumeArray[i])&lt;br /&gt;
&lt;br /&gt;
==Save the scene into a new directory==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save the scene into a single MRB file==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save a node to file==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Override default scene save dialog==&lt;br /&gt;
&lt;br /&gt;
Place this class in the scripted module file to override&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MyModuleFileDialog ():&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;This specially named class is detected by the scripted loadable&lt;br /&gt;
   module and is the target for optional drag and drop operations.&lt;br /&gt;
   See: Base/QTGUI/qSlicerScriptedFileDialog.h.&lt;br /&gt;
&lt;br /&gt;
   This class is used for overriding default scene save dialog&lt;br /&gt;
   with simple saving the scene without asking anything.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
   def __init__(self,qSlicerFileDialog ):&lt;br /&gt;
     self.qSlicerFileDialog = qSlicerFileDialog&lt;br /&gt;
     qSlicerFileDialog.fileType = 'NoFile'&lt;br /&gt;
     qSlicerFileDialog.description = 'Save scene'&lt;br /&gt;
     qSlicerFileDialog.action = slicer.qSlicerFileDialog.Write&lt;br /&gt;
&lt;br /&gt;
   def execDialog(self):&lt;br /&gt;
     # Implement custom scene save operation here.&lt;br /&gt;
     # Return True if saving completed successfully,&lt;br /&gt;
     # return False if saving was cancelled.&lt;br /&gt;
     ...&lt;br /&gt;
     return saved&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Override application close behavior==&lt;br /&gt;
&lt;br /&gt;
When application close is requested then by default confirmation popup is displayed.&lt;br /&gt;
To customize this behavior (for example, allow application closing without displaying default confirmation popup)&lt;br /&gt;
an event filter can be installed for the close event on the main window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class CloseApplicationEventFilter(qt.QWidget):&lt;br /&gt;
  def eventFilter(self, object, event):&lt;br /&gt;
    if event.type() == qt.QEvent.Close:&lt;br /&gt;
      event.accept()&lt;br /&gt;
      return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
filter = CloseApplicationEventFilter()&lt;br /&gt;
slicer.util.mainWindow().installEventFilter(filter)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Center the 3D View on the Scene==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Display text in a 3D view or slice view==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To display text in slice views, replace the first line by this line (and consider hiding slice view annotations, to prevent them from overwriting the text you place there):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().sliceWidget(&amp;quot;Red&amp;quot;).sliceView()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide slice view annotations (DataProbe)==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Turning off interpolation==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Customize viewer layout==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;layout type=&amp;quot;vertical&amp;quot; split=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLSliceNode&amp;quot; singletontag=&amp;quot;Red&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;orientation&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewcolor&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/layout&amp;gt;&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Built-in layout IDs are all below 100, so you can choose any large random number&lt;br /&gt;
# for your custom layout ID.&lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
&lt;br /&gt;
# Switch to the new custom layout &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
You can use this code snippet to add a button to the layout selector toolbar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Add button to layout selector toolbar for this custom layout&lt;br /&gt;
viewToolBar = mainWindow().findChild('QToolBar', 'ViewToolBar')&lt;br /&gt;
layoutMenu = viewToolBar.widgetForAction(viewToolBar.actions()[0]).menu()&lt;br /&gt;
layoutSwitchActionParent = layoutMenu  # use `layoutMenu` to add inside layout list, use `viewToolBar` to add next the standard layout list&lt;br /&gt;
layoutSwitchAction = layoutSwitchActionParent.addAction(&amp;quot;My view&amp;quot;) # add inside layout list&lt;br /&gt;
layoutSwitchAction.setData(layoutId)&lt;br /&gt;
layoutSwitchAction.setIcon(qt.QIcon(':Icons/Go.png'))&lt;br /&gt;
layoutSwitchAction.setToolTip('3D and slice view')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Customize keyboard shortcuts==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's an example for cycling through Segment Editor effects (requested [https://discourse.slicer.org/t/is-there-a-keystroke-to-cycle-through-effects-in-segment-editor/10117/2 on the forum] for the [http://slicermorph.org SlicerMorph] project).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def cycleEffect(delta=1):&lt;br /&gt;
    try:&lt;br /&gt;
        orderedNames = list(slicer.modules.SegmentEditorWidget.editor.effectNameOrder())&lt;br /&gt;
        allNames = slicer.modules.SegmentEditorWidget.editor.availableEffectNames()&lt;br /&gt;
        for name in allNames:&lt;br /&gt;
            try:&lt;br /&gt;
                orderedNames.index(name)&lt;br /&gt;
            except ValueError:&lt;br /&gt;
                orderedNames.append(name)&lt;br /&gt;
        orderedNames.insert(0, None)&lt;br /&gt;
        activeEffect = slicer.modules.SegmentEditorWidget.editor.activeEffect()&lt;br /&gt;
        if activeEffect:&lt;br /&gt;
            activeName = slicer.modules.SegmentEditorWidget.editor.activeEffect().name&lt;br /&gt;
        else:&lt;br /&gt;
            activeName = None&lt;br /&gt;
        newIndex = (orderedNames.index(activeName) + delta) % len(orderedNames)&lt;br /&gt;
        slicer.modules.SegmentEditorWidget.editor.setActiveEffectByName(orderedNames[newIndex])&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        # module not active&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('`', lambda: cycleEffect(-1)),&lt;br /&gt;
    ('~', lambda: cycleEffect(1)),&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Customize keyboard/mouse gestures in viewers==&lt;br /&gt;
&lt;br /&gt;
Example for making the 3D view rotate using right-click-and-drag:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
threeDViewWidget = slicer.app.layoutManager().threeDWidget(0)&lt;br /&gt;
cameraDisplayableManager = threeDViewWidget.threeDView().displayableManagerByClassName('vtkMRMLCameraDisplayableManager')&lt;br /&gt;
cameraWidget = cameraDisplayableManager.GetCameraWidget()&lt;br /&gt;
&lt;br /&gt;
# Remove old mapping from right-click-and-drag&lt;br /&gt;
cameraWidget.SetEventTranslationClickAndDrag(cameraWidget.WidgetStateIdle, vtk.vtkCommand.RightButtonPressEvent, vtk.vtkEvent.NoModifier,&lt;br /&gt;
    cameraWidget.WidgetStateRotate, vtk.vtkWidgetEvent.NoEvent, vtk.vtkWidgetEvent.NoEvent)&lt;br /&gt;
&lt;br /&gt;
# Make right-click-and-drag rotate the view&lt;br /&gt;
cameraWidget.SetEventTranslationClickAndDrag(cameraWidget.WidgetStateIdle, vtk.vtkCommand.RightButtonPressEvent, vtk.vtkEvent.NoModifier,&lt;br /&gt;
    cameraWidget.WidgetStateRotate, cameraWidget.WidgetEventRotateStart, cameraWidget.WidgetEventRotateEnd)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Disable certain user interactions in slice views==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change default slice view orientation==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set all slice views linked by default==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  defaultSliceCompositeNode.UnRegister(None)  # CreateNodeByClass is factory method, need to unregister the result to prevent memory leaks&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set crosshair jump mode to centered by default==&lt;br /&gt;
&lt;br /&gt;
You can change default slice jump mode (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
crosshair=slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLCrosshairNode&amp;quot;)&lt;br /&gt;
crosshair.SetCrosshairBehavior(crosshair.CenteredJumpSlice)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set up custom units in slice view ruler==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManager = sliceView.displayableManagerByClassName(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;)&lt;br /&gt;
  displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
  displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
  displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
  displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
  displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
  displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
  displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
  displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
  displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
  displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
  displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
  displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show orientation marker in all views==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodes = slicer.util.getNodesByClass('vtkMRMLAbstractViewNode')&lt;br /&gt;
for viewNode in viewNodes:&lt;br /&gt;
  viewNode.SetOrientationMarkerType(slicer.vtkMRMLAbstractViewNode.OrientationMarkerTypeAxes)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a slice view outside the view layout==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;TestSlice1&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;TS1&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
viewNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(layoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
viewWidget.sliceViewName = layoutName&lt;br /&gt;
viewWidget.sliceViewLabel = layoutLabel&lt;br /&gt;
c = viewNode.GetLayoutColor()&lt;br /&gt;
viewWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLSliceNode(viewNode)&lt;br /&gt;
sliceLogics = slicer.app.applicationLogic().GetSliceLogics()&lt;br /&gt;
viewWidget.setSliceLogics(sliceLogics)&lt;br /&gt;
sliceLogics.AddItem(viewWidget.sliceLogic())&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a 3D view outside the view layout==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;Test3DView&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;T3&amp;quot;&lt;br /&gt;
layoutColor = [1.0, 1.0, 0.0]&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML node&lt;br /&gt;
viewNode = slicer.vtkMRMLViewNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(layoutColor)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLThreeDWidget()&lt;br /&gt;
viewWidget.viewLabel = layoutLabel&lt;br /&gt;
viewWidget.viewColor = qt.QColor.fromRgbF(*layoutColor)&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLViewNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get displayable manager of a certain type for a certain view==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
threeDViewWidget = slicer.app.layoutManager().threeDWidget(0)&lt;br /&gt;
modelDisplayableManager = threeDViewWidget.threeDView().displayableManagerByClassName('vtkMRMLModelDisplayableManager')&lt;br /&gt;
if modelDisplayableManager is None:&lt;br /&gt;
  logging.error('Failed to find the model displayable manager')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Running an ITK filter in Python using SimpleITK==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
&lt;br /&gt;
*See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
*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&lt;br /&gt;
&lt;br /&gt;
==Get current mouse coordinates in a slice view==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get DataProbe text==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get axial slice as numpy array==&lt;br /&gt;
&lt;br /&gt;
An axis-aligned (axial/sagittal/coronal/) slices of a volume can be extracted using simple numpy array indexing. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
sliceIndex = 12&lt;br /&gt;
&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)  # Get volume as numpy array&lt;br /&gt;
slice = voxels[sliceIndex:,:]  # Get one slice of the volume as numpy array&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get reformatted image from a slice viewer as numpy array==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print(voxels.shape)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Combine multiple volumes into one==&lt;br /&gt;
&lt;br /&gt;
This example combines two volumes into a new one by subtracting one from the other.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
[input1Volume, input2Volume] = SampleData.SampleDataLogic().downloadDentalSurgery()&lt;br /&gt;
&lt;br /&gt;
import slicer.util&lt;br /&gt;
a = slicer.util.arrayFromVolume(input1Volume)&lt;br /&gt;
b = slicer.util.arrayFromVolume(input2Volume)&lt;br /&gt;
&lt;br /&gt;
# 'a' and 'b' are numpy arrays,&lt;br /&gt;
# they can be combined using any numpy array operations&lt;br /&gt;
# to produce the result array 'c'&lt;br /&gt;
c = b-a&lt;br /&gt;
&lt;br /&gt;
volumeNode = slicer.modules.volumes.logic().CloneVolume(input1Volume, &amp;quot;Difference&amp;quot;)&lt;br /&gt;
slicer.util.updateVolumeFromArray(volumeNode, c)&lt;br /&gt;
setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Add noise to image==&lt;br /&gt;
&lt;br /&gt;
This example shows how to add simulated noise to a volume.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Get a sample input volume node&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Get volume as numpy array and add noise&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
voxels[:] = voxels + np.random.normal(0.0, 20.0, size=voxels.shape)&lt;br /&gt;
slicer.util.arrayFromVolumeModified(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Mask volume using segmentation==&lt;br /&gt;
&lt;br /&gt;
This example shows how to blank out voxels of a volume outside all segments.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Input nodes&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
&lt;br /&gt;
# Write segmentation to labelmap volume node with a geometry that matches the volume node&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, volumeNode)&lt;br /&gt;
&lt;br /&gt;
# Masking&lt;br /&gt;
import numpy as np&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
mask = slicer.util.arrayFromVolume(labelmapVolumeNode)&lt;br /&gt;
maskedVoxels = np.copy(voxels)  # we don't want to modify the original volume&lt;br /&gt;
maskedVoxels[mask==0] = 0&lt;br /&gt;
&lt;br /&gt;
# Write masked volume to volume node and show it&lt;br /&gt;
maskedVolumeNode = slicer.modules.volumes.logic().CloneVolume(volumeNode, &amp;quot;Masked&amp;quot;)&lt;br /&gt;
slicer.util.updateVolumeFromArray(maskedVolumeNode, maskedVoxels)&lt;br /&gt;
slicer.util.setSliceViewerLayers(maskedVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Apply random deformations to image==&lt;br /&gt;
&lt;br /&gt;
This example shows how to apply random translation, rotation, and deformations to a volume to simulate variation in patient positioning, soft tissue motion, and random anatomical variations.&lt;br /&gt;
Control points are placed on a regularly spaced grid and then each control point is displaced by a random amount.&lt;br /&gt;
Thin-plate spline transform is computed from the original and transformed point list.&lt;br /&gt;
&lt;br /&gt;
https://gist.github.com/lassoan/428af5285da75dc033d32ebff65ba940&lt;br /&gt;
&lt;br /&gt;
==Thick slab reconstruction and maximum/minimum intensity volume projections==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
==Change default file type for nodes (that have never been saved yet)==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
==Change file type for saving for all volumes (with already existing storage nodes)==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Sequences==&lt;br /&gt;
&lt;br /&gt;
===Access voxels of a 4D volume as numpy array===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get sequence node&lt;br /&gt;
import SampleData&lt;br /&gt;
sequenceNode = SampleData.SampleDataLogic().downloadSample('CTPCardioSeq')&lt;br /&gt;
# Alternatively, get the first sequence node in the scene:&lt;br /&gt;
# sequenceNode = slicer.util.getNodesByClass('vtkMRMLSequenceNode')[0]&lt;br /&gt;
&lt;br /&gt;
# Get voxels of itemIndex'th volume as numpy array&lt;br /&gt;
itemIndex = 5&lt;br /&gt;
voxelArray = slicer.util.arrayFromVolume(sequenceNode.GetNthDataNode(itemIndex))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get index value===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
print(&amp;quot;Index value of {0}th item: {1} = {2} {3}&amp;quot;.format(&lt;br /&gt;
  itemIndex,&lt;br /&gt;
  sequenceNode.GetIndexName(),&lt;br /&gt;
  sequenceNode.GetNthIndexValue(itemIndex),&lt;br /&gt;
  sequenceNode.GetIndexUnit()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Browse a sequence and access currently displayed nodes===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a sequence node&lt;br /&gt;
import SampleData&lt;br /&gt;
sequenceNode = SampleData.SampleDataLogic().downloadSample('CTPCardioSeq')&lt;br /&gt;
&lt;br /&gt;
# Find corresponding sequence browser node&lt;br /&gt;
browserNode = slicer.modules.sequences.logic().GetFirstBrowserNodeForSequenceNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Print sequence information&lt;br /&gt;
print(&amp;quot;Number of items in the sequence: {0}&amp;quot;.format(browserNode.GetNumberOfItems()))&lt;br /&gt;
print(&amp;quot;Index name: {0}&amp;quot;.format(browserNode.GetMasterSequenceNode().GetIndexName()))&lt;br /&gt;
&lt;br /&gt;
# Jump to a selected sequence item&lt;br /&gt;
browserNode.SetSelectedItemNumber(5)&lt;br /&gt;
&lt;br /&gt;
# Get currently displayed volume node voxels as numpy array&lt;br /&gt;
volumeNode = browserNode.GetProxyNode(sequenceNode)&lt;br /&gt;
voxelArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
===Concatenate all sequences in the scene into a new sequence===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Segmentations==&lt;br /&gt;
&lt;br /&gt;
===Create a segmentation from a labelmap volume and display in 3D===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
===Export labelmap node from segmentation node===&lt;br /&gt;
&lt;br /&gt;
Export labelmap matching reference geometry of the segmentation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, slicer.vtkSegmentation.EXTENT_REFERENCE_GEOMETRY)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export smallest possible labelmap:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export labelmap that matches geometry of a chosen reference volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Export a selection of segments (identified by their names):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentNames = [&amp;quot;Prostate&amp;quot;, &amp;quot;Urethra&amp;quot;]&lt;br /&gt;
segmentIds = vtk.vtkStringArray()&lt;br /&gt;
for segmentName in segmentNames:&lt;br /&gt;
    segmentId = segmentationNode.GetSegmentation().GetSegmentIdBySegmentName(segmentName)&lt;br /&gt;
    segmentIds.InsertNextValue(segmentId)&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.ExportSegmentsToLabelmapNode(segmentationNode, segmentIds, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export to file by pressing Ctrl+Shift+S key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPath = &amp;quot;c:/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def exportLabelmap():&lt;br /&gt;
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLSegmentationNode&amp;quot;)&lt;br /&gt;
    referenceVolumeNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
    labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
    slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
    filepath = outputPath + &amp;quot;/&amp;quot; + referenceVolumeNode.GetName()+&amp;quot;-label.nrrd&amp;quot;&lt;br /&gt;
    slicer.util.saveNode(labelmapVolumeNode, filepath)&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode.GetDisplayNode().GetColorNode())&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
    slicer.util.delayDisplay(&amp;quot;Segmentation saved to &amp;quot;+filepath)&lt;br /&gt;
&lt;br /&gt;
shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
shortcut.setKey(qt.QKeySequence('Ctrl+Shift+s'))&lt;br /&gt;
shortcut.connect( 'activated()', exportLabelmap)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Export model nodes from segmentation node===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode(&amp;quot;Segmentation&amp;quot;)&lt;br /&gt;
shNode = slicer.mrmlScene.GetSubjectHierarchyNode()&lt;br /&gt;
exportFolderItemId = shNode.CreateFolderItem(shNode.GetSceneItemID(), &amp;quot;Segments&amp;quot;)&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModels(segmentationNode, exportFolderItemId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Create a hollow model from boundary of solid segment===&lt;br /&gt;
&lt;br /&gt;
In most cases, the most robust and flexible tool for creating empty shell models (e.g., vessel wall model from contrast agent segmentation) is the &amp;quot;Hollow&amp;quot; effect in Segment Editor module. However, for very thin shells, extrusion of the exported surface mesh representation may be just as robust and require less memory and computation time.&lt;br /&gt;
&lt;br /&gt;
Example of creating a shell model from a segment (id=&amp;quot;Segment_1&amp;quot;) and convert it to a shell:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get closed surface representation of the segment&lt;br /&gt;
shellThickness = 3.0  # mm&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentationNode.CreateClosedSurfaceRepresentation()&lt;br /&gt;
polyData = segmentationNode.GetClosedSurfaceInternalRepresentation('Segment_1')&lt;br /&gt;
&lt;br /&gt;
# Create shell&lt;br /&gt;
extrude = vtk.vtkLinearExtrusionFilter()&lt;br /&gt;
extrude.SetInputData(polyData)&lt;br /&gt;
extrude.SetExtrusionTypeToNormalExtrusion()&lt;br /&gt;
extrude.SetScaleFactor(shellThickness)&lt;br /&gt;
&lt;br /&gt;
# Compute consistent surface normals&lt;br /&gt;
triangle_filter = vtk.vtkTriangleFilter()&lt;br /&gt;
triangle_filter.SetInputConnection(extrude.GetOutputPort())&lt;br /&gt;
normals = vtk.vtkPolyDataNormals()&lt;br /&gt;
normals.SetInputConnection(triangle_filter.GetOutputPort())&lt;br /&gt;
normals.FlipNormalsOn()&lt;br /&gt;
&lt;br /&gt;
# Save result into new model node&lt;br /&gt;
slicer.modules.models.logic().AddModel(normals.GetOutputPort())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Show a segmentation in 3D===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get a representation of a segment===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = slicer.vtkOrientedImageData()&lt;br /&gt;
segmentationNode.GetBinaryLabelmapRepresentation(segmentID, image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
segmentationNode.GetClosedSurfaceRepresentation(segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert all segments using default path and conversion parameters===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert all segments using custom path or conversion parameters===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
referenceGeometry = slicer.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(slicer.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Re-convert using a modified conversion parameter===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Create keyboard shortcut for toggling sphere brush for paint and erase effects===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def toggleSphereBrush():&lt;br /&gt;
    segmentEditorWidget = slicer.modules.segmenteditor.widgetRepresentation().self().editor&lt;br /&gt;
    paintEffect = segmentEditorWidget.effectByName(&amp;quot;Paint&amp;quot;)&lt;br /&gt;
    isSphere = paintEffect.integerParameter('BrushSphere')&lt;br /&gt;
    # BrushSphere is &amp;quot;common&amp;quot; parameter (shared between paint and erase)&lt;br /&gt;
    paintEffect.setCommonParameter(&amp;quot;BrushSphere&amp;quot;, 0 if isSphere else 1)&lt;br /&gt;
&lt;br /&gt;
shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
shortcut.setKey(qt.QKeySequence(&amp;quot;s&amp;quot;))&lt;br /&gt;
shortcut.connect('activated()', toggleSphereBrush)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get centroid of a segment in world (RAS) coordinates===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get histogram of a segmented region===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate input data&lt;br /&gt;
################################################&lt;br /&gt;
&lt;br /&gt;
# Load master volume&lt;br /&gt;
import SampleData&lt;br /&gt;
sampleDataLogic = SampleData.SampleDataLogic()&lt;br /&gt;
masterVolumeNode = sampleDataLogic.downloadMRBrainTumor1()&lt;br /&gt;
&lt;br /&gt;
# Create segmentation&lt;br /&gt;
segmentationNode = slicer.vtkMRMLSegmentationNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(segmentationNode)&lt;br /&gt;
segmentationNode.CreateDefaultDisplayNodes() # only needed for display&lt;br /&gt;
segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(masterVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Create segment&lt;br /&gt;
tumorSeed = vtk.vtkSphereSource()&lt;br /&gt;
tumorSeed.SetCenter(-6, 30, 28)&lt;br /&gt;
tumorSeed.SetRadius(25)&lt;br /&gt;
tumorSeed.Update()&lt;br /&gt;
segmentationNode.AddSegmentFromClosedSurfaceRepresentation(tumorSeed.GetOutput(), &amp;quot;Segment A&amp;quot;, [1.0,0.0,0.0])&lt;br /&gt;
&lt;br /&gt;
# Compute histogram&lt;br /&gt;
################################################&lt;br /&gt;
&lt;br /&gt;
labelValue = 1  # label value of first segment&lt;br /&gt;
&lt;br /&gt;
# Get segmentation as labelmap volume node&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, masterVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Extract all voxels of the segment as numpy array&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(masterVolumeNode)&lt;br /&gt;
labelArray = slicer.util.arrayFromVolume(labelmapVolumeNode)&lt;br /&gt;
segmentVoxels = volumeArray[labelArray==labelValue]&lt;br /&gt;
&lt;br /&gt;
# Compute histogram&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(segmentVoxels, bins=50)&lt;br /&gt;
&lt;br /&gt;
# Plot histogram&lt;br /&gt;
################################################&lt;br /&gt;
&lt;br /&gt;
slicer.util.plot(histogram, xColumnIndex = 1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get segments visible at a selected position===&lt;br /&gt;
&lt;br /&gt;
Show in the console names of segments visible at a markups fiducial position:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLSegmentationNode&amp;quot;)&lt;br /&gt;
markupsFiducialNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
sliceViewLabel = &amp;quot;Red&amp;quot;  # any slice view where segmentation node is visible works&lt;br /&gt;
&lt;br /&gt;
def printSegmentNames(unused1=None, unused2=None):&lt;br /&gt;
    &lt;br /&gt;
    sliceViewWidget = slicer.app.layoutManager().sliceWidget(sliceViewLabel)&lt;br /&gt;
    segmentationsDisplayableManager = sliceViewWidget.sliceView().displayableManagerByClassName('vtkMRMLSegmentationsDisplayableManager2D')&lt;br /&gt;
    ras = [0,0,0]&lt;br /&gt;
    markupsFiducialNode.GetNthControlPointPositionWorld(0, ras)&lt;br /&gt;
    segmentIds = vtk.vtkStringArray()&lt;br /&gt;
    segmentationsDisplayableManager.GetVisibleSegmentsForPosition(ras, segmentationNode.GetDisplayNode(), segmentIds)&lt;br /&gt;
    for idIndex in range(segmentIds.GetNumberOfValues()):&lt;br /&gt;
        segment = segmentationNode.GetSegmentation().GetSegment(segmentIds.GetValue(idIndex))&lt;br /&gt;
        print('Segment found at position {0}: {1}'.format(ras, segment.GetName()))&lt;br /&gt;
&lt;br /&gt;
# Observe markup node changes&lt;br /&gt;
markupsFiducialNode.AddObserver(slicer.vtkMRMLMarkupsPlaneNode.PointModifiedEvent, printSegmentNames)&lt;br /&gt;
printSegmentNames()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Set default segmentation options===&lt;br /&gt;
&lt;br /&gt;
Allow segments to overlap each other by default:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultSegmentEditorNode = slicer.vtkMRMLSegmentEditorNode()&lt;br /&gt;
defaultSegmentEditorNode.SetOverwriteMode(slicer.vtkMRMLSegmentEditorNode.OverwriteNone)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultSegmentEditorNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To always make this the default, add the lines above to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
===How to run segment editor effects from a script===&lt;br /&gt;
&lt;br /&gt;
Editor effects are complex because they need to handle changing master volumes, undo/redo, masking operations, etc. Therefore, it is recommended to use the effect by instantiating a qMRMLSegmentEditorWidget or use/extract processing logic of the effect and use that from a script.&lt;br /&gt;
&lt;br /&gt;
====Use Segment editor effects from script (qMRMLSegmentEditorWidget)====&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
*[https://gist.github.com/lassoan/ef30bc27a22a648ead7f82243f5cc7d5 AI-assisted brain tumor segmentation]&lt;br /&gt;
*[https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
*[https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
*[https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
*[https://gist.github.com/lassoan/4d0b94bda52d5b099432e424e03aa2b1 segment cranial cavity automatically in dry bone skull CT]&lt;br /&gt;
*[https://gist.github.com/lassoan/84d1f9a093dbb6a46c0fcc89279d8088 remove patient table from CT image]&lt;br /&gt;
&lt;br /&gt;
Description of effect parameters are available [https://slicer.readthedocs.io/en/latest/developer_guide/modules/segmenteditor.html#effect-parameters here].&lt;br /&gt;
&lt;br /&gt;
====Use logic of effect from a script====&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters ''extracted'' from an effect:&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
===Process segment using a VTK filter===&lt;br /&gt;
&lt;br /&gt;
This example shows how to apply a VTK filter to a segment that dilates the image by a specified margin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = &amp;quot;Segment_1&amp;quot;&lt;br /&gt;
kernelSize = [3,1,5]&lt;br /&gt;
&lt;br /&gt;
# Export segment as vtkImageData (via temporary labelmap volume node)&lt;br /&gt;
segmentIds = vtk.vtkStringArray()&lt;br /&gt;
segmentIds.InsertNextValue(segmentId)&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportSegmentsToLabelmapNode(segmentationNode, segmentIds, labelmapVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Process segmentation&lt;br /&gt;
segmentImageData = labelmapVolumeNode.GetImageData()&lt;br /&gt;
erodeDilate = vtk.vtkImageDilateErode3D()&lt;br /&gt;
erodeDilate.SetInputData(segmentImageData)&lt;br /&gt;
erodeDilate.SetDilateValue(1)&lt;br /&gt;
erodeDilate.SetErodeValue(0)&lt;br /&gt;
erodeDilate.SetKernelSize(*kernelSize)&lt;br /&gt;
erodeDilate.Update()&lt;br /&gt;
segmentImageData.DeepCopy(erodeDilate.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Import segment from vtkImageData&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, segmentationNode, segmentIds)&lt;br /&gt;
&lt;br /&gt;
# Cleanup temporary nodes&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode.GetDisplayNode().GetColorNode())&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get information from segmentation nrrd file header===&lt;br /&gt;
&lt;br /&gt;
You can use this code snippet to get information from segmentation (.seg.nrrd), for example when creating numpy arrays for generating training data for deep learning networks. This script can be used in any Python environment, not just inside Slicer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# pip_install('pynrrd')&lt;br /&gt;
&lt;br /&gt;
def read_segmentation_info(filename):&lt;br /&gt;
    import nrrd&lt;br /&gt;
    header = nrrd.read_header(filename)&lt;br /&gt;
    segmentation_info = {}&lt;br /&gt;
    segments = []&lt;br /&gt;
    segment_index = 0&lt;br /&gt;
    while True:&lt;br /&gt;
        prefix = &amp;quot;Segment{0}_&amp;quot;.format(segment_index)&lt;br /&gt;
        if not prefix + &amp;quot;ID&amp;quot; in header.keys():&lt;br /&gt;
            break&lt;br /&gt;
        segment = {}&lt;br /&gt;
        segment[&amp;quot;index&amp;quot;] = segment_index&lt;br /&gt;
        segment[&amp;quot;color&amp;quot;] = [float(i) for i in header[prefix + &amp;quot;Color&amp;quot;].split(&amp;quot; &amp;quot;)]  # Segment0_Color:=0.501961 0.682353 0.501961&lt;br /&gt;
        segment[&amp;quot;colorAutoGenerated&amp;quot;] = int(header[prefix + &amp;quot;ColorAutoGenerated&amp;quot;]) != 0  # Segment0_ColorAutoGenerated:=1&lt;br /&gt;
        segment[&amp;quot;extent&amp;quot;] = [int(i) for i in header[prefix + &amp;quot;Extent&amp;quot;].split(&amp;quot; &amp;quot;)]  # Segment0_Extent:=68 203 53 211 24 118&lt;br /&gt;
        segment[&amp;quot;id&amp;quot;] = header[prefix + &amp;quot;ID&amp;quot;]  # Segment0_ID:=Segment_1&lt;br /&gt;
        segment[&amp;quot;labelValue&amp;quot;] = int(header[prefix + &amp;quot;LabelValue&amp;quot;])  # Segment0_LabelValue:=1&lt;br /&gt;
        segment[&amp;quot;layer&amp;quot;] = int(header[prefix + &amp;quot;Layer&amp;quot;])  # Segment0_Layer:=0&lt;br /&gt;
        segment[&amp;quot;name&amp;quot;] = header[prefix + &amp;quot;Name&amp;quot;]  # Segment0_Name:=Segment_1&lt;br /&gt;
        segment[&amp;quot;nameAutoGenerated&amp;quot;] = int(header[prefix + &amp;quot;NameAutoGenerated&amp;quot;]) != 0  # Segment0_NameAutoGenerated:=1&lt;br /&gt;
        # Segment0_Tags:=Segmentation.Status:inprogress|TerminologyEntry:Segmentation category and type - 3D Slicer General Anatomy list&lt;br /&gt;
        # ~SCT^85756007^Tissue~SCT^85756007^Tissue~^^~Anatomic codes - DICOM master list~^^~^^|&lt;br /&gt;
        tags = {}&lt;br /&gt;
        tags_str = header[prefix + &amp;quot;Tags&amp;quot;].split(&amp;quot;|&amp;quot;)&lt;br /&gt;
        for tag_str in tags_str:&lt;br /&gt;
            tag_str = tag_str.strip()&lt;br /&gt;
            if not tag_str:&lt;br /&gt;
                continue&lt;br /&gt;
            key, value = tag_str.split(&amp;quot;:&amp;quot;, maxsplit=1)&lt;br /&gt;
            tags[key] = value&lt;br /&gt;
        segment[&amp;quot;tags&amp;quot;] = tags&lt;br /&gt;
        segments.append(segment)&lt;br /&gt;
        segment_index += 1&lt;br /&gt;
    segmentation_info[&amp;quot;segments&amp;quot;] = segments&lt;br /&gt;
    return segmentation_info&lt;br /&gt;
&lt;br /&gt;
def segment_from_name(segmentation_info, segment_name):&lt;br /&gt;
    for segment in segmentation_info[&amp;quot;segments&amp;quot;]:&lt;br /&gt;
        if segment_name == segment[&amp;quot;name&amp;quot;]:&lt;br /&gt;
            return segment&lt;br /&gt;
    raise KeyError('segment not found by name ' + segment_name)&lt;br /&gt;
&lt;br /&gt;
def segment_names(segmentation_info):&lt;br /&gt;
    names = []&lt;br /&gt;
    for segment in segmentation_info[&amp;quot;segments&amp;quot;]:&lt;br /&gt;
        names.append(segment[&amp;quot;name&amp;quot;])&lt;br /&gt;
    return names&lt;br /&gt;
&lt;br /&gt;
def extract_segments(voxels, header, segmentation_info, segment_names_to_label_values):&lt;br /&gt;
    import numpy as np&lt;br /&gt;
    # Create empty array from last 3 dimensions (output will be flattened to a 3D array)&lt;br /&gt;
    output_voxels = np.zeros(voxels.shape[-3:])&lt;br /&gt;
    # Copy non-segmentation fields to the extracted header&lt;br /&gt;
    output_header = {}&lt;br /&gt;
    for key in header.keys():&lt;br /&gt;
        if not re.match(&amp;quot;^Segment[0-9]+_.+&amp;quot;, key):&lt;br /&gt;
            output_header[key] = header[key]&lt;br /&gt;
    # Copy extracted segments&lt;br /&gt;
    dims = len(voxels.shape)&lt;br /&gt;
    for output_segment_index, segment_name_to_label_value in enumerate(segment_names_to_label_values):&lt;br /&gt;
        # Copy relabeled voxel data&lt;br /&gt;
        segment = segment_from_name(segmentation_info, segment_name_to_label_value[0])&lt;br /&gt;
        input_label_value = segment[&amp;quot;labelValue&amp;quot;]&lt;br /&gt;
        output_label_value = segment_name_to_label_value[1]&lt;br /&gt;
        if dims == 3:&lt;br /&gt;
            output_voxels[voxels == input_label_value] = output_label_value&lt;br /&gt;
        elif dims == 4:&lt;br /&gt;
            inputLayer = segment[&amp;quot;layer&amp;quot;]&lt;br /&gt;
            output_voxels[voxels[inputLayer,:,:,:] == input_label_value] = output_label_value&lt;br /&gt;
        else:&lt;br /&gt;
            raise ValueError(&amp;quot;Voxel array dimension is invalid&amp;quot;)&lt;br /&gt;
        # Copy all segment fields corresponding to this segment&lt;br /&gt;
        for key in header.keys():&lt;br /&gt;
            prefix = &amp;quot;Segment{0}_&amp;quot;.format(segment[&amp;quot;index&amp;quot;])&lt;br /&gt;
            matched = re.match(&amp;quot;^&amp;quot;+prefix+&amp;quot;(.+)&amp;quot;, key)&lt;br /&gt;
            if matched:&lt;br /&gt;
                field_name = matched.groups()[0]&lt;br /&gt;
                if field_name == &amp;quot;LabelValue&amp;quot;:&lt;br /&gt;
                    value = output_label_value&lt;br /&gt;
                elif field_name == &amp;quot;Layer&amp;quot;:&lt;br /&gt;
                    # output is a single layer (3D volume)&lt;br /&gt;
                    value = 0&lt;br /&gt;
                else:&lt;br /&gt;
                    value = header[key]&lt;br /&gt;
                output_header[&amp;quot;Segment{0}_&amp;quot;.format(output_segment_index) + field_name] = value&lt;br /&gt;
    # Remove unnecessary 4th dimension (volume is collapsed into 3D)&lt;br /&gt;
    if dims == 4:&lt;br /&gt;
        # Remove &amp;quot;none&amp;quot; from &amp;quot;none (0,1,0) (0,0,-1) (-1.2999954223632812,0,0)&amp;quot;&lt;br /&gt;
        output_header[&amp;quot;space directions&amp;quot;] = output_header[&amp;quot;space directions&amp;quot;][-3:,:]&lt;br /&gt;
        # Remove &amp;quot;list&amp;quot; from &amp;quot;list domain domain domain&amp;quot;&lt;br /&gt;
        output_header[&amp;quot;kinds&amp;quot;] = output_header[&amp;quot;kinds&amp;quot;][-3:]&lt;br /&gt;
    return output_voxels, output_header&lt;br /&gt;
&lt;br /&gt;
# Read segmentation and show some information about segments&lt;br /&gt;
filename = &amp;quot;c:/Users/andra/OneDrive/Projects/SegmentationPynrrd/SegmentationOverlapping.seg.nrrd&amp;quot;&lt;br /&gt;
segmentation_info = read_segmentation_info(filename)&lt;br /&gt;
number_of_segments = len(segmentation_info[&amp;quot;segments&amp;quot;])&lt;br /&gt;
names = segment_names(segmentation_info)&lt;br /&gt;
label0 = segment_from_name(segmentation_info, names[0])[&amp;quot;labelValue&amp;quot;]&lt;br /&gt;
print(&amp;quot;Number of segments: &amp;quot; + str())&lt;br /&gt;
print(&amp;quot;Segment names: &amp;quot; + str(names))&lt;br /&gt;
print(&amp;quot;Label value of {0}: {1}&amp;quot;.format(names[0], label0))&lt;br /&gt;
&lt;br /&gt;
# Extract selected segments with chosen label values&lt;br /&gt;
extracted_filename = &amp;quot;c:/Users/andra/OneDrive/Projects/SegmentationPynrrd/SegmentationExtracted.seg.nrrd&amp;quot;&lt;br /&gt;
voxels, header = nrrd.read(filename)&lt;br /&gt;
segment_list = [(&amp;quot;Segment_1&amp;quot;, 10), (&amp;quot;Segment_3&amp;quot;, 12), (&amp;quot;Segment_4&amp;quot;, 6)]&lt;br /&gt;
extracted_voxels, extracted_header = extract_segments(voxels, header, segmentation_info, segment_list)&lt;br /&gt;
nrrd.write(extracted_filename, extracted_voxels, extracted_header)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Quantifying segments==&lt;br /&gt;
&lt;br /&gt;
===Get centroid of each segment===&lt;br /&gt;
&lt;br /&gt;
Place a markups fiducial point at the centroid of each segment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
&lt;br /&gt;
# Compute centroids&lt;br /&gt;
import SegmentStatistics&lt;br /&gt;
segStatLogic = SegmentStatistics.SegmentStatisticsLogic()&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;Segmentation&amp;quot;, segmentationNode.GetID())&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.centroid_ras.enabled&amp;quot;, str(True))&lt;br /&gt;
segStatLogic.computeStatistics()&lt;br /&gt;
stats = segStatLogic.getStatistics()&lt;br /&gt;
&lt;br /&gt;
# Place a markup point in each centroid&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
for segmentId in stats['SegmentIDs']:&lt;br /&gt;
    centroid_ras = stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.centroid_ras&amp;quot;]&lt;br /&gt;
    segmentName = segmentationNode.GetSegmentation().GetSegment(segmentId).GetName()&lt;br /&gt;
    markupsNode.AddFiducialFromArray(centroid_ras, segmentName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get size, position, and orientation of each segment===&lt;br /&gt;
&lt;br /&gt;
This example computes oriented bounding box for each segment and displays them using annotation ROI.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
&lt;br /&gt;
# Compute bounding boxes&lt;br /&gt;
import SegmentStatistics&lt;br /&gt;
segStatLogic = SegmentStatistics.SegmentStatisticsLogic()&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;Segmentation&amp;quot;, segmentationNode.GetID())&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_origin_ras.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_diameter_mm.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_x.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_y.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_z.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.computeStatistics()&lt;br /&gt;
stats = segStatLogic.getStatistics()&lt;br /&gt;
&lt;br /&gt;
# Draw ROI for each oriented bounding box&lt;br /&gt;
import numpy as np&lt;br /&gt;
for segmentId in stats['SegmentIDs']:&lt;br /&gt;
    # Get bounding box&lt;br /&gt;
    obb_origin_ras = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_origin_ras&amp;quot;])&lt;br /&gt;
    obb_diameter_mm = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_diameter_mm&amp;quot;])&lt;br /&gt;
    obb_direction_ras_x = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_x&amp;quot;])&lt;br /&gt;
    obb_direction_ras_y = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_y&amp;quot;])&lt;br /&gt;
    obb_direction_ras_z = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_z&amp;quot;])&lt;br /&gt;
    # Create ROI&lt;br /&gt;
    segment = segmentationNode.GetSegmentation().GetSegment(segmentId)&lt;br /&gt;
    roi=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLAnnotationROINode&amp;quot;)&lt;br /&gt;
    roi.SetName(segment.GetName()+' bounding box')&lt;br /&gt;
    roi.SetXYZ(0.0, 0.0, 0.0)&lt;br /&gt;
    roi.SetRadiusXYZ(*(0.5*obb_diameter_mm))&lt;br /&gt;
    # Position and orient ROI using a transform&lt;br /&gt;
    obb_center_ras = obb_origin_ras+0.5*(obb_diameter_mm[0] * obb_direction_ras_x + obb_diameter_mm[1] * obb_direction_ras_y + obb_diameter_mm[2] * obb_direction_ras_z)&lt;br /&gt;
    boundingBoxToRasTransform = np.row_stack((np.column_stack((obb_direction_ras_x, obb_direction_ras_y, obb_direction_ras_z, obb_center_ras)), (0, 0, 0, 1)))&lt;br /&gt;
    boundingBoxToRasTransformMatrix = slicer.util.vtkMatrixFromArray(boundingBoxToRasTransform)&lt;br /&gt;
    transformNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLTransformNode')&lt;br /&gt;
    transformNode.SetAndObserveMatrixTransformToParent(boundingBoxToRasTransformMatrix)&lt;br /&gt;
    roi.SetAndObserveTransformNodeID(transformNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Complete list of available parameters can be obtained by running &amp;lt;code&amp;gt;segStatLogic.getParameterNode().GetParameterNames()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Markups==&lt;br /&gt;
&lt;br /&gt;
===Load markups fiducial list from file===&lt;br /&gt;
&lt;br /&gt;
Markups fiducials can be loaded from file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.loadMarkupsFiducialList('/path/to/list/F.fcsv')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adding Fiducials Programatically===&lt;br /&gt;
&lt;br /&gt;
Markups fiducials can be added to the currently active list from the python console by using the following module logic command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.modules.markups.logic().AddFiducial()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command with no arguments will place a new fiducial at the origin. You can also pass it an initial location:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.modules.markups.logic().AddFiducial(1.0, -2.0, 3.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Add a button to module GUI to activate fiducial placement===&lt;br /&gt;
&lt;br /&gt;
This code snippet creates a toggle button, which activates fiducial placement when pressed (and deactivates when released).&lt;br /&gt;
&lt;br /&gt;
The [http://apidocs.slicer.org/master/classqSlicerMarkupsPlaceWidget.html qSlicerMarkupsPlaceWidget widget] can automatically activate placement of multiple points and can show buttons for deleting points, changing colors, lock, and hide points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
w=slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
w.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
markupsNodeID = slicer.modules.markups.logic().AddNewFiducialNode()&lt;br /&gt;
w.setCurrentNode(slicer.mrmlScene.GetNodeByID(markupsNodeID))&lt;br /&gt;
# Hide all buttons and only show place button&lt;br /&gt;
w.buttonsVisible=False&lt;br /&gt;
w.placeButton().show()&lt;br /&gt;
w.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adding Fiducials via Mouse Clicks===&lt;br /&gt;
&lt;br /&gt;
You can also set the mouse mode into Markups fiducial placement by calling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
placeModePersistence = 1&lt;br /&gt;
slicer.modules.markups.logic().StartPlaceMode(placeModePersistence)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A lower level way to do this is via the selection and interaction nodes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
selectionNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSelectionNodeSingleton&amp;quot;)&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
interactionNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLInteractionNodeSingleton&amp;quot;)&lt;br /&gt;
placeModePersistence = 1&lt;br /&gt;
interactionNode.SetPlaceModePersistence(placeModePersistence)&lt;br /&gt;
# mode 1 is Place, can also be accessed via slicer.vtkMRMLInteractionNode().Place&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To switch back to view transform once you're done placing fiducials:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLInteractionNodeSingleton&amp;quot;)&lt;br /&gt;
interactionNode.SwitchToViewTransformMode()&lt;br /&gt;
# also turn off place mode persistence if required&lt;br /&gt;
interactionNode.SetPlaceModePersistence(0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Access to Fiducial Properties===&lt;br /&gt;
&lt;br /&gt;
Each vtkMRMLMarkupsFiducialNode has a vector of points in it which can be accessed from python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fidNode = getNode(&amp;quot;vtkMRMLMarkupsFiducialNode1&amp;quot;)&lt;br /&gt;
n = fidNode.AddFiducial(4.0, 5.5, -6.0)&lt;br /&gt;
fidNode.SetNthFiducialLabel(n, &amp;quot;new label&amp;quot;)&lt;br /&gt;
# each markup is given a unique id which can be accessed from the superclass level&lt;br /&gt;
id1 = fidNode.GetNthMarkupID(n)&lt;br /&gt;
# manually set the position&lt;br /&gt;
fidNode.SetNthFiducialPosition(n, 6.0, 7.0, 8.0)&lt;br /&gt;
# set the label&lt;br /&gt;
fidNode.SetNthFiducialLabel(n, &amp;quot;New label&amp;quot;)&lt;br /&gt;
# set the selected flag, only selected = 1 fiducials will be passed to CLIs&lt;br /&gt;
fidNode.SetNthFiducialSelected(n, 1)&lt;br /&gt;
# set the visibility flag&lt;br /&gt;
fidNode.SetNthFiducialVisibility(n, 0)  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can loop over the fiducials in a list and get the coordinates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fidList = slicer.util.getNode('F')&lt;br /&gt;
numFids = fidList.GetNumberOfFiducials()&lt;br /&gt;
for i in range(numFids):&lt;br /&gt;
  ras = [0,0,0]&lt;br /&gt;
  fidList.GetNthFiducialPosition(i,ras)&lt;br /&gt;
  # the world position is the RAS position with any transform matrices applied&lt;br /&gt;
  world = [0,0,0,0]&lt;br /&gt;
  fidList.GetNthFiducialWorldCoordinates(0,world)&lt;br /&gt;
  print(i,&amp;quot;: RAS =&amp;quot;,ras,&amp;quot;, world =&amp;quot;,world)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also look at the sample code in the [https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/Endoscopy/Endoscopy.py#L287 Endoscopy module] to see how python is used to access fiducials from a scripted module.&lt;br /&gt;
&lt;br /&gt;
==Accessing views, renderers, and cameras==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide view controller bars==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Customize widgets in view controller bars==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceController = slicer.app.layoutManager().sliceWidget(&amp;quot;Red&amp;quot;).sliceController()&lt;br /&gt;
&lt;br /&gt;
# hide what is not needed&lt;br /&gt;
sliceController.pinButton().hide()&lt;br /&gt;
#sliceController.viewLabel().hide()&lt;br /&gt;
sliceController.fitToWindowToolButton().hide()&lt;br /&gt;
sliceController.sliceOffsetSlider().hide()&lt;br /&gt;
&lt;br /&gt;
# add custom widgets&lt;br /&gt;
myButton = qt.QPushButton(&amp;quot;My custom button&amp;quot;)&lt;br /&gt;
sliceController.barLayout().addWidget(myButton)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change 3D view background color==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNode = slicer.app.layoutManager().threeDWidget(0).mrmlViewNode()&lt;br /&gt;
viewNode.SetBackgroundColor(1,0,0)&lt;br /&gt;
viewNode.SetBackgroundColor2(1,0,0)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide Slicer logo from main window (to increase space)==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.findChild(slicer.util.mainWindow(), 'LogoLabel').visible = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subject hierarchy== &lt;br /&gt;
====Get the pseudo-singleton subject hierarchy node====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.mrmlScene.GetSubjectHierarchyNode()&lt;br /&gt;
&lt;br /&gt;
====Create subject hierarchy item====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
====Get subject hierarchy item====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
====Traverse children of a subject hierarchy item====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children) # Add a third argument with value True for recursive query&lt;br /&gt;
  for i in range(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
====Manipulate subject hierarchy item====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data node associated to an item&lt;br /&gt;
  shNode.SetItemDisplayVisibility(itemID, 1)&lt;br /&gt;
  # Set visibility of whole branch&lt;br /&gt;
  # Note: Folder-type items (fodler, subject, study, etc.) create their own display nodes when show/hiding from UI.&lt;br /&gt;
  #       The displayable managers use SH information to determine visibility of an item, so no need to show/hide individual leaf nodes any more.&lt;br /&gt;
  #       Once the folder display node is created, it can be shown hidden simply using shNode.SetItemDisplayVisibility&lt;br /&gt;
  # From python, this is how to trigger creating a folder display node&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler().instance()&lt;br /&gt;
  folderPlugin = pluginHandler.pluginByName('Folder')&lt;br /&gt;
  folderPlugin.setDisplayVisibility(folderItemID, 1)&lt;br /&gt;
&lt;br /&gt;
====Filter items in TreeView or ComboBox====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
===Listen to subject hierarchy item events===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
===Subject hierarchy plugin offering view context menu action===&lt;br /&gt;
If an object that supports view context menus (e.g. markups) is right-clicked in a slice or 3D view, it can offer custom actions. Due to internal limitations these plugins must be set up differently, as explained [https://github.com/Slicer/Slicer/blob/master/Modules/Loadable/Annotations/SubjectHierarchyPlugins/AnnotationsSubjectHierarchyPlugin.py#L96-L107 here]. This example makes it easier to create such a plugin.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import vtk, qt, ctk, slicer&lt;br /&gt;
from slicer.ScriptedLoadableModule import *&lt;br /&gt;
from slicer.util import VTKObservationMixin&lt;br /&gt;
&lt;br /&gt;
from SubjectHierarchyPlugins import AbstractScriptedSubjectHierarchyPlugin&lt;br /&gt;
&lt;br /&gt;
class ViewContextMenu(ScriptedLoadableModule):&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Uses ScriptedLoadableModule base class, available at:&lt;br /&gt;
  https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py&lt;br /&gt;
  &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  def __init__(self, parent):&lt;br /&gt;
    ScriptedLoadableModule.__init__(self, parent)&lt;br /&gt;
    self.parent.title = &amp;quot;Markup Editor&amp;quot;&lt;br /&gt;
    self.parent.categories = [&amp;quot;SlicerMorph&amp;quot;, &amp;quot;Labs&amp;quot;]&lt;br /&gt;
    self.parent.dependencies = []&lt;br /&gt;
    self.parent.contributors = [&amp;quot;Steve Pieper (Isomics, Inc.)&amp;quot;]&lt;br /&gt;
    self.parent.helpText = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
A tool to manipulate Markups using the Segment Editor as a geometry backend&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    self.parent.helpText += self.getDefaultModuleDocumentationLink()&lt;br /&gt;
    self.parent.acknowledgementText = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
This module was developed by Steve Pieper, Sara Rolfe and Murat Maga,&lt;br /&gt;
through a NSF ABI Development grant, &amp;quot;An Integrated Platform for Retrieval,&lt;br /&gt;
Visualization and Analysis of 3D Morphology From Digital Biological Collections&amp;quot;&lt;br /&gt;
(Award Numbers: 1759883 (Murat Maga), 1759637 (Adam Summers), 1759839 (Douglas Boyer)).&lt;br /&gt;
This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc.,&lt;br /&gt;
Andras Lasso, PerkLab, and Steve Pieper, Isomics, Inc.&lt;br /&gt;
and was partially funded by NIH grant 3P41RR013218-12S1.&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    #&lt;br /&gt;
    # register subject hierarchy plugin once app is initialized&lt;br /&gt;
    #&lt;br /&gt;
    def onStartupCompleted():&lt;br /&gt;
        import SubjectHierarchyPlugins&lt;br /&gt;
        from ViewContextMenu import ViewContextMenuSubjectHierarchyPlugin&lt;br /&gt;
        scriptedPlugin = slicer.qSlicerSubjectHierarchyScriptedPlugin(None)&lt;br /&gt;
        scriptedPlugin.setPythonSource(ViewContextMenuSubjectHierarchyPlugin.filePath)&lt;br /&gt;
        pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler.instance()&lt;br /&gt;
        pluginHandler.registerPlugin(scriptedPlugin)&lt;br /&gt;
        print('ViewContextMenuSubjectHierarchyPlugin loaded')&lt;br /&gt;
    slicer.app.connect(&amp;quot;startupCompleted()&amp;quot;, onStartupCompleted)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class ViewContextMenuSubjectHierarchyPlugin(AbstractScriptedSubjectHierarchyPlugin):&lt;br /&gt;
&lt;br /&gt;
    # Necessary static member to be able to set python source to scripted subject hierarchy plugin&lt;br /&gt;
    filePath = __file__&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, scriptedPlugin):&lt;br /&gt;
        self.viewAction = qt.QAction(f&amp;quot;CUSTOM VIEW ...&amp;quot;, scriptedPlugin)&lt;br /&gt;
        self.viewAction.objectName = 'CustomViewAction'&lt;br /&gt;
        self.viewAction.connect(&amp;quot;triggered()&amp;quot;, self.onViewAction)&lt;br /&gt;
&lt;br /&gt;
    def onViewAction(self):&lt;br /&gt;
        print(f&amp;quot;VIEW ACTION&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def viewContextMenuActions(self):&lt;br /&gt;
        return [self.viewAction]&lt;br /&gt;
&lt;br /&gt;
    def showViewContextMenuActionsForItem(self, itemID, eventData=None):&lt;br /&gt;
        pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler.instance()&lt;br /&gt;
        pluginLogic = pluginHandler.pluginLogic()&lt;br /&gt;
        menuActions = list(pluginLogic.availableViewMenuActionNames())&lt;br /&gt;
        menuActions.append('CustomViewAction')&lt;br /&gt;
        pluginLogic.setDisplayedViewMenuActionNames(menuActions)&lt;br /&gt;
        self.viewAction.visible = True&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Use whitelist to customize view menu===&lt;br /&gt;
When right-clicking certain types of nodes in the 2D/3D views, a subject hierarchy menu pops up. If menu actions need to be removed, a whitelist can be used to specify the ones that should show up.&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler.instance()&lt;br /&gt;
  pluginLogic = pluginHandler.pluginLogic()&lt;br /&gt;
  menuActions = pluginLogic.availableViewMenuActionNames()&lt;br /&gt;
  # Returns ('RenamePointAction', 'DeletePointAction', 'ToggleSelectPointAction', 'EditPropertiesAction')&lt;br /&gt;
  newActions = ['RenamePointAction']&lt;br /&gt;
  pluginLogic.setDisplayedViewMenuActionNames(newActions)&lt;br /&gt;
&lt;br /&gt;
==Plotting==&lt;br /&gt;
&lt;br /&gt;
===Slicer plots displayed in view layout===&lt;br /&gt;
&lt;br /&gt;
Create histogram plot of a volume and show it embedded in the view layout. More information: https://www.slicer.org/wiki/Documentation/Nightly/Developers/Plots&lt;br /&gt;
&lt;br /&gt;
====Using &amp;lt;code&amp;gt;slicer.util.plot&amp;lt;/code&amp;gt; utility function====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
chartNode = slicer.util.plot(histogram, xColumnIndex = 1)&lt;br /&gt;
chartNode.SetYAxisRangeAuto(False)&lt;br /&gt;
chartNode.SetYAxisRange(0, 4e5)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:SlicerPlot.png]]&lt;br /&gt;
&lt;br /&gt;
====Using MRML classes only====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using matplotlib===&lt;br /&gt;
&lt;br /&gt;
Matplotlib may be used from within Slicer, but the default Tk backend locks up and crashes Slicer. However, Matplotlib may still be used through other backends. More details can be found on the [http://matplotlib.sourceforge.net/ MatPlotLib] pages.&lt;br /&gt;
&lt;br /&gt;
====Non-interactive plot====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
&lt;br /&gt;
# Static image view&lt;br /&gt;
pm = qt.QPixmap(&amp;quot;MatplotlibExample.png&amp;quot;)&lt;br /&gt;
imageWidget = qt.QLabel()&lt;br /&gt;
imageWidget.setPixmap(pm)&lt;br /&gt;
imageWidget.setScaledContents(True)&lt;br /&gt;
imageWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:MatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
====Plot in Slicer Jupyter notebook====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import JupyterNotebooksLib as slicernb&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
def f(t):&lt;br /&gt;
    s1 = np.cos(2*np.pi*t)&lt;br /&gt;
    e1 = np.exp(-t)&lt;br /&gt;
    return s1 * e1&lt;br /&gt;
&lt;br /&gt;
t1 = np.arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = np.arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = np.arange(0.0, 2.0, 0.01)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
fig, axs = plt.subplots(2, 1, constrained_layout=True)&lt;br /&gt;
axs[0].plot(t1, f(t1), 'o', t2, f(t2), '-')&lt;br /&gt;
axs[0].set_title('subplot 1')&lt;br /&gt;
axs[0].set_xlabel('distance (m)')&lt;br /&gt;
axs[0].set_ylabel('Damped oscillation')&lt;br /&gt;
fig.suptitle('This is a somewhat long figure title', fontsize=16)&lt;br /&gt;
&lt;br /&gt;
axs[1].plot(t3, np.cos(2*np.pi*t3), '--')&lt;br /&gt;
axs[1].set_xlabel('time (s)')&lt;br /&gt;
axs[1].set_title('subplot 2')&lt;br /&gt;
axs[1].set_ylabel('Undamped')&lt;br /&gt;
&lt;br /&gt;
slicernb.MatplotlibDisplay(matplotlib.pyplot)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:JupyterNotebookMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
====Interactive plot using wxWidgets GUI toolkit====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
  import wx&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib wxPython')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Set matplotlib to use WXAgg backend&lt;br /&gt;
import matplotlib&lt;br /&gt;
matplotlib.use('WXAgg')&lt;br /&gt;
&lt;br /&gt;
# Show an interactive plot&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
fig, ax = plt.subplots()&lt;br /&gt;
ax.plot(histogram[1][1:], histogram[0].astype(float))&lt;br /&gt;
ax.grid(True)&lt;br /&gt;
ax.set_ylim((0, 4e5))&lt;br /&gt;
plt.show(block=False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:InteractiveMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==Execute external applications==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
===Run process in default environment===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;br /&gt;
&lt;br /&gt;
==Manage extensions==&lt;br /&gt;
&lt;br /&gt;
===Download and install extension===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensionName = 'SlicerIGT'&lt;br /&gt;
em = slicer.app.extensionsManagerModel()&lt;br /&gt;
if not em.isExtensionInstalled(extensionName):&lt;br /&gt;
    extensionMetaData = em.retrieveExtensionMetadataByName(extensionName)&lt;br /&gt;
    url = em.serverUrl().toString()+'/download/item/'+extensionMetaData['item_id']&lt;br /&gt;
    extensionPackageFilename = slicer.app.temporaryPath+'/'+extensionMetaData['md5']&lt;br /&gt;
    slicer.util.downloadFile(url, extensionPackageFilename)&lt;br /&gt;
    em.installExtension(extensionPackageFilename)&lt;br /&gt;
    slicer.util.restart()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Install a module directly from a git repository===&lt;br /&gt;
This can be useful for sharing code in development without requiring a restart of Slicer.&lt;br /&gt;
&lt;br /&gt;
https://gist.github.com/pieper/a9c0ba57de3833c9f5aea68247bda597&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=63311</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=63311"/>
		<updated>2020-06-25T16:46:04Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Subject hierarchy plugin offering view context menu action&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=  &lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the[[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
&lt;br /&gt;
*[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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
*[https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
&lt;br /&gt;
*Capture the full Slicer screen and save it into a file&lt;br /&gt;
&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
&lt;br /&gt;
*Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
*Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
&lt;br /&gt;
*How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loadedVolumeNode = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional options may be specified in &amp;lt;code&amp;gt;properties&amp;lt;/code&amp;gt; argument. For example, load an image stack by disabling &amp;lt;code&amp;gt;singleFile&amp;lt;/code&amp;gt; option:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loadedVolumeNode = slicer.util.loadVolume('c:/Users/abc/Documents/SomeImage/file001.png', {'singleFile': False})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Automatically load volumes that are copied into a folder==&lt;br /&gt;
&lt;br /&gt;
This example shows how to implement a simple background task by using a timer. The background task is to check for any new volume files in folder and if there is any then automatically load it.&lt;br /&gt;
&lt;br /&gt;
There are more efficient methods for file system monitoring or exchanging image data in real-time (for example, using OpenIGTLink), the example below is just for demonstration purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
incomingVolumeFolder = &amp;quot;c:/tmp/incoming&amp;quot;&lt;br /&gt;
incomingVolumesProcessed = []&lt;br /&gt;
&lt;br /&gt;
def checkForNewVolumes():&lt;br /&gt;
  # Check if there is a new file in the &lt;br /&gt;
  from os import listdir&lt;br /&gt;
  from os.path import isfile, join&lt;br /&gt;
  for f in listdir(incomingVolumeFolder):&lt;br /&gt;
    if f in incomingVolumesProcessed:&lt;br /&gt;
      # this is an incoming file, it was already there&lt;br /&gt;
      continue&lt;br /&gt;
    filePath = join(incomingVolumeFolder, f)&lt;br /&gt;
    if not isfile(filePath):&lt;br /&gt;
      # ignore directories&lt;br /&gt;
      continue&lt;br /&gt;
    logging.info(&amp;quot;Loading new file: &amp;quot;+f)&lt;br /&gt;
    incomingVolumesProcessed.append(f)&lt;br /&gt;
    slicer.util.loadVolume(filePath)&lt;br /&gt;
  # Check again in 3000ms&lt;br /&gt;
  qt.QTimer.singleShot(3000, checkForNewVolumes)&lt;br /&gt;
&lt;br /&gt;
# Start monitoring&lt;br /&gt;
checkForNewVolumes()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
===How to load DICOM files into the scene from a folder===&lt;br /&gt;
&lt;br /&gt;
This code loads all DICOM objects into the scene from a file folder. All the registered plugins are evaluated and the one with the highest confidence will be used to load the data. Files are imported into a temporary DICOM database, so the current Slicer DICOM database is not impacted.&lt;br /&gt;
&lt;br /&gt;
  dicomDataDir = &amp;quot;c:/my/folder/with/dicom-files&amp;quot;  # input folder with DICOM files&lt;br /&gt;
  loadedNodeIDs = []  # this list will contain the list of all loaded node IDs&lt;br /&gt;
  &lt;br /&gt;
  from DICOMLib import DICOMUtils&lt;br /&gt;
  with DICOMUtils.TemporaryDICOMDatabase() as db:&lt;br /&gt;
    DICOMUtils.importDicom(dicomDataDir, db)&lt;br /&gt;
    patientUIDs = db.patients()&lt;br /&gt;
    for patientUID in patientUIDs:&lt;br /&gt;
      loadedNodeIDs.extend(DICOMUtils.loadPatientByUID(patientUID))&lt;br /&gt;
&lt;br /&gt;
===How to access top level tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # Note, fileValue accesses the database of cached top level tags&lt;br /&gt;
  # (nested tags are not included)&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
===How to access DICOM tags nested in a sequence===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # use pydicom to access the full header, which requires&lt;br /&gt;
  # re-reading the dataset instead of using the database cache&lt;br /&gt;
  import pydicom&lt;br /&gt;
  pydicom.dcmread(fileList[0])&lt;br /&gt;
  ds.CTExposureSequence[0].ExposureModulationType&lt;br /&gt;
&lt;br /&gt;
===How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
===How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
===How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
===How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm'); slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
===Export a volume to DICOM file format===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Customize table columns in DICOM browser===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database() # Need to go this way, do not use slicer.dicomDatabase for this&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
&lt;br /&gt;
*How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
for viewNode in viewNodes:&lt;br /&gt;
  viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
== Switch to a different module ==&lt;br /&gt;
&lt;br /&gt;
This utility function can be used to open a different module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.selectModule('DICOM')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
&lt;br /&gt;
*How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two slice planes==&lt;br /&gt;
&lt;br /&gt;
Measure angle between red and yellow slice nodes. Whenever any of the slice nodes are moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeIds = ['vtkMRMLSliceNodeRed', 'vtkMRMLSliceNodeYellow']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    sliceNormalVector = []&lt;br /&gt;
    for sliceNodeId in sliceNodeIds:&lt;br /&gt;
        sliceToRAS = slicer.mrmlScene.GetNodeByID(sliceNodeId).GetSliceToRAS()&lt;br /&gt;
        sliceNormalVector.append([sliceToRAS.GetElement(0,2), sliceToRAS.GetElement(1,2), sliceToRAS.GetElement(2,2)])&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(sliceNormalVector[0], sliceNormalVector[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between slice planes = {0:0.3f}'.format(angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe slice node changes&lt;br /&gt;
for sliceNodeId in sliceNodeIds:&lt;br /&gt;
    slicer.mrmlScene.GetNodeByID(sliceNodeId).AddObserver(vtk.vtkCommand.ModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two markup planes ==&lt;br /&gt;
&lt;br /&gt;
Measure angle between two markup plane nodes. Whenever any of the plane nodes are moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
planeNodeNames = ['P', 'P_1']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    planeNormalVectors = []&lt;br /&gt;
    for planeNodeName in planeNodeNames:&lt;br /&gt;
        planeNode = slicer.util.getFirstNodeByClassByName('vtkMRMLMarkupsPlaneNode', planeNodeName)&lt;br /&gt;
        planeNormalVector = [0.0, 0.0, 0.0]&lt;br /&gt;
        planeNode.GetNormalWorld(planeNormalVector)&lt;br /&gt;
        planeNormalVectors.append(planeNormalVector)&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(planeNormalVectors[0], planeNormalVectors[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between planes {0} and {1} = {2:0.3f}'.format(planeNodeNames[0], planeNodeNames[1], angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe plane node changes&lt;br /&gt;
for planeNodeName in planeNodeNames:&lt;br /&gt;
    planeNode = slicer.util.getFirstNodeByClassByName('vtkMRMLMarkupsPlaneNode', planeNodeName)&lt;br /&gt;
    planeNode.AddObserver(slicer.vtkMRMLMarkupsPlaneNode.PointModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two markup lines==&lt;br /&gt;
&lt;br /&gt;
Measure angle between two markup line nodes. Whenever either line is moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineNodeNames = ['L', 'L_1']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    import numpy as np&lt;br /&gt;
    lineDirectionVectors = []&lt;br /&gt;
    for lineNodeName in lineNodeNames:&lt;br /&gt;
        lineNode = slicer.util.getFirstNodeByClassByName('vtkMRMLMarkupsLineNode', lineNodeName)&lt;br /&gt;
        lineStartPos = np.zeros(3)&lt;br /&gt;
        lineEndPos = np.zeros(3)&lt;br /&gt;
        lineNode.GetNthControlPointPositionWorld(0, lineStartPos)&lt;br /&gt;
        lineNode.GetNthControlPointPositionWorld(1, lineEndPos)&lt;br /&gt;
        lineDirectionVector = (lineEndPos-lineStartPos)/np.linalg.norm(lineEndPos-lineStartPos)&lt;br /&gt;
        lineDirectionVectors.append(lineDirectionVector)&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(lineDirectionVectors[0], lineDirectionVectors[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between lines {0} and {1} = {2:0.3f}'.format(lineNodeNames[0], lineNodeNames[1], angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe line node changes&lt;br /&gt;
for lineNodeName in lineNodeNames:&lt;br /&gt;
    lineNode = slicer.util.getFirstNodeByClassByName('vtkMRMLMarkupsLineNode', lineNodeName)&lt;br /&gt;
    lineNode.AddObserver(slicer.vtkMRMLMarkupsLineNode.PointModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from a normal vector and position==&lt;br /&gt;
&lt;br /&gt;
This code snippet shows how to display a slice view defined by a normal vector and position in an anatomically sensible way: rotating slice view so that &amp;quot;up&amp;quot; direction (or &amp;quot;right&amp;quot; direction) is towards an anatomical axis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition, defaultViewUpDirection=None, backupViewRightDirection=None):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Set slice pose from the provided plane normal and position. View up direction is determined automatically,&lt;br /&gt;
    to make view up point towards defaultViewUpDirection.&lt;br /&gt;
    :param defaultViewUpDirection Slice view will be spinned in-plane to match point approximately this up direction. Default: patient superior.&lt;br /&gt;
    :param backupViewRightDirection Slice view will be spinned in-plane to match point approximately this right direction&lt;br /&gt;
        if defaultViewUpDirection is too similar to sliceNormal. Default: patient left.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Fix up input directions&lt;br /&gt;
    if defaultViewUpDirection is None:&lt;br /&gt;
        defaultViewUpDirection = [0,0,1]&lt;br /&gt;
    if backupViewRightDirection is None:&lt;br /&gt;
        backupViewRightDirection = [-1,0,0]&lt;br /&gt;
    if sliceNormal[1]&amp;gt;=0:&lt;br /&gt;
        sliceNormalStandardized = sliceNormal&lt;br /&gt;
    else:&lt;br /&gt;
        sliceNormalStandardized = [-sliceNormal[0], -sliceNormal[1], -sliceNormal[2]]&lt;br /&gt;
    # Compute slice axes&lt;br /&gt;
    sliceNormalViewUpAngle = vtk.vtkMath.AngleBetweenVectors(sliceNormalStandardized, defaultViewUpDirection)&lt;br /&gt;
    angleTooSmallThresholdRad = 0.25 # about 15 degrees&lt;br /&gt;
    if sliceNormalViewUpAngle &amp;gt; angleTooSmallThresholdRad and sliceNormalViewUpAngle &amp;lt; vtk.vtkMath.Pi() - angleTooSmallThresholdRad:&lt;br /&gt;
        viewUpDirection = defaultViewUpDirection&lt;br /&gt;
        sliceAxisY = viewUpDirection&lt;br /&gt;
        sliceAxisX = [0, 0, 0]&lt;br /&gt;
        vtk.vtkMath.Cross(sliceAxisY, sliceNormalStandardized, sliceAxisX)&lt;br /&gt;
    else:&lt;br /&gt;
        sliceAxisX = backupViewRightDirection&lt;br /&gt;
    # Set slice axes&lt;br /&gt;
    sliceNode.SetSliceToRASByNTP(sliceNormalStandardized[0], sliceNormalStandardized[1], sliceNormalStandardized[2],&lt;br /&gt;
        sliceAxisX[0], sliceAxisX[1], sliceAxisX[2],&lt;br /&gt;
        slicePosition[0], slicePosition[1], slicePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Example usage:&lt;br /&gt;
sliceNode = getNode('vtkMRMLSliceNodeRed')&lt;br /&gt;
transformNode = getNode('Transform_3')&lt;br /&gt;
transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
transformNode.GetMatrixTransformToParent(transformMatrix)&lt;br /&gt;
sliceNormal = [transformMatrix.GetElement(0,2), transformMatrix.GetElement(1,2), transformMatrix.GetElement(2,2)]&lt;br /&gt;
slicePosition = [transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)]&lt;br /&gt;
setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Switching to markup fiducial placement mode==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change markup fiducial display properties==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get a notification if a markup point position is modified==&lt;br /&gt;
&lt;br /&gt;
Event management of Slicer-4.11 version is still subject to change. The example below shows how point manipulation can be observed now.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupChanged(caller,event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    if movingMarkupIndex &amp;gt;= 0:&lt;br /&gt;
        pos = [0,0,0]&lt;br /&gt;
        markupsNode.GetNthFiducialPosition(movingMarkupIndex, pos)&lt;br /&gt;
        isPreview = markupsNode.GetNthControlPointPositionStatus(movingMarkupIndex) == slicer.vtkMRMLMarkupsNode.PositionPreview&lt;br /&gt;
        if isPreview:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} is previewed at {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
        else:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} was moved {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
    else:&lt;br /&gt;
        logging.info(&amp;quot;Points modified: slice view = {0}&amp;quot;.format(sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupStartInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()    &lt;br /&gt;
    logging.info(&amp;quot;Start interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupEndInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    logging.info(&amp;quot;End interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, onMarkupChanged)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointStartInteractionEvent, onMarkupStartInteraction)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointEndInteractionEvent, onMarkupEndInteraction)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get a notification if a transform is modified==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate a node around a specified point==&lt;br /&gt;
&lt;br /&gt;
Set up the scene:&lt;br /&gt;
&lt;br /&gt;
*Add a markup fiducial node (centerOfRotationMarkupsNode) with a single point to specify center of rotation.&lt;br /&gt;
*Add a rotation transform (rotationTransformNode) that will be edited in Transforms module to specify rotation angles.&lt;br /&gt;
*Add a transform (finalTransformNode) and apply it (not harden) to those nodes (images, models, etc.) that you want to rotate around the center of rotation point.&lt;br /&gt;
&lt;br /&gt;
Then run the script below, go to Transforms module, select rotationTransformNode, and move rotation sliders.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# This markups fiducial node specifies the center of rotation&lt;br /&gt;
centerOfRotationMarkupsNode = getNode('F')&lt;br /&gt;
# This transform can be  edited in Transforms module&lt;br /&gt;
rotationTransformNode = getNode('LinearTransform_3')&lt;br /&gt;
# This transform has to be applied to the image, model, etc.&lt;br /&gt;
finalTransformNode = getNode('LinearTransform_4')&lt;br /&gt;
&lt;br /&gt;
def updateFinalTransform(unusedArg1=None, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
    rotationMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
    rotationTransformNode.GetMatrixTransformToParent(rotationMatrix)&lt;br /&gt;
    rotationCenterPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
    centerOfRotationMarkupsNode.GetNthControlPointPositionWorld(0, rotationCenterPointCoord)&lt;br /&gt;
    finalTransform = vtk.vtkTransform()&lt;br /&gt;
    finalTransform.Translate(rotationCenterPointCoord)&lt;br /&gt;
    finalTransform.Concatenate(rotationMatrix)&lt;br /&gt;
    finalTransform.Translate(-rotationCenterPointCoord[0], -rotationCenterPointCoord[1], -rotationCenterPointCoord[2])&lt;br /&gt;
    finalTransformNode.SetAndObserveMatrixTransformToParent(finalTransform.GetMatrix())&lt;br /&gt;
&lt;br /&gt;
# Manual initial update&lt;br /&gt;
updateFinalTransform()&lt;br /&gt;
&lt;br /&gt;
# Automatic update when point is moved or transform is modified&lt;br /&gt;
rotationTransformNodeObserver = rotationTransformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, updateFinalTransform)&lt;br /&gt;
centerOfRotationMarkupsNodeObserver = centerOfRotationMarkupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, updateFinalTransform)&lt;br /&gt;
&lt;br /&gt;
# Execute these lines to stop automatic updates:&lt;br /&gt;
# rotationTransformNode.RemoveObserver(rotationTransformNodeObserver)&lt;br /&gt;
# centerOfRotationMarkupsNode.RemoveObserver(centerOfRotationMarkupsNodeObserver)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate a node around a specified line==&lt;br /&gt;
&lt;br /&gt;
Set up the scene:&lt;br /&gt;
&lt;br /&gt;
*Add a markup line node (rotationAxisMarkupsNode) with 2 points to specify rotation axis.&lt;br /&gt;
*Add a rotation transform (rotationTransformNode) that will be edited in Transforms module to specify rotation angle.&lt;br /&gt;
*Add a transform (finalTransformNode) and apply it (not harden) to those nodes (images, models, etc.) that you want to rotate around the line.&lt;br /&gt;
&lt;br /&gt;
Then run the script below, go to Transforms module, select rotationTransformNode, and move Edit / Rotation / IS slider.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# This markups fiducial node specifies the center of rotation&lt;br /&gt;
rotationAxisMarkupsNode = getNode('L')&lt;br /&gt;
# This transform can be edited in Transforms module (Edit / Rotation / IS slider)&lt;br /&gt;
rotationTransformNode = getNode('LinearTransform_3')&lt;br /&gt;
# This transform has to be applied to the image, model, etc.&lt;br /&gt;
finalTransformNode = getNode('LinearTransform_4')&lt;br /&gt;
&lt;br /&gt;
def updateFinalTransform(unusedArg1=None, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
    import numpy as np&lt;br /&gt;
    rotationAxisPoint1_World = np.zeros(3)&lt;br /&gt;
    rotationAxisMarkupsNode.GetNthControlPointPositionWorld(0, rotationAxisPoint1_World)&lt;br /&gt;
    rotationAxisPoint2_World = np.zeros(3)&lt;br /&gt;
    rotationAxisMarkupsNode.GetNthControlPointPositionWorld(1, rotationAxisPoint2_World)&lt;br /&gt;
    axisDirectionZ_World = rotationAxisPoint2_World-rotationAxisPoint1_World&lt;br /&gt;
    axisDirectionZ_World = axisDirectionZ_World/np.linalg.norm(axisDirectionZ_World)&lt;br /&gt;
    # Get transformation between world coordinate system and rotation axis aligne coordinate system&lt;br /&gt;
    worldToRotationAxisTransform = vtk.vtkMatrix4x4()&lt;br /&gt;
    p=vtk.vtkPlaneSource()&lt;br /&gt;
    p.SetNormal(axisDirectionZ_World)&lt;br /&gt;
    axisOrigin = np.array(p.GetOrigin())&lt;br /&gt;
    axisDirectionX_World = np.array(p.GetPoint1())-axisOrigin&lt;br /&gt;
    axisDirectionY_World = np.array(p.GetPoint2())-axisOrigin&lt;br /&gt;
    rotationAxisToWorldTransform = np.row_stack((np.column_stack((axisDirectionX_World, axisDirectionY_World, axisDirectionZ_World, rotationAxisPoint1_World)), (0, 0, 0, 1)))&lt;br /&gt;
    rotationAxisToWorldTransformMatrix = slicer.util.vtkMatrixFromArray(rotationAxisToWorldTransform)&lt;br /&gt;
    worldToRotationAxisTransformMatrix = slicer.util.vtkMatrixFromArray(np.linalg.inv(rotationAxisToWorldTransform))&lt;br /&gt;
    # Compute transformation chain&lt;br /&gt;
    rotationMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
    rotationTransformNode.GetMatrixTransformToParent(rotationMatrix)&lt;br /&gt;
    finalTransform = vtk.vtkTransform()&lt;br /&gt;
    finalTransform.Concatenate(rotationAxisToWorldTransformMatrix)&lt;br /&gt;
    finalTransform.Concatenate(rotationMatrix)&lt;br /&gt;
    finalTransform.Concatenate(worldToRotationAxisTransformMatrix)&lt;br /&gt;
    finalTransformNode.SetAndObserveMatrixTransformToParent(finalTransform.GetMatrix())&lt;br /&gt;
&lt;br /&gt;
# Manual initial update&lt;br /&gt;
updateFinalTransform()&lt;br /&gt;
&lt;br /&gt;
# Automatic update when point is moved or transform is modified&lt;br /&gt;
rotationTransformNodeObserver = rotationTransformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, updateFinalTransform)&lt;br /&gt;
rotationAxisMarkupsNodeObserver = rotationAxisMarkupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, updateFinalTransform)&lt;br /&gt;
&lt;br /&gt;
# Execute these lines to stop automatic updates:&lt;br /&gt;
# rotationTransformNode.RemoveObserver(rotationTransformNodeObserver)&lt;br /&gt;
# rotationAxisMarkupsNode.RemoveObserver(rotationAxisMarkupsNodeObserver)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a context menu when a markup point is clicked in a slice or 3D view==&lt;br /&gt;
&lt;br /&gt;
Subject hierarchy plugins can offer actions in the view context menu when right-clicking objects that support such picking (such as Markups fiducials). A comprehensive [https://github.com/Slicer/Slicer/blob/master/Modules/Loadable/Annotations/SubjectHierarchyPlugins/AnnotationsSubjectHierarchyPlugin.py subject hierarchy plugin example] is for the Annotations module.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  def viewContextMenuActions(self):&lt;br /&gt;
    return [self.doSomething]&lt;br /&gt;
&lt;br /&gt;
  def showViewContextMenuActionsForItem(self, itemID, eventData):&lt;br /&gt;
    if not itemID:&lt;br /&gt;
      logging.error('Invalid item for view context menu ' + str(itemID))&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    pluginHandlerSingleton = slicer.qSlicerSubjectHierarchyPluginHandler.instance()&lt;br /&gt;
    shNode = pluginHandlerSingleton.subjectHierarchyNode()&lt;br /&gt;
    if shNode is None:&lt;br /&gt;
      logging.error('Failed to access subject hierarchy node')&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    associatedNode = shNode.GetItemDataNode(itemID)&lt;br /&gt;
    if not associatedNode or not associatedNode.IsA(&amp;quot;vtkMRMLMarkupsNode&amp;quot;):&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    self.viewMenuEventData = eventData&lt;br /&gt;
    self.viewMenuEventData['NodeID'] = associatedNode.GetID()&lt;br /&gt;
&lt;br /&gt;
  def onDoSomething(self):&lt;br /&gt;
    nodeID = self.viewMenuEventData['NodeID']&lt;br /&gt;
    markupsNode = slicer.mrmlScene.GetNodeByID(nodeID)&lt;br /&gt;
    if markupsNode is None or not markupsNode.IsA(&amp;quot;vtkMRMLMarkupsNode&amp;quot;):&lt;br /&gt;
      logging.error('Failed to get fiducial markups node by ID ' + str(nodeID))&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    componentIndex = self.viewMenuEventData['ComponentIndex']&lt;br /&gt;
    markupID = markupsNode.GetNthMarkupID(componentIndex)&lt;br /&gt;
    &lt;br /&gt;
    # Do something with the clicked fiducial&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Write markup positions to JSON file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Write annotation ROI to JSON file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a simple surface mesh as a model node==&lt;br /&gt;
&lt;br /&gt;
This example shows how to display a simple surface mesh (a box, created by a VTK source filter) as a model node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create and set up polydata source&lt;br /&gt;
box = vtk.vtkCubeSource()&lt;br /&gt;
box.SetXLength(30)&lt;br /&gt;
box.SetYLength(20)&lt;br /&gt;
box.SetZLength(15)&lt;br /&gt;
box.SetCenter(10,20,5)&lt;br /&gt;
&lt;br /&gt;
# Create a model node that displays output of the source&lt;br /&gt;
boxNode = slicer.modules.models.logic().AddModel(box.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Adjust display properties&lt;br /&gt;
boxNode.GetDisplayNode().SetColor(1,0,0)&lt;br /&gt;
boxNode.GetDisplayNode().SetOpacity(0.8)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure distance of points from surface==&lt;br /&gt;
&lt;br /&gt;
This example computes closest distance of points (markups fiducial 'F') from a surface (model node 'mymodel') and writes results into a table.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
modelNode = getNode('mymodel')&lt;br /&gt;
&lt;br /&gt;
# Transform model polydata to world coordinate system&lt;br /&gt;
if modelNode.GetParentTransformNode():&lt;br /&gt;
    transformModelToWorld = vtk.vtkGeneralTransform()&lt;br /&gt;
    slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(modelNode.GetParentTransformNode(), None, transformModelToWorld)&lt;br /&gt;
    polyTransformToWorld = vtk.vtkTransformPolyDataFilter()&lt;br /&gt;
    polyTransformToWorld.SetTransform(transformModelToWorld)&lt;br /&gt;
    polyTransformToWorld.SetInputData(modelNode.GetPolyData())&lt;br /&gt;
    polyTransformToWorld.Update()&lt;br /&gt;
    surface_World = polyTransformToWorld.GetOutput()&lt;br /&gt;
else:&lt;br /&gt;
    surface_World = modelNode.GetPolyData()&lt;br /&gt;
&lt;br /&gt;
# Create arrays to store results&lt;br /&gt;
indexCol = vtk.vtkIntArray()&lt;br /&gt;
indexCol.SetName(&amp;quot;Index&amp;quot;)&lt;br /&gt;
labelCol = vtk.vtkStringArray()&lt;br /&gt;
labelCol.SetName(&amp;quot;Name&amp;quot;)&lt;br /&gt;
distanceCol = vtk.vtkDoubleArray()&lt;br /&gt;
distanceCol.SetName(&amp;quot;Distance&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
distanceFilter = vtk.vtkImplicitPolyDataDistance()&lt;br /&gt;
distanceFilter.SetInput(surface_World);&lt;br /&gt;
nOfFiduciallPoints = markupsNode.GetNumberOfFiducials()&lt;br /&gt;
for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    point_World = [0,0,0]&lt;br /&gt;
    markupsNode.GetNthControlPointPositionWorld(i, point_World)&lt;br /&gt;
    closestPointOnSurface_World = [0,0,0]&lt;br /&gt;
    closestPointDistance = distanceFilter.EvaluateFunctionAndGetClosestPoint(point_World, closestPointOnSurface_World)&lt;br /&gt;
    indexCol.InsertNextValue(i)&lt;br /&gt;
    labelCol.InsertNextValue(markupsNode.GetNthControlPointLabel(i))&lt;br /&gt;
    distanceCol.InsertNextValue(closestPointDistance)&lt;br /&gt;
&lt;br /&gt;
# Create a table from result arrays&lt;br /&gt;
resultTableNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;, &amp;quot;Points from surface distance&amp;quot;)&lt;br /&gt;
resultTableNode.AddColumn(indexCol)&lt;br /&gt;
resultTableNode.AddColumn(labelCol)&lt;br /&gt;
resultTableNode.AddColumn(distanceCol)&lt;br /&gt;
&lt;br /&gt;
# Show table in view layout&lt;br /&gt;
slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpTableView)&lt;br /&gt;
slicer.app.applicationLogic().GetSelectionNode().SetReferenceActiveTableID(resultTableNode.GetID())&lt;br /&gt;
slicer.app.applicationLogic().PropagateTableSelection()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Add a texture mapped plane to the scene as a model==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create model node&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
planeSource.SetOrigin(-50.0, -50.0, 0.0)&lt;br /&gt;
planeSource.SetPoint1(50.0, -50.0, 0.0)&lt;br /&gt;
planeSource.SetPoint2(-50.0, 50.0, 0.0)&lt;br /&gt;
model = slicer.modules.models.logic().AddModel(planeSource.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Tune display properties&lt;br /&gt;
modelDisplay = model.GetDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
&lt;br /&gt;
# Add texture (just use image of an ellipsoid)&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
modelDisplay.SetTextureImageDataConnection(e.GetOutputPort())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get scalar values at surface of a model==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Select cells of a model using markups fiducial points==&lt;br /&gt;
&lt;br /&gt;
The following script selects cells of a model node that are closest to positions of markups fiducial points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get input nodes&lt;br /&gt;
modelNode = slicer.util.getNode('Segment_1') # select cells in this model&lt;br /&gt;
markupsNode = slicer.util.getNode('F') # points will be selected at positions specified by this markups fiducial node&lt;br /&gt;
&lt;br /&gt;
# Create scalar array that will store selection state&lt;br /&gt;
cellScalars = modelNode.GetMesh().GetCellData()&lt;br /&gt;
selectionArray = cellScalars.GetArray('selection')&lt;br /&gt;
if not selectionArray:&lt;br /&gt;
    selectionArray = vtk.vtkIntArray()&lt;br /&gt;
    selectionArray.SetName('selection')&lt;br /&gt;
    selectionArray.SetNumberOfValues(modelNode.GetMesh().GetNumberOfCells())&lt;br /&gt;
    selectionArray.Fill(0)&lt;br /&gt;
    cellScalars.AddArray(selectionArray)&lt;br /&gt;
&lt;br /&gt;
# Set up coloring by selection array&lt;br /&gt;
modelNode.GetDisplayNode().SetActiveScalar(&amp;quot;selection&amp;quot;, vtk.vtkAssignAttribute.CELL_DATA)&lt;br /&gt;
modelNode.GetDisplayNode().SetAndObserveColorNodeID(&amp;quot;vtkMRMLColorTableNodeWarm1&amp;quot;)&lt;br /&gt;
modelNode.GetDisplayNode().SetScalarVisibility(True)&lt;br /&gt;
&lt;br /&gt;
# Initialize cell locator&lt;br /&gt;
cell = vtk.vtkCellLocator()&lt;br /&gt;
cell.SetDataSet(modelNode.GetMesh())&lt;br /&gt;
cell.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onPointsModified(observer=None, eventid=None):&lt;br /&gt;
    global markupsNode, selectionArray&lt;br /&gt;
    selectionArray.Fill(0) # set all cells to non-selected by default&lt;br /&gt;
    markupPoints = slicer.util.arrayFromMarkupsControlPoints(markupsNode)&lt;br /&gt;
    closestPoint = [0.0, 0.0, 0.0]&lt;br /&gt;
    cellObj = vtk.vtkGenericCell()&lt;br /&gt;
    cellId = vtk.mutable(0)&lt;br /&gt;
    subId = vtk.mutable(0)&lt;br /&gt;
    dist2 = vtk.mutable(0.0)&lt;br /&gt;
    for markupPoint in markupPoints:&lt;br /&gt;
        cell.FindClosestPoint(markupPoint, closestPoint, cellObj, cellId, subId, dist2)&lt;br /&gt;
        closestCell = cellId.get()&lt;br /&gt;
        if closestCell &amp;gt;=0:&lt;br /&gt;
            selectionArray.SetValue(closestCell, 100) # set selected cell's scalar value to non-zero&lt;br /&gt;
    selectionArray.Modified()&lt;br /&gt;
&lt;br /&gt;
# Initial update&lt;br /&gt;
onPointsModified()&lt;br /&gt;
# Automatic update each time when a markup point is modified&lt;br /&gt;
markupsNodeObserverTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsFiducialNode.PointModifiedEvent, onPointsModified)&lt;br /&gt;
&lt;br /&gt;
# To stop updating selection, run this:&lt;br /&gt;
# markupsNode.RemoveObserver(markupsNodeObserverTag)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export entire scene as VRML==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export model to Blender, including color by scalar==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export a tract (FiberBundle) to Blender, including color==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Iterate over tract (FiberBundle) streamline points==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Clone a node==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Clone a volume==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create a new volume==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
imageData.GetPointData().GetScalars().Fill(fillVoxelValue)&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get value of a volume at specific voxel coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel value of &amp;quot;volumeNode&amp;quot; at &amp;quot;ijk&amp;quot; volume voxel coordinates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
ijk = [20,40,30]  # volume voxel coordinates&lt;br /&gt;
&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)  # get voxels as a numpy array&lt;br /&gt;
voxelValue = voxels[ijk[2], ijk[1], ijk[0]]  # note that numpy array index order is kji (not ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Modify voxels in a volume==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get volume voxel coordinates from markup fiducial RAS coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get markup fiducial RAS coordinates from volume voxel coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get the values of all voxels for a label value==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Access values in a DTI tensor volume==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change window/level (brightness/contrast) or colormap of a volume==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Make mouse left-click and drag on the image adjust window/level==&lt;br /&gt;
&lt;br /&gt;
In older Slicer versions, by default, left-click and drag in a slice view adjusted window/level of the displayed image. Window/level adjustment is now a new mouse mode that can be activated by clicking on its toolbar button or running this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.applicationLogic().GetInteractionNode().SetCurrentInteractionMode(slicer.vtkMRMLInteractionNode.AdjustWindowLevel)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create custom color table==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manipulate a Slice View==&lt;br /&gt;
&lt;br /&gt;
===Change slice offset===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Change slice orientation===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Show slice views in 3D window===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Reset field of view to show background volume maximized===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rotate slice views to volume plane===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Iterate over current visible slice views, and set foreground and background images===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     compositeNode = layoutManager.sliceWidget(sliceViewName).sliceLogic().GetSliceCompositeNode()&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a volume in slice views==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show comparison view of all model files a folder==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
modelDir = &amp;quot;c:/some/folder/containing/models&amp;quot;&lt;br /&gt;
modelFileExt = &amp;quot;stl&amp;quot;&lt;br /&gt;
numberOfColumns = 4&lt;br /&gt;
&lt;br /&gt;
import math&lt;br /&gt;
import os&lt;br /&gt;
modelFiles = list(f for f in os.listdir(modelDir) if f.endswith('.' + modelFileExt))&lt;br /&gt;
&lt;br /&gt;
# Create a custom layout&lt;br /&gt;
numberOfRows = int(math.ceil(len(modelFiles)/numberOfColumns))&lt;br /&gt;
customLayoutId=567  # we pick a random id that is not used by others&lt;br /&gt;
slicer.app.setRenderPaused(True)&lt;br /&gt;
customLayout = '&amp;lt;layout type=&amp;quot;vertical&amp;quot;&amp;gt;'&lt;br /&gt;
viewIndex = 0&lt;br /&gt;
for rowIndex in range(numberOfRows):&lt;br /&gt;
  customLayout += '&amp;lt;item&amp;gt;&amp;lt;layout type=&amp;quot;horizontal&amp;quot;&amp;gt;'&lt;br /&gt;
  for colIndex in range(numberOfColumns):&lt;br /&gt;
    name = os.path.basename(modelFiles[viewIndex]) if viewIndex &amp;lt; len(modelFiles) else &amp;quot;compare &amp;quot;+str(viewIndex)&lt;br /&gt;
    customLayout += '&amp;lt;item&amp;gt;&amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;'+name&lt;br /&gt;
    customLayout += '&amp;quot;&amp;gt;&amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;'+name+'&amp;lt;/property&amp;gt;&amp;lt;/view&amp;gt;&amp;lt;/item&amp;gt;'&lt;br /&gt;
    viewIndex += 1&lt;br /&gt;
  customLayout += '&amp;lt;/layout&amp;gt;&amp;lt;/item&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
customLayout += '&amp;lt;/layout&amp;gt;'&lt;br /&gt;
if not slicer.app.layoutManager().layoutLogic().GetLayoutNode().SetLayoutDescription(customLayoutId, customLayout):&lt;br /&gt;
    slicer.app.layoutManager().layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)&lt;br /&gt;
&lt;br /&gt;
slicer.app.layoutManager().setLayout(customLayoutId)&lt;br /&gt;
&lt;br /&gt;
# Load and show each model in a view&lt;br /&gt;
for modelIndex, modelFile in enumerate(modelFiles):&lt;br /&gt;
    # Show only one model in each view&lt;br /&gt;
    name = os.path.basename(modelFile)&lt;br /&gt;
    viewNode = slicer.mrmlScene.GetSingletonNode(name, &amp;quot;vtkMRMLViewNode&amp;quot;)&lt;br /&gt;
    viewNode.LinkedControlOn()&lt;br /&gt;
    modelNode = slicer.util.loadModel(modelDir+&amp;quot;/&amp;quot;+modelFile)&lt;br /&gt;
    modelNode.GetDisplayNode().AddViewNodeID(viewNode.GetID())&lt;br /&gt;
&lt;br /&gt;
slicer.app.setRenderPaused(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change opacity of foreground volume in slice views==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Fit slice plane to markup fiducials==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.zeros(3)&lt;br /&gt;
p2 = np.zeros(3)&lt;br /&gt;
p3 = np.zeros(3)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0.0, 0.0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save a series of images from a Slice View==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rasterize a model and save it to a series of image files==&lt;br /&gt;
&lt;br /&gt;
This example shows how to generate a stack of image files from an STL file:&lt;br /&gt;
&lt;br /&gt;
 inputModelFile = &amp;quot;/some/input/folder/SomeShape.stl&amp;quot;&lt;br /&gt;
 outputDir = &amp;quot;/some/output/folder&amp;quot;&lt;br /&gt;
 outputVolumeLabelValue = 100&lt;br /&gt;
 outputVolumeSpacingMm = [0.5, 0.5, 0.5]&lt;br /&gt;
 outputVolumeMarginMm = [10.0, 10.0, 10.0]&lt;br /&gt;
 &lt;br /&gt;
 # Read model&lt;br /&gt;
 inputModel = slicer.util.loadModel(inputModelFile)&lt;br /&gt;
 &lt;br /&gt;
 # Determine output volume geometry and create a corresponding reference volume&lt;br /&gt;
 import math&lt;br /&gt;
 import numpy as np&lt;br /&gt;
 bounds = np.zeros(6)&lt;br /&gt;
 inputModel.GetBounds(bounds)&lt;br /&gt;
 imageData = vtk.vtkImageData()&lt;br /&gt;
 imageSize = [ int((bounds[axis*2+1]-bounds[axis*2]+outputVolumeMarginMm[axis]*2.0)/outputVolumeSpacingMm[axis]) for axis in range(3) ]&lt;br /&gt;
 imageOrigin = [ bounds[axis*2]-outputVolumeMarginMm[axis] for axis in range(3) ]&lt;br /&gt;
 imageData.SetDimensions(imageSize)&lt;br /&gt;
 imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1)&lt;br /&gt;
 imageData.GetPointData().GetScalars().Fill(0)&lt;br /&gt;
 referenceVolumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
 referenceVolumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
 referenceVolumeNode.SetSpacing(outputVolumeSpacingMm)&lt;br /&gt;
 referenceVolumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
 referenceVolumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
 &lt;br /&gt;
 # Convert model to labelmap&lt;br /&gt;
 seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
 seg.SetReferenceImageGeometryParameterFromVolumeNode(referenceVolumeNode)&lt;br /&gt;
 slicer.modules.segmentations.logic().ImportModelToSegmentationNode(inputModel, seg)&lt;br /&gt;
 seg.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
 outputLabelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
 slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(seg, outputLabelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
 outputLabelmapVolumeArray = (slicer.util.arrayFromVolume(outputLabelmapVolumeNode) * outputVolumeLabelValue).astype('int8')&lt;br /&gt;
 &lt;br /&gt;
 # Write labelmap volume to series of TIFF files&lt;br /&gt;
 pip_install(&amp;quot;imageio&amp;quot;)&lt;br /&gt;
 import imageio&lt;br /&gt;
 for i in range(len(outputLabelmapVolumeArray)):&lt;br /&gt;
     imageio.imwrite(f'{outputDir}/image_{i:03}.tiff', outputLabelmapVolumeArray[i])&lt;br /&gt;
&lt;br /&gt;
==Save the scene into a new directory==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save the scene into a single MRB file==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save a node to file==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Center the 3D View on the Scene==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Display text in a 3D view or slice view==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide slice view annotations (DataProbe)==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Turning off interpolation==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Customize viewer layout==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;layout type=&amp;quot;vertical&amp;quot; split=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLSliceNode&amp;quot; singletontag=&amp;quot;Red&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;orientation&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewcolor&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/layout&amp;gt;&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Built-in layout IDs are all below 100, so you can choose any large random number&lt;br /&gt;
# for your custom layout ID.&lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
&lt;br /&gt;
# Switch to the new custom layout &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
You can use this code snippet to add a button to the layout selector toolbar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Add button to layout selector toolbar for this custom layout&lt;br /&gt;
viewToolBar = mainWindow().findChild('QToolBar', 'ViewToolBar')&lt;br /&gt;
layoutMenu = viewToolBar.widgetForAction(viewToolBar.actions()[0]).menu()&lt;br /&gt;
layoutSwitchActionParent = layoutMenu  # use `layoutMenu` to add inside layout list, use `viewToolBar` to add next the standard layout list&lt;br /&gt;
layoutSwitchAction = layoutSwitchActionParent.addAction(&amp;quot;My view&amp;quot;) # add inside layout list&lt;br /&gt;
layoutSwitchAction.setData(layoutId)&lt;br /&gt;
layoutSwitchAction.setIcon(qt.QIcon(':Icons/Go.png'))&lt;br /&gt;
layoutSwitchAction.setToolTip('3D and slice view')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Customize keyboard shortcuts==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's an example for cycling through Segment Editor effects (requested [https://discourse.slicer.org/t/is-there-a-keystroke-to-cycle-through-effects-in-segment-editor/10117/2 on the forum] for the [http://slicermorph.org SlicerMorph] project).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def cycleEffect(delta=1):&lt;br /&gt;
    try:&lt;br /&gt;
        orderedNames = list(slicer.modules.SegmentEditorWidget.editor.effectNameOrder())&lt;br /&gt;
        allNames = slicer.modules.SegmentEditorWidget.editor.availableEffectNames()&lt;br /&gt;
        for name in allNames:&lt;br /&gt;
            try:&lt;br /&gt;
                orderedNames.index(name)&lt;br /&gt;
            except ValueError:&lt;br /&gt;
                orderedNames.append(name)&lt;br /&gt;
        orderedNames.insert(0, None)&lt;br /&gt;
        activeEffect = slicer.modules.SegmentEditorWidget.editor.activeEffect()&lt;br /&gt;
        if activeEffect:&lt;br /&gt;
            activeName = slicer.modules.SegmentEditorWidget.editor.activeEffect().name&lt;br /&gt;
        else:&lt;br /&gt;
            activeName = None&lt;br /&gt;
        newIndex = (orderedNames.index(activeName) + delta) % len(orderedNames)&lt;br /&gt;
        slicer.modules.SegmentEditorWidget.editor.setActiveEffectByName(orderedNames[newIndex])&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        # module not active&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('`', lambda: cycleEffect(-1)),&lt;br /&gt;
    ('~', lambda: cycleEffect(1)),&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Disable certain user interactions in slice views==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change default slice view orientation==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set all slice views linked by default==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set crosshair jump mode to centered by default==&lt;br /&gt;
&lt;br /&gt;
You can change default slice jump mode (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
crosshair=slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLCrosshairNode&amp;quot;)&lt;br /&gt;
crosshair.SetCrosshairBehavior(crosshair.CenteredJumpSlice)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set up custom units in slice view ruler==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in range(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a slice view outside the view layout==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;TS&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
viewNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(layoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
viewWidget.sliceViewName = layoutName&lt;br /&gt;
viewWidget.sliceViewLabel = layoutLabel&lt;br /&gt;
c = viewNode.GetLayoutColor()&lt;br /&gt;
viewWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLSliceNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a 3D view outside the view layout==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;Test3DView&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;T3&amp;quot;&lt;br /&gt;
layoutColor = [1.0, 1.0, 0.0]&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML node&lt;br /&gt;
viewNode = slicer.vtkMRMLViewNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(layoutColor)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLThreeDWidget()&lt;br /&gt;
viewWidget.viewLabel = layoutLabel&lt;br /&gt;
viewWidget.viewColor = qt.QColor.fromRgbF(*layoutColor)&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLViewNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get displayable manager of a certain type for a certain view==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelDisplayableManager = None&lt;br /&gt;
threeDViewWidget = slicer.app.layoutManager().threeDWidget(0)&lt;br /&gt;
managers = vtk.vtkCollection()&lt;br /&gt;
threeDViewWidget.getDisplayableManagers(managers)&lt;br /&gt;
for i in range(managers.GetNumberOfItems()):&lt;br /&gt;
  obj = managers.GetItemAsObject(i)&lt;br /&gt;
  if obj.IsA('vtkMRMLModelDisplayableManager'):&lt;br /&gt;
    modelDisplayableManager = obj&lt;br /&gt;
    break&lt;br /&gt;
if modelDisplayableManager is None:&lt;br /&gt;
  logging.error('Failed to find the model displayable manager')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Running an ITK filter in Python using SimpleITK==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
&lt;br /&gt;
*See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
*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&lt;br /&gt;
&lt;br /&gt;
==Get current mouse coordinates in a slice view==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get DataProbe text==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get axial slice as numpy array==&lt;br /&gt;
&lt;br /&gt;
An axis-aligned (axial/sagittal/coronal/) slices of a volume can be extracted using simple numpy array indexing. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
sliceIndex = 12&lt;br /&gt;
&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)  # Get volume as numpy array&lt;br /&gt;
slice = voxels[sliceIndex:,:]  # Get one slice of the volume as numpy array&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get reformatted image from a slice viewer as numpy array==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print(voxels.shape)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Combine multiple volumes into one==&lt;br /&gt;
&lt;br /&gt;
This example combines two volumes into a new one by subtracting one from the other.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
[input1Volume, input2Volume] = SampleData.SampleDataLogic().downloadDentalSurgery()&lt;br /&gt;
&lt;br /&gt;
import slicer.util&lt;br /&gt;
a = slicer.util.arrayFromVolume(input1Volume)&lt;br /&gt;
b = slicer.util.arrayFromVolume(input2Volume)&lt;br /&gt;
&lt;br /&gt;
# 'a' and 'b' are numpy arrays,&lt;br /&gt;
# they can be combined using any numpy array operations&lt;br /&gt;
# to produce the result array 'c'&lt;br /&gt;
c = b-a&lt;br /&gt;
&lt;br /&gt;
volumeNode = slicer.modules.volumes.logic().CloneVolume(input1Volume, &amp;quot;Difference&amp;quot;)&lt;br /&gt;
slicer.util.updateVolumeFromArray(volumeNode, c)&lt;br /&gt;
setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Add noise to image==&lt;br /&gt;
&lt;br /&gt;
This example shows how to add simulated noise to a volume.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Get a sample input volume node&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Get volume as numpy array and add noise&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
voxels[:] = voxels + np.random.normal(0.0, 20.0, size=voxels.shape)&lt;br /&gt;
slicer.util.arrayFromVolumeModified(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Apply random deformations to image==&lt;br /&gt;
&lt;br /&gt;
This example shows how to apply random translation, rotation, and deformations to a volume to simulate variation in patient positioning, soft tissue motion, and random anatomical variations.&lt;br /&gt;
Control points are placed on a regularly spaced grid and then each control point is displaced by a random amount.&lt;br /&gt;
Thin-plate spline transform is computed from the original and transformed point list.&lt;br /&gt;
&lt;br /&gt;
https://gist.github.com/lassoan/428af5285da75dc033d32ebff65ba940&lt;br /&gt;
&lt;br /&gt;
==Thick slab reconstruction and maximum/minimum intensity volume projections==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
==Change default file type for nodes (that have never been saved yet)==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
==Change file type for saving for all volumes (with already existing storage nodes)==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Sequences==&lt;br /&gt;
&lt;br /&gt;
===Concatenate all sequences in the scene into a new sequence===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Segmentations==&lt;br /&gt;
&lt;br /&gt;
===Create a segmentation from a labelmap volume and display in 3D===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
===Export labelmap node from segmentation node===&lt;br /&gt;
&lt;br /&gt;
Export smallest possible labelmap:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export labelmap that matches geometry of a chosen reference volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export by pressing Ctrl+Shift+s key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPath = &amp;quot;c:/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def exportLabelmap():&lt;br /&gt;
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLSegmentationNode&amp;quot;)&lt;br /&gt;
    referenceVolumeNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
    labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
    slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
    filepath = outputPath + &amp;quot;/&amp;quot; + referenceVolumeNode.GetName()+&amp;quot;-label.nrrd&amp;quot;&lt;br /&gt;
    slicer.util.saveNode(labelmapVolumeNode, filepath)&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode.GetDisplayNode().GetColorNode())&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
    slicer.util.delayDisplay(&amp;quot;Segmentation saved to &amp;quot;+filepath)&lt;br /&gt;
&lt;br /&gt;
shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
shortcut.setKey(qt.QKeySequence('Ctrl+Shift+s'))&lt;br /&gt;
shortcut.connect( 'activated()', exportLabelmap)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Export model nodes from segmentation node===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode(&amp;quot;Segmentation&amp;quot;)&lt;br /&gt;
shNode = slicer.mrmlScene.GetSubjectHierarchyNode()&lt;br /&gt;
exportFolderItemId = shNode.CreateFolderItem(shNode.GetSceneItemID(), &amp;quot;Segments&amp;quot;)&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModels(segmentationNode, exportFolderItemId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Show a segmentation in 3D===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get a representation of a segment===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = slicer.vtkOrientedImageData()&lt;br /&gt;
segmentationNode.GetBinaryLabelmapRepresentation(segmentID, image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
segmentationNode.GetClosedSurfaceRepresentation(segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert all segments using default path and conversion parameters===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert all segments using custom path or conversion parameters===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Re-convert using a modified conversion parameter===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get centroid of a segment in world (RAS) coordinates===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get histogram of a segmented region ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate input data&lt;br /&gt;
################################################&lt;br /&gt;
&lt;br /&gt;
# Load master volume&lt;br /&gt;
import SampleData&lt;br /&gt;
sampleDataLogic = SampleData.SampleDataLogic()&lt;br /&gt;
masterVolumeNode = sampleDataLogic.downloadMRBrainTumor1()&lt;br /&gt;
&lt;br /&gt;
# Create segmentation&lt;br /&gt;
segmentationNode = slicer.vtkMRMLSegmentationNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(segmentationNode)&lt;br /&gt;
segmentationNode.CreateDefaultDisplayNodes() # only needed for display&lt;br /&gt;
segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(masterVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Create segment&lt;br /&gt;
tumorSeed = vtk.vtkSphereSource()&lt;br /&gt;
tumorSeed.SetCenter(-6, 30, 28)&lt;br /&gt;
tumorSeed.SetRadius(25)&lt;br /&gt;
tumorSeed.Update()&lt;br /&gt;
segmentationNode.AddSegmentFromClosedSurfaceRepresentation(tumorSeed.GetOutput(), &amp;quot;Segment A&amp;quot;, [1.0,0.0,0.0])&lt;br /&gt;
&lt;br /&gt;
# Compute histogram&lt;br /&gt;
################################################&lt;br /&gt;
&lt;br /&gt;
labelValue = 1  # label value of first segment&lt;br /&gt;
&lt;br /&gt;
# Get segmentation as labelmap volume node&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, masterVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Extract all voxels of the segment as numpy array&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(masterVolumeNode)&lt;br /&gt;
labelArray = slicer.util.arrayFromVolume(labelmapVolumeNode)&lt;br /&gt;
segmentVoxels = volumeArray[labelArray==labelValue]&lt;br /&gt;
&lt;br /&gt;
# Compute histogram&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(segmentVoxels, bins=50)&lt;br /&gt;
&lt;br /&gt;
# Plot histogram&lt;br /&gt;
################################################&lt;br /&gt;
&lt;br /&gt;
slicer.util.plot(histogram, xColumnIndex = 1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to run segment editor effects from a script===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
*[https://gist.github.com/lassoan/ef30bc27a22a648ead7f82243f5cc7d5 AI-assisted brain tumor segmentation]&lt;br /&gt;
*[https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
*[https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
*[https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
*[https://gist.github.com/lassoan/4d0b94bda52d5b099432e424e03aa2b1 segment cranial cavity automatically in dry bone skull CT]&lt;br /&gt;
*[https://gist.github.com/lassoan/84d1f9a093dbb6a46c0fcc89279d8088 remove patient table from CT image]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
==Quantifying segments==&lt;br /&gt;
&lt;br /&gt;
===Get size, position, and orientation of each segment===&lt;br /&gt;
&lt;br /&gt;
This example computes oriented bounding box for each segment and displays them using annotation ROI.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
&lt;br /&gt;
# Compute bounding boxes&lt;br /&gt;
import SegmentStatistics&lt;br /&gt;
segStatLogic = SegmentStatistics.SegmentStatisticsLogic()&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;Segmentation&amp;quot;, segmentationNode.GetID())&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_origin_ras.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_diameter_mm.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_x.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_y.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_z.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.computeStatistics()&lt;br /&gt;
stats = segStatLogic.getStatistics()&lt;br /&gt;
&lt;br /&gt;
# Draw ROI for each oriented bounding box&lt;br /&gt;
import numpy as np&lt;br /&gt;
for segmentId in stats['SegmentIDs']:&lt;br /&gt;
    # Get bounding box&lt;br /&gt;
    obb_origin_ras = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_origin_ras&amp;quot;])&lt;br /&gt;
    obb_diameter_mm = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_diameter_mm&amp;quot;])&lt;br /&gt;
    obb_direction_ras_x = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_x&amp;quot;])&lt;br /&gt;
    obb_direction_ras_y = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_y&amp;quot;])&lt;br /&gt;
    obb_direction_ras_z = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_z&amp;quot;])&lt;br /&gt;
    # Create ROI&lt;br /&gt;
    segment = segmentationNode.GetSegmentation().GetSegment(segmentId)&lt;br /&gt;
    roi=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLAnnotationROINode&amp;quot;)&lt;br /&gt;
    roi.SetName(segment.GetName()+' bounding box')&lt;br /&gt;
    roi.SetXYZ(0.0, 0.0, 0.0)&lt;br /&gt;
    roi.SetRadiusXYZ(*(0.5*obb_diameter_mm))&lt;br /&gt;
    # Position and orient ROI using a transform&lt;br /&gt;
    obb_center_ras = obb_origin_ras+0.5*(obb_diameter_mm[0] * obb_direction_ras_x + obb_diameter_mm[1] * obb_direction_ras_y + obb_diameter_mm[2] * obb_direction_ras_z)&lt;br /&gt;
    boundingBoxToRasTransform = np.row_stack((np.column_stack((obb_direction_ras_x, obb_direction_ras_y, obb_direction_ras_z, obb_center_ras)), (0, 0, 0, 1)))&lt;br /&gt;
    boundingBoxToRasTransformMatrix = slicer.util.vtkMatrixFromArray(boundingBoxToRasTransform)&lt;br /&gt;
    transformNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLTransformNode')&lt;br /&gt;
    transformNode.SetAndObserveMatrixTransformToParent(boundingBoxToRasTransformMatrix)&lt;br /&gt;
    roi.SetAndObserveTransformNodeID(transformNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Markups==&lt;br /&gt;
&lt;br /&gt;
===Load markups fiducial list from file===&lt;br /&gt;
&lt;br /&gt;
Markups fiducials can be loaded from file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.loadMarkupsFiducialList('/path/to/list/F.fcsv')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding Fiducials Programatically ===&lt;br /&gt;
&lt;br /&gt;
Markups fiducials can be added to the currently active list from the python console by using the following module logic command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.modules.markups.logic().AddFiducial()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command with no arguments will place a new fiducial at the origin. You can also pass it an initial location:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.modules.markups.logic().AddFiducial(1.0, -2.0, 3.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Add a button to module GUI to activate fiducial placement ===&lt;br /&gt;
&lt;br /&gt;
This code snippet creates a toggle button, which activates fiducial placement when pressed (and deactivates when released).&lt;br /&gt;
&lt;br /&gt;
The [http://apidocs.slicer.org/master/classqSlicerMarkupsPlaceWidget.html qSlicerMarkupsPlaceWidget widget] can automatically activate placement of multiple points and can show buttons for deleting points, changing colors, lock, and hide points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
w=slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
w.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
markupsNodeID = slicer.modules.markups.logic().AddNewFiducialNode()&lt;br /&gt;
w.setCurrentNode(slicer.mrmlScene.GetNodeByID(markupsNodeID))&lt;br /&gt;
# Hide all buttons and only show place button&lt;br /&gt;
w.buttonsVisible=False&lt;br /&gt;
w.placeButton().show()&lt;br /&gt;
w.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding Fiducials via Mouse Clicks ===&lt;br /&gt;
&lt;br /&gt;
You can also set the mouse mode into Markups fiducial placement by calling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
placeModePersistence = 1&lt;br /&gt;
slicer.modules.markups.logic().StartPlaceMode(placeModePersistence)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A lower level way to do this is via the selection and interaction nodes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
selectionNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSelectionNodeSingleton&amp;quot;)&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
interactionNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLInteractionNodeSingleton&amp;quot;)&lt;br /&gt;
placeModePersistence = 1&lt;br /&gt;
interactionNode.SetPlaceModePersistence(placeModePersistence)&lt;br /&gt;
# mode 1 is Place, can also be accessed via slicer.vtkMRMLInteractionNode().Place&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To switch back to view transform once you're done placing fiducials:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLInteractionNodeSingleton&amp;quot;)&lt;br /&gt;
interactionNode.SwitchToViewTransformMode()&lt;br /&gt;
# also turn off place mode persistence if required&lt;br /&gt;
interactionNode.SetPlaceModePersistence(0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Access to Fiducial Properties ===&lt;br /&gt;
&lt;br /&gt;
Each vtkMRMLMarkupsFiducialNode has a vector of points in it which can be accessed from python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fidNode = getNode(&amp;quot;vtkMRMLMarkupsFiducialNode1&amp;quot;)&lt;br /&gt;
n = fidNode.AddFiducial(4.0, 5.5, -6.0)&lt;br /&gt;
fidNode.SetNthFiducialLabel(n, &amp;quot;new label&amp;quot;)&lt;br /&gt;
# each markup is given a unique id which can be accessed from the superclass level&lt;br /&gt;
id1 = fidNode.GetNthMarkupID(n)&lt;br /&gt;
# manually set the position&lt;br /&gt;
fidNode.SetNthFiducialPosition(n, 6.0, 7.0, 8.0)&lt;br /&gt;
# set the label&lt;br /&gt;
fidNode.SetNthFiducialLabel(n, &amp;quot;New label&amp;quot;)&lt;br /&gt;
# set the selected flag, only selected = 1 fiducials will be passed to CLIs&lt;br /&gt;
fidNode.SetNthFiducialSelected(n, 1)&lt;br /&gt;
# set the visibility flag&lt;br /&gt;
fidNode.SetNthFiducialVisibility(n, 0)  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can loop over the fiducials in a list and get the coordinates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fidList = slicer.util.getNode('F')&lt;br /&gt;
numFids = fidList.GetNumberOfFiducials()&lt;br /&gt;
for i in range(numFids):&lt;br /&gt;
  ras = [0,0,0]&lt;br /&gt;
  fidList.GetNthFiducialPosition(i,ras)&lt;br /&gt;
  # the world position is the RAS position with any transform matrices applied&lt;br /&gt;
  world = [0,0,0,0]&lt;br /&gt;
  fidList.GetNthFiducialWorldCoordinates(0,world)&lt;br /&gt;
  print(i,&amp;quot;: RAS =&amp;quot;,ras,&amp;quot;, world =&amp;quot;,world)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also look at the sample code in the [https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/Endoscopy/Endoscopy.py#L287  Endoscopy module] to see how python is used to access fiducials from a scripted module.&lt;br /&gt;
&lt;br /&gt;
==Accessing views, renderers, and cameras==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide view controller bars==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Customize widgets in view controller bars==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceController = slicer.app.layoutManager().sliceWidget(&amp;quot;Red&amp;quot;).sliceController()&lt;br /&gt;
&lt;br /&gt;
# hide what is not needed&lt;br /&gt;
sliceController.pinButton().hide()&lt;br /&gt;
#sliceController.viewLabel().hide()&lt;br /&gt;
sliceController.fitToWindowToolButton().hide()&lt;br /&gt;
sliceController.sliceOffsetSlider().hide()&lt;br /&gt;
&lt;br /&gt;
# add custom widgets&lt;br /&gt;
myButton = qt.QPushButton(&amp;quot;My custom button&amp;quot;)&lt;br /&gt;
sliceController.barLayout().addWidget(b)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change 3D view background color==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNode = slicer.app.layoutManager().threeDWidget(0).mrmlViewNode()&lt;br /&gt;
viewNode.SetBackgroundColor(1,0,0)&lt;br /&gt;
viewNode.SetBackgroundColor2(1,0,0)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide Slicer logo from main window (to increase space)==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.findChild(slicer.util.mainWindow(), 'LogoLabel').visible = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subject hierarchy== &lt;br /&gt;
====Get the pseudo-singleton subject hierarchy node====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.mrmlScene.GetSubjectHierarchyNode()&lt;br /&gt;
&lt;br /&gt;
====Create subject hierarchy item====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
====Get subject hierarchy item====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
====Traverse children of a subject hierarchy item====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in range(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
====Manipulate subject hierarchy item====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data node associated to an item&lt;br /&gt;
  shNode.SetItemDisplayVisibility(itemID, 1)&lt;br /&gt;
  # Set visibility of whole branch&lt;br /&gt;
  # Note: Folder-type items (fodler, subject, study, etc.) create their own display nodes when show/hiding from UI.&lt;br /&gt;
  #       The displayable managers use SH information to determine visibility of an item, so no need to show/hide individual leaf nodes any more.&lt;br /&gt;
  #       Once the folder display node is created, it can be shown hidden simply using shNode.SetItemDisplayVisibility&lt;br /&gt;
  # From python, this is how to trigger creating a folder display node&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler().instance()&lt;br /&gt;
  folderPlugin = pluginHandler.pluginByName('Folder')&lt;br /&gt;
  folderPlugin.setDisplayVisibility(folderItemID, 1)&lt;br /&gt;
&lt;br /&gt;
====Filter items in TreeView or ComboBox====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
===Listen to subject hierarchy item events===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
===Subject hierarchy plugin offering view context menu action===&lt;br /&gt;
If an object that supports view context menus (e.g. markups) is right-clicked in a slice or 3D view, it can offer custom actions. Due to internal limitations these plugins must be set up differently, as explained [https://github.com/Slicer/Slicer/blob/master/Modules/Loadable/Annotations/SubjectHierarchyPlugins/AnnotationsSubjectHierarchyPlugin.py#L96-L107 here]. This example makes it easier to create such a plugin.&lt;br /&gt;
&lt;br /&gt;
  import os&lt;br /&gt;
  import vtk, qt, ctk, slicer&lt;br /&gt;
  from slicer.ScriptedLoadableModule import *&lt;br /&gt;
  &lt;br /&gt;
  from SubjectHierarchyPlugins import AbstractScriptedSubjectHierarchyPlugin&lt;br /&gt;
  &lt;br /&gt;
  class ViewContextMenuTest(ScriptedLoadableModule):&lt;br /&gt;
      def __init__(self, parent):&lt;br /&gt;
          ScriptedLoadableModule.__init__(self, parent)&lt;br /&gt;
          parent.title = &amp;quot;Test Subject Hierarchy Plugin Loader&amp;quot;&lt;br /&gt;
          &lt;br /&gt;
          # register subject hierarchy plugin once app is initialized&lt;br /&gt;
          def onStartupCompleted():&lt;br /&gt;
            import SubjectHierarchyPlugins&lt;br /&gt;
            from ViewContextMenuTest import ViewContextMenuTestSubjectHierarchyPlugin&lt;br /&gt;
            scriptedPlugin = slicer.qSlicerSubjectHierarchyScriptedPlugin(None)&lt;br /&gt;
            scriptedPlugin.setPythonSource(ViewContextMenuTestSubjectHierarchyPlugin.filePath)&lt;br /&gt;
            pluginHandlerSingleton = slicer.qSlicerSubjectHierarchyPluginHandler.instance()&lt;br /&gt;
            pluginHandlerSingleton.registerPlugin(scriptedPlugin)&lt;br /&gt;
          slicer.app.connect(&amp;quot;startupCompleted()&amp;quot;, onStartupCompleted)&lt;br /&gt;
  &lt;br /&gt;
  class ViewContextMenuTestWidget(ScriptedLoadableModuleWidget):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; dummy module widget to allow reloading in developer mode &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    def setup(self):&lt;br /&gt;
      ScriptedLoadableModuleWidget.setup(self)&lt;br /&gt;
  &lt;br /&gt;
  class ViewContextMenuTestSubjectHierarchyPlugin(AbstractScriptedSubjectHierarchyPlugin):&lt;br /&gt;
  &lt;br /&gt;
    # Necessary static member to be able to set python source to scripted subject hierarchy plugin&lt;br /&gt;
    filePath = __file__&lt;br /&gt;
    &lt;br /&gt;
    def __init__(self, scriptedPlugin):&lt;br /&gt;
      # AbstractScriptedSubjectHierarchyPlugin.__init__(self, scriptedPlugin) # This call needs to be commented out!&lt;br /&gt;
      &lt;br /&gt;
      self.viewAction = qt.QAction(f&amp;quot;CUSTOM VIEW ...&amp;quot;, scriptedPlugin)&lt;br /&gt;
      self.viewAction.objectName = 'CustomViewAction' # Necessary for the white list (see pluginLogic.setDisplayedViewMenuActionNames)&lt;br /&gt;
      self.viewAction.connect(&amp;quot;triggered()&amp;quot;, self.onViewAction)&lt;br /&gt;
      &lt;br /&gt;
    def onViewAction(self):&lt;br /&gt;
      print(f&amp;quot;VIEW ACTION&amp;quot;)&lt;br /&gt;
      &lt;br /&gt;
    def viewContextMenuActions(self):&lt;br /&gt;
      return [self.viewAction]&lt;br /&gt;
      &lt;br /&gt;
    def showViewContextMenuActionsForItem(self, itemID, eventData=None):&lt;br /&gt;
      self.viewAction.visible = True&lt;br /&gt;
&lt;br /&gt;
===Use whitelist to customize view menu===&lt;br /&gt;
When right-clicking certain types of nodes in the 2D/3D views, a subject hierarchy menu pops up. If menu actions need to be removed, a whitelist can be used to specify the ones that should show up.&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler.instance()&lt;br /&gt;
  pluginLogic = pluginHandler.pluginLogic()&lt;br /&gt;
  menuActions = pluginLogic.availableViewMenuActionNames()&lt;br /&gt;
  # Returns ('RenamePointAction', 'DeletePointAction', 'ToggleSelectPointAction', 'EditPropertiesAction')&lt;br /&gt;
  newActions = ['RenamePointAction']&lt;br /&gt;
  pluginLogic.setDisplayedViewMenuActionNames(newActions)&lt;br /&gt;
&lt;br /&gt;
==Plotting==&lt;br /&gt;
&lt;br /&gt;
===Slicer plots displayed in view layout===&lt;br /&gt;
&lt;br /&gt;
Create histogram plot of a volume and show it embedded in the view layout. More information: https://www.slicer.org/wiki/Documentation/Nightly/Developers/Plots&lt;br /&gt;
&lt;br /&gt;
====Using &amp;lt;code&amp;gt;slicer.util.plot&amp;lt;/code&amp;gt; utility function====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
chartNode = slicer.util.plot(histogram, xColumnIndex = 1)&lt;br /&gt;
chartNode.SetYAxisRangeAuto(False)&lt;br /&gt;
chartNode.SetYAxisRange(0, 4e5)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:SlicerPlot.png]]&lt;br /&gt;
&lt;br /&gt;
====Using MRML classes only====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using matplotlib===&lt;br /&gt;
&lt;br /&gt;
Matplotlib may be used from within Slicer, but the default Tk backend locks up and crashes Slicer. However, Matplotlib may still be used through other backends. More details can be found on the [http://matplotlib.sourceforge.net/ MatPlotLib] pages.&lt;br /&gt;
&lt;br /&gt;
====Non-interactive plot====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
&lt;br /&gt;
# Static image view&lt;br /&gt;
pm = qt.QPixmap(&amp;quot;MatplotlibExample.png&amp;quot;)&lt;br /&gt;
imageWidget = qt.QLabel()&lt;br /&gt;
imageWidget.setPixmap(pm)&lt;br /&gt;
imageWidget.setScaledContents(True)&lt;br /&gt;
imageWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:MatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
====Plot in Slicer Jupyter notebook====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
display(filename='MatplotlibExample.png', type=&amp;quot;image/png&amp;quot;, binary=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:JupyterNotebookMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
====Interactive plot using wxWidgets GUI toolkit====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
  import wx&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib wxPython')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Set matplotlib to use WXAgg backend&lt;br /&gt;
import matplotlib&lt;br /&gt;
matplotlib.use('WXAgg')&lt;br /&gt;
&lt;br /&gt;
# Show an interactive plot&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
fig, ax = plt.subplots()&lt;br /&gt;
ax.plot(histogram[1][1:], histogram[0].astype(float))&lt;br /&gt;
ax.grid(True)&lt;br /&gt;
ax.set_ylim((0, 4e5))&lt;br /&gt;
plt.show(block=False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:InteractiveMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==Execute external applications==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
===Run process in default environment===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;br /&gt;
&lt;br /&gt;
==Manage extensions==&lt;br /&gt;
&lt;br /&gt;
===Download and install extension===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensionName = 'SlicerIGT'&lt;br /&gt;
em = slicer.app.extensionsManagerModel()&lt;br /&gt;
if not em.isExtensionInstalled(extensionName):&lt;br /&gt;
    extensionMetaData = em.retrieveExtensionMetadataByName(extensionName)&lt;br /&gt;
    url = em.serverUrl().toString()+'/download/item/'+extensionMetaData['item_id']&lt;br /&gt;
    extensionPackageFilename = slicer.app.temporaryPath+'/'+extensionMetaData['md5']&lt;br /&gt;
    slicer.util.downloadFile(url, extensionPackageFilename)&lt;br /&gt;
    em.installExtension(extensionPackageFilename)&lt;br /&gt;
    slicer.util.restart()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Labs/Slicer5-roadmap&amp;diff=63195</id>
		<title>Documentation/Labs/Slicer5-roadmap</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Labs/Slicer5-roadmap&amp;diff=63195"/>
		<updated>2020-05-01T10:41:13Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Revisit MRML Copy API */ Done&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The major version number upgrade to 5 provides an opportunity to make changes that affect the&lt;br /&gt;
application, the API, or the code in a way that was not possible in the past seven or so years.&lt;br /&gt;
&lt;br /&gt;
This page collects community suggestions related to the transition plan for Slicer 4.10 and major changes for Slicer 5.x&lt;br /&gt;
&lt;br /&gt;
Related forum post: https://discourse.slicer.org/t/slicer-5-0-deprecation-discussion-wiki/2377&lt;br /&gt;
&lt;br /&gt;
==Overall Goals==&lt;br /&gt;
&lt;br /&gt;
*Improve user experience&lt;br /&gt;
**More logical interface&lt;br /&gt;
**Perform most common tasks easily&lt;br /&gt;
**Easier to discover advanced features&lt;br /&gt;
**Improve asynchronous behavior (like loading data in a background thread)&lt;br /&gt;
*Defining core and extensions&lt;br /&gt;
**Core functionality is:&lt;br /&gt;
***DICOM and other format I/O, Subject management&lt;br /&gt;
***Visualization 2D/3D/4D&lt;br /&gt;
***Segmentation&lt;br /&gt;
***Transforms and Registration&lt;br /&gt;
***Annotations and Markups&lt;br /&gt;
***Programmability and Extensibility&lt;br /&gt;
**Move some extensions to core (Sequences, DICOMPlugins...)&lt;br /&gt;
**Move some core to extensions (SimpleITK, Editor...)&lt;br /&gt;
*Simplify maintenance&lt;br /&gt;
**Remove legacy code that adds more complexity than value&lt;br /&gt;
**Deprecate support for older build options and platforms (old libs, old compilers, etc)&lt;br /&gt;
**Simplify documentation creation and use&lt;br /&gt;
**Streamline the build and release process&lt;br /&gt;
**Use unmodified upstream libraries&lt;br /&gt;
*Developer experience&lt;br /&gt;
**Improve API / Scripting documentation organization / search engine optimization&lt;br /&gt;
**Simplify/accelerate build process on all platforms (options to use prebuilt sdk for example)&lt;br /&gt;
**Use standard packages (Qt, Python, VTK, ITK)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Specific Change Proposals==&lt;br /&gt;
&lt;br /&gt;
===Slicer 5.0: Backward incompatible changes===&lt;br /&gt;
&lt;br /&gt;
====Third-party library updates====&lt;br /&gt;
&lt;br /&gt;
*Update to latest VTK: may fix issues in rendering (Virtual Reality Qt widget, [https://discourse.slicer.org/t/setting-of-markerstyle-does-not-work/9073/6 plot line markers])&lt;br /&gt;
*Update to latest Qt: May fix [https://discourse.slicer.org/t/extension-wizard-file-open-dialogs-hang-ui-for-several-seconds/7881/9 Qt temporary hang] on startup and when showing file dialog&lt;br /&gt;
&lt;br /&gt;
====Python3====&lt;br /&gt;
&lt;br /&gt;
Switch to Python3 and use the same compiler as official Python distribution. This would allow installation of any Python package inside Slicer's Python environment.&lt;br /&gt;
&lt;br /&gt;
Tasks:&lt;br /&gt;
&lt;br /&gt;
*Update of CTK: Build system, CTK Python console and [https://github.com/commontk/CTK/blob/master/CMake/ctkWrapPythonQt.py ctkWrapPythonQt.py] - '''DONE''' {{done}}&lt;br /&gt;
*Update [https://github.com/Slicer/Slicer/blob/master/SuperBuild/External_python.cmake External_python.cmake] - '''DONE''' {{done}}&lt;br /&gt;
*Update of &amp;quot;C++ to python bridge&amp;quot; classes ([https://github.com/Slicer/Slicer/blob/master/Base/QTCore/qSlicerScriptedUtils_p.h qSlicerScriptedUtils_p.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTGUI/qSlicerScriptedLoadableModule.h qSlicerScriptedLoadableModule.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTGUI/qSlicerScriptedFileDialog.h qSlicerScriptedFileDialog.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTGUI/qSlicerScriptedLoadableModuleWidget.h qSlicerScriptedLoadableModuleWidget.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTCore/qSlicerScriptedFileWriter.h qSlicerScriptedFileWriter.h], ...) - '''DONE''' {{done}}&lt;br /&gt;
*Update of install rules and macos fixup - '''DONE''' {{done}}&lt;br /&gt;
*Update of python scripts to be compliant with python 3 - '''DONE''' {{done}}&lt;br /&gt;
&lt;br /&gt;
Some of the issues discovered after integration of Python 3:&lt;br /&gt;
&lt;br /&gt;
*Fix iomodule.c build error with VS2017. See https://github.com/Slicer/Slicer/pull/1118#issuecomment-482436689. Fixed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=28138 r28138] - '''DONE''' {{done}}&lt;br /&gt;
*Fix crash in Debug build. See https://github.com/lassoan/Slicer/tree/python-startup-hang-in-debug-mode. Fixed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=28141 r28141] - '''DONE''' {{done}}&lt;br /&gt;
*&amp;lt;tt&amp;gt;restart()&amp;lt;/tt&amp;gt; Python function does not work. Fixed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=28143 r28143] - '''DONE''' {{done}}&lt;br /&gt;
&lt;br /&gt;
References:&lt;br /&gt;
&lt;br /&gt;
*discourse post: https://discourse.slicer.org/t/updating-slicer-to-work-with-python-3/4662/14&lt;br /&gt;
*GitHub PR: https://github.com/Slicer/Slicer/pull/1118&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Revisit MRML Copy API====&lt;br /&gt;
&lt;br /&gt;
Copy method does not perform complete deep-copy in some classes. For Sequences, we need both DeepCopy (for node modifications) and ShallowCopy (for fast replay possible).&lt;br /&gt;
&lt;br /&gt;
There are also too many variants of node copy methods, which makes it difficult to use them correctly.&lt;br /&gt;
&lt;br /&gt;
See also https://issues.slicer.org/view.php?id=2608.&lt;br /&gt;
&lt;br /&gt;
Assign to Andras Lasso. - '''DONE''' {{done}}&lt;br /&gt;
&lt;br /&gt;
====Coordinate system in files====&lt;br /&gt;
&lt;br /&gt;
To be consistent with the rest of the world: Save models and markups in LPS coordinate system by default. If no coordinate system is specified in input file, assume LPS. See https://issues.slicer.org/view.php?id=4445&lt;br /&gt;
&lt;br /&gt;
====Acquisition transform====&lt;br /&gt;
&lt;br /&gt;
Enable acquisition transform by default, to show correct loading of tilted gantry images. It has proven to work well.  See https://github.com/Slicer/Slicer/commit/b7650af3c27f34fc894bfdd587f2a4c02ba62a8b&lt;br /&gt;
&lt;br /&gt;
====Model Hierarchies====&lt;br /&gt;
&lt;br /&gt;
Remove Model Hierarchy feature and make sure that Subject Hierarchy covers all use cases.  This will impact ModelMaker, which should be converted to a simpler version that only returns models and not semantics.  Need to check extensions, especially SlicerDMRI, for any dependencies on Model Hierarchy. - '''DONE''' {{done}}&lt;br /&gt;
&lt;br /&gt;
====Extension description file format====&lt;br /&gt;
&lt;br /&gt;
Transition from [[Documentation/Nightly/Developers/Extensions/DescriptionFile|`.s4ext` text file]] to a json or yaml.&lt;br /&gt;
&lt;br /&gt;
===Remove deprecated modules and/or Migrate to extension===&lt;br /&gt;
&lt;br /&gt;
====Editor====&lt;br /&gt;
The module already directs users to Segment Editor, which provides all the functionality of Editor and more, and&lt;br /&gt;
is the successor module that will be improved and maintained. Removing it would decrease confusion of both old&lt;br /&gt;
and new Slicer users&lt;br /&gt;
&lt;br /&gt;
*Potentially the hack about modules with names ending with the string &amp;quot;Lib&amp;quot; can also be removed after the Editor module will not require it. It is [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Base/QTCore/qSlicerUtils.cxx?r1=26891&amp;amp;r2=26890&amp;amp;pathrev=26891 around here].&lt;br /&gt;
&lt;br /&gt;
*'''Make Editor hidden in 4.10, advertise its removal (some extensions still use it), then remove it in 5.0'''. Remove it from toolbar, move Editor to legacy category in 4.10&lt;br /&gt;
&lt;br /&gt;
*Investigate if the module could easily be moved to an extension&lt;br /&gt;
&lt;br /&gt;
====VectorToScalarVolume====&lt;br /&gt;
&lt;br /&gt;
The plan would be to improve the Volume module so that vector volume could be converted to scalar volume, similarly to scalar to labelmap conversion option. Then, this module could be removed.&lt;br /&gt;
&lt;br /&gt;
====Unused module code====&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;s&amp;gt;MultiVolumeRendering: A [https://github.com/Slicer/Slicer/tree/master/Modules/Loadable/MultiVolumeRendering module] that was effectively not developed since 2012, and is not currently compiled with Slicer.&amp;lt;/s&amp;gt; - Removed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27087 r27087]&lt;br /&gt;
*&amp;lt;s&amp;gt;Measurements: Same argument as MultiVolumeRendering&amp;lt;/s&amp;gt; - Removed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27087 r27087]&lt;br /&gt;
*&amp;lt;s&amp;gt;AtlasCreator Loadable module logic&amp;lt;/s&amp;gt; - Removed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27088 r27088]&lt;br /&gt;
&lt;br /&gt;
====CLI modules====&lt;br /&gt;
&lt;br /&gt;
*Model to Label Map: Has too many limitations and bugs (cannot handle concave structures, can cause Slicer to hang or crash, etc.), and is not maintained any more. It might be better to remove it than to fix it, especially that there is an algorithm for the same thing in Slicer that works much better&lt;br /&gt;
**The model node to labelmap node conversion feature could be added as a subject hierarchy plugin, if the route via segmentation node is not convenient enough&lt;br /&gt;
&lt;br /&gt;
*Review CLI modules&lt;br /&gt;
**BlobDetection&lt;br /&gt;
**ConnectedComponent&lt;br /&gt;
**GrayscaleModelMaker, ModelMaker: The modules are too different to combine them. Each have specific use cases.&lt;br /&gt;
**DiffusionTensorTest, ROITest, TestGridTransformRegistration: Already excluded from package by specifying &amp;lt;tt&amp;gt;NO_INSTALL&amp;lt;/tt&amp;gt;&lt;br /&gt;
**Resample Scalar Volume: Resample Scalar/Vector/DWI Volume module (which Crop Volume uses as well) can do everything it does already, except for four extra interpolation options. Probably can be removed&lt;br /&gt;
&lt;br /&gt;
====Migrate to extension====&lt;br /&gt;
&lt;br /&gt;
Existing [https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/DMRIInstall/DMRIInstall.py DMRIInstall] scripted module will be re-factored and moved into a &amp;lt;tt&amp;gt;Modules/Scripted/InstallSuggestions&amp;lt;/tt&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Then, after transitioning them to extension, the following module will be added to the &amp;quot;InstallSuggestions&amp;quot; so that the user knows how to install them:&lt;br /&gt;
&lt;br /&gt;
*BRAINSTools (also add SlicerElastix to the suggestions)&lt;br /&gt;
*SimpleITK: Only used in the editor&lt;br /&gt;
*EMSegment: already disabled in Slicer-4.10, so it may be completely removed from build scripts instead of moving it to an extension&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
*2018-12-13: Jc: Following discussion with Ron, we need to make sure to have at least one non-rigid registration method and one ICP based method (e.g Landmark Registration) available in the main distribution.&lt;br /&gt;
&lt;br /&gt;
====PETStandardUptakeValueComputation====&lt;br /&gt;
&lt;br /&gt;
Remove PETStandardUptakeValueComputation from Slicer core, as a more advanced version of this is available in an extension: https://github.com/QIICR/Slicer-PETDICOMExtension. See details here: https://github.com/Slicer/Slicer/pull/1068#issuecomment-450905887&lt;br /&gt;
&lt;br /&gt;
===Coding Style===&lt;br /&gt;
&lt;br /&gt;
====Slicer 5.0: Indentation of curly braces====&lt;br /&gt;
In Slicer the curly braces have a two-space indentation everywhere within functions. As this was inherited from VTK, but VTK changed its convention to align the braces with the statements (if etc.), it could make sense to make the change in Slicer too. This is considered a major change because it affects almost all cxx files.&lt;br /&gt;
&lt;br /&gt;
====Simpler VTK smart pointer usage====&lt;br /&gt;
Use &amp;lt;code&amp;gt;vtkNew&amp;lt;type&amp;gt; var;&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;vtkSmartPointer&amp;lt;type&amp;gt; var = vtkSmartPointer&amp;lt;type&amp;gt;::New();&amp;lt;/code&amp;gt; and remove now unnecessary &amp;lt;code&amp;gt;.GetPointer()&amp;lt;/code&amp;gt; calls.&lt;br /&gt;
&lt;br /&gt;
===Usability===&lt;br /&gt;
&lt;br /&gt;
====Volume Rendering Activation Method====&lt;br /&gt;
&lt;br /&gt;
We have had lots of issues with people finding the eye icon.&lt;br /&gt;
&lt;br /&gt;
===Miscellaneous===&lt;br /&gt;
&lt;br /&gt;
====Tcl codes====&lt;br /&gt;
&amp;lt;s&amp;gt;Most of the TCL code seems to be a heritage from Slicer3. Can they be removed?&amp;lt;/s&amp;gt; - Done in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27091 r27091]&lt;br /&gt;
&lt;br /&gt;
====Remove self-test modules from the All modules list====&lt;br /&gt;
Users already find the all modules list very long, and as the self tests are for developers only (and can be found in the modules list under the Testing category), they could be removed from the list.  Make sure they are available in Developer mode.&lt;br /&gt;
&lt;br /&gt;
====Remove BTX/ETX pairs====&lt;br /&gt;
Once VTK7 is no longer supported, the old way for disabling python wrapping is no longer needed. According to my tests (Csaba), wrapping works fine in all of those cases, so the new way (#ifndef __VTK_WRAP__) is not needed either.&lt;br /&gt;
&lt;br /&gt;
===Slicer 5.2: Backward incompatible changes===&lt;br /&gt;
&lt;br /&gt;
====Build System Simplification====&lt;br /&gt;
&lt;br /&gt;
*Pick the most recent reasonable CMake version and remove any complexities in the build system are only there to work around limitations of old CMake versions.&lt;br /&gt;
&lt;br /&gt;
*Consider any ways to streamline/simplify the configure and build process, even it if may require changing extensions.&lt;br /&gt;
&lt;br /&gt;
*Look for ways to minimize the effect of long directory path-related build issues.  Currently on mac and windows we are pushing the limit of path length unless very short paths are used (e.g. /s5 or d:\s5).  Reorganizing the build tree might give us more headroom.&lt;br /&gt;
&lt;br /&gt;
====Remove remote data support from MRML====&lt;br /&gt;
&lt;br /&gt;
MRML theoretically supports downloading files through http, but this feature has not seen much use. This will not likely to change in the future because there is a wide range of data access and authentication protocols, which would not be practical at MRML level.&lt;br /&gt;
&lt;br /&gt;
It would be better to remove remote data support from MRML to simplify data storage. We can keep useful utility classes, such as cache manager for keeping track of local temporary files (downloaded using SampleData or other modules that download significant amount of temporary data).&lt;br /&gt;
&lt;br /&gt;
See also https://discourse.slicer.org/t/improving-testing-data-management-for-self-test/5014/4.&lt;br /&gt;
&lt;br /&gt;
====Improve layout manager====&lt;br /&gt;
&lt;br /&gt;
*Support multiple displays: Currently, it is very hard to leverage multiple displays (need to stretch the Slicer window over multiple screens and align splitter manually to the screen boundary). Allow defining single-display and multi-display layouts. Single-display layouts could be selected for each display independently, while multi-monitor layouts would set views on several displays at once. Keeping a single layout manager (and enhance it with to allow creation of multiple widgets) would make it easier to maintain backward compatibility for existing modules.&lt;br /&gt;
*View layout IDs: View layout IDs are currently integer values, which makes it difficult to ensure that modules always choose unique IDs. We should switch to using string IDs. String IDs can may be prefixed with modulename+&amp;quot;.&amp;quot; as we do it for singleton tags and node attributes. We may remain somewhat backward compatible by having SetLayoutID(int) method that maps known layout integer IDs to the new string IDs. See discussion here: https://github.com/Slicer/Slicer/pull/1061#discussion_r241825827&lt;br /&gt;
&lt;br /&gt;
====SceneViews====&lt;br /&gt;
&lt;br /&gt;
The scene views feature does not work well for a long time now, and there is no consensus about what should be the scope it supports.&lt;br /&gt;
&lt;br /&gt;
Suggestion:&lt;br /&gt;
&lt;br /&gt;
*Do not save the state of all nodes: Support only display, view and hierarchy nodes.&lt;br /&gt;
*Make SceneViews as stable as possible for these cases and remove support for data notes etc.&lt;br /&gt;
*If a node is removed, update associated scene views&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
*2018-12-13: Jc: Following discussion with Ron, we should keep the SceneView functionality. All data should be associated with the &amp;quot;master&amp;quot; view, and scene view should be different combination of viewing parameters (layout, camera, visibility, etc ...). A mrb to consider for testing is the [http://slicer.kitware.com/midas3/slicerdatastore/view?itemId=126553&amp;amp;layout=layout LungSegments_scene.mrb]&lt;br /&gt;
*Another suggestion from Sonia is that SceneViews could be read-only for certain classes of nodes.  It's not clear how that would be implemented, but it could address the instability problems while enabling the use of SceneViews for training.&lt;br /&gt;
&lt;br /&gt;
====Undo/Redo====&lt;br /&gt;
Similarly to SceneViews, it is a great feature but in time it started breaking.&lt;br /&gt;
Need to decide if we want to keep it, and if yes fix it.&lt;br /&gt;
&lt;br /&gt;
Potential fix (currently being tested by Kyle Sunderland and Andras Lasso): Add an &amp;quot;undo enabled&amp;quot; flag to vtkMRMLNode, disable it by default, only enable it for nodes that undo/redo has tested to work correctly. Preliminary tests show that the feature largely works, but there are complications with undo/redo of node add/remove actions and node references.&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
*2018-12-13: Jc: Following discussion with Ron, would be nice to also have undo/redo for camera settings, field of view, etc ... within a given view. It is easy to inadvertently modify settings ... (e.g when trying to pan using a trackpad with shift+left click but inadvertently using only left click)&lt;br /&gt;
&lt;br /&gt;
====Removal of Charts based infrastructure====&lt;br /&gt;
&lt;br /&gt;
With Slicer 5.0, the idea is to remove the [[Documentation/Nightly/Developers/Charts|Charts]] infrastructure based on jqPlot, and only keep&lt;br /&gt;
the [[Documentation/Nightly/Developers/Plots|Plots]] infrastructure based on VTK Charts.&lt;br /&gt;
&lt;br /&gt;
Ron's request: enable anti-aliasing (MSAA or FXAA) and use less subtle default colors (https://www.slicer.org/wiki/Slicer4:2012_GenericChartColors) to improve appearance.&lt;br /&gt;
&lt;br /&gt;
==Additional proposed changes to be discussed==&lt;br /&gt;
&lt;br /&gt;
*Bundle IPython package in Slicer installer - Slicer Jupyter extension has been added, do we need more?&lt;br /&gt;
**Do we want history across sessions?&lt;br /&gt;
**Quick access to script repository&lt;br /&gt;
*[https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Install using brew]&lt;br /&gt;
*Add opt-in collection of usage statistics for various features (e.g. could be triggered when a module is entered).&lt;br /&gt;
*Enable geometry correction by default (e.g. gantry tilt as [https://discourse.slicer.org/t/actual-size-of-stl-models/5005/21 discussed here]).&lt;br /&gt;
*Remove legacy 1.0 pydicom and only bundle latest (see https://pydicom.github.io/pydicom/stable/transition_to_pydicom1.html#).  Import name changed from 'dicom' to 'pydicom' (See also: https://github.com/Slicer/Slicer/pull/1231)&lt;br /&gt;
*Remove DICOM Networking (DIMSE) code https://discourse.slicer.org/t/dicom-retrieve-on-windows-10-there-is-no-service-listening-dicom-communications-no-telnet-connection-to-ports&lt;br /&gt;
*Update the logo along [https://discourse.slicer.org/t/slicer-module-panel-icon-in-dark-mode/8353/3 as discussed here].&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=63155</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=63155"/>
		<updated>2020-04-02T15:35:08Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Show a context menu when a markup point is clicked in a slice or 3D view */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=  &lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the[[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
&lt;br /&gt;
*[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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
*[https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
&lt;br /&gt;
*Capture the full Slicer screen and save it into a file&lt;br /&gt;
&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
&lt;br /&gt;
*Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
*Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
&lt;br /&gt;
*How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loadedVolumeNode = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Automatically load volumes that are copied into a folder==&lt;br /&gt;
&lt;br /&gt;
This example shows how to implement a simple background task by using a timer. The background task is to check for any new volume files in folder and if there is any then automatically load it.&lt;br /&gt;
&lt;br /&gt;
There are more efficient methods for file system monitoring or exchanging image data in real-time (for example, using OpenIGTLink), the example below is just for demonstration purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
incomingVolumeFolder = &amp;quot;c:/tmp/incoming&amp;quot;&lt;br /&gt;
incomingVolumesProcessed = []&lt;br /&gt;
&lt;br /&gt;
def checkForNewVolumes():&lt;br /&gt;
  # Check if there is a new file in the &lt;br /&gt;
  from os import listdir&lt;br /&gt;
  from os.path import isfile, join&lt;br /&gt;
  for f in listdir(incomingVolumeFolder):&lt;br /&gt;
    if f in incomingVolumesProcessed:&lt;br /&gt;
      # this is an incoming file, it was already there&lt;br /&gt;
      continue&lt;br /&gt;
    filePath = join(incomingVolumeFolder, f)&lt;br /&gt;
    if not isfile(filePath):&lt;br /&gt;
      # ignore directories&lt;br /&gt;
      continue&lt;br /&gt;
    logging.info(&amp;quot;Loading new file: &amp;quot;+f)&lt;br /&gt;
    incomingVolumesProcessed.append(f)&lt;br /&gt;
    slicer.util.loadVolume(filePath)&lt;br /&gt;
  # Check again in 3000ms&lt;br /&gt;
  qt.QTimer.singleShot(3000, checkForNewVolumes)&lt;br /&gt;
&lt;br /&gt;
# Start monitoring&lt;br /&gt;
checkForNewVolumes()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
===How to load DICOM files into the scene from a folder===&lt;br /&gt;
&lt;br /&gt;
This code loads all DICOM objects into the scene from a file folder. All the registered plugins are evaluated and the one with the highest confidence will be used to load the data. Files are imported into a temporary DICOM database, so the current Slicer DICOM database is not impacted.&lt;br /&gt;
&lt;br /&gt;
  dicomDataDir = &amp;quot;c:/my/folder/with/dicom-files&amp;quot;  # input folder with DICOM files&lt;br /&gt;
  loadedNodeIDs = []  # this list will contain the list of all loaded node IDs&lt;br /&gt;
  &lt;br /&gt;
  from DICOMLib import DICOMUtils&lt;br /&gt;
  with DICOMUtils.TemporaryDICOMDatabase() as db:&lt;br /&gt;
    DICOMUtils.importDicom(dicomDataDir, db)&lt;br /&gt;
    patientUIDs = db.patients()&lt;br /&gt;
    for patientUID in patientUIDs:&lt;br /&gt;
      loadedNodeIDs.extend(DICOMUtils.loadPatientByUID(patientUID))&lt;br /&gt;
&lt;br /&gt;
===How to access top level tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # Note, fileValue accesses the database of cached top level tags&lt;br /&gt;
  # (nested tags are not included)&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
===How to access DICOM tags nested in a sequence===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # use pydicom to access the full header, which requires&lt;br /&gt;
  # re-reading the dataset instead of using the database cache&lt;br /&gt;
  import pydicom&lt;br /&gt;
  pydicom.dcmread(fileList[0])&lt;br /&gt;
  ds.CTExposureSequence[0].ExposureModulationType&lt;br /&gt;
&lt;br /&gt;
===How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
===How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
===How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
===How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm'); slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
===Export a volume to DICOM file format===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Customize table columns in DICOM browser===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database() # Need to go this way, do not use slicer.dicomDatabase for this&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
&lt;br /&gt;
*How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
for viewNode in viewNodes:&lt;br /&gt;
  viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
&lt;br /&gt;
*How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two slice planes==&lt;br /&gt;
&lt;br /&gt;
Measure angle between red and yellow slice nodes. Whenever any of the slice nodes are moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeIds = ['vtkMRMLSliceNodeRed', 'vtkMRMLSliceNodeYellow']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    sliceNormalVector = []&lt;br /&gt;
    for sliceNodeId in sliceNodeIds:&lt;br /&gt;
        sliceToRAS = slicer.mrmlScene.GetNodeByID(sliceNodeId).GetSliceToRAS()&lt;br /&gt;
        sliceNormalVector.append([sliceToRAS.GetElement(0,2), sliceToRAS.GetElement(1,2), sliceToRAS.GetElement(2,2)])&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(sliceNormalVector[0], sliceNormalVector[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between slice planes = {0:0.3f}'.format(angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe slice node changes&lt;br /&gt;
for sliceNodeId in sliceNodeIds:&lt;br /&gt;
    slicer.mrmlScene.GetNodeByID(sliceNodeId).AddObserver(vtk.vtkCommand.ModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from a normal vector and position==&lt;br /&gt;
&lt;br /&gt;
This code snippet shows how to display a slice view defined by a normal vector and position in an anatomically sensible way: rotating slice view so that &amp;quot;up&amp;quot; direction (or &amp;quot;right&amp;quot; direction) is towards an anatomical axis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition, defaultViewUpDirection=None, backupViewRightDirection=None):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Set slice pose from the provided plane normal and position. View up direction is determined automatically,&lt;br /&gt;
    to make view up point towards defaultViewUpDirection.&lt;br /&gt;
    :param defaultViewUpDirection Slice view will be spinned in-plane to match point approximately this up direction. Default: patient superior.&lt;br /&gt;
    :param backupViewRightDirection Slice view will be spinned in-plane to match point approximately this right direction&lt;br /&gt;
        if defaultViewUpDirection is too similar to sliceNormal. Default: patient left.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Fix up input directions&lt;br /&gt;
    if defaultViewUpDirection is None:&lt;br /&gt;
        defaultViewUpDirection = [0,0,1]&lt;br /&gt;
    if backupViewRightDirection is None:&lt;br /&gt;
        backupViewRightDirection = [-1,0,0]&lt;br /&gt;
    if sliceNormal[1]&amp;gt;=0:&lt;br /&gt;
        sliceNormalStandardized = sliceNormal&lt;br /&gt;
    else:&lt;br /&gt;
        sliceNormalStandardized = [-sliceNormal[0], -sliceNormal[1], -sliceNormal[2]]&lt;br /&gt;
    # Compute slice axes&lt;br /&gt;
    sliceNormalViewUpAngle = vtk.vtkMath.AngleBetweenVectors(sliceNormalStandardized, defaultViewUpDirection)&lt;br /&gt;
    angleTooSmallThresholdRad = 0.25 # about 15 degrees&lt;br /&gt;
    if sliceNormalViewUpAngle &amp;gt; angleTooSmallThresholdRad and sliceNormalViewUpAngle &amp;lt; vtk.vtkMath.Pi() - angleTooSmallThresholdRad:&lt;br /&gt;
        viewUpDirection = defaultViewUpDirection&lt;br /&gt;
        sliceAxisY = viewUpDirection&lt;br /&gt;
        sliceAxisX = [0, 0, 0]&lt;br /&gt;
        vtk.vtkMath.Cross(sliceAxisY, sliceNormalStandardized, sliceAxisX)&lt;br /&gt;
    else:&lt;br /&gt;
        sliceAxisX = backupViewRightDirection&lt;br /&gt;
    # Set slice axes&lt;br /&gt;
    sliceNode.SetSliceToRASByNTP(sliceNormalStandardized[0], sliceNormalStandardized[1], sliceNormalStandardized[2],&lt;br /&gt;
        sliceAxisX[0], sliceAxisX[1], sliceAxisX[2],&lt;br /&gt;
        slicePosition[0], slicePosition[1], slicePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Example usage:&lt;br /&gt;
sliceNode = getNode('vtkMRMLSliceNodeRed')&lt;br /&gt;
transformNode = getNode('Transform_3')&lt;br /&gt;
transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
transformNode.GetMatrixTransformToParent(transformMatrix)&lt;br /&gt;
sliceNormal = [transformMatrix.GetElement(0,2), transformMatrix.GetElement(1,2), transformMatrix.GetElement(2,2)]&lt;br /&gt;
slicePosition = [transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)]&lt;br /&gt;
setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Switching to markup fiducial placement mode==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change markup fiducial display properties==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get a notification if a markup point position is modified==&lt;br /&gt;
&lt;br /&gt;
Event management of Slicer-4.11 version is still subject to change. The example below shows how point manipulation can be observed now.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupChanged(caller,event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    if movingMarkupIndex &amp;gt;= 0:&lt;br /&gt;
        pos = [0,0,0]&lt;br /&gt;
        markupsNode.GetNthFiducialPosition(movingMarkupIndex, pos)&lt;br /&gt;
        isPreview = markupsNode.GetNthControlPointPositionStatus(movingMarkupIndex) == slicer.vtkMRMLMarkupsNode.PositionPreview&lt;br /&gt;
        if isPreview:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} is previewed at {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
        else:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} was moved {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
    else:&lt;br /&gt;
        logging.info(&amp;quot;Points modified: slice view = {0}&amp;quot;.format(sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupStartInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()    &lt;br /&gt;
    logging.info(&amp;quot;Start interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupEndInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    logging.info(&amp;quot;End interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, onMarkupChanged)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointStartInteractionEvent, onMarkupStartInteraction)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointEndInteractionEvent, onMarkupEndInteraction)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get a notification if a transform is modified==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate a node around a specified point==&lt;br /&gt;
&lt;br /&gt;
Set up the scene:&lt;br /&gt;
&lt;br /&gt;
*Add a markup fiducial node (centerOfRotationMarkupsNode) with a single point to specify center of rotation.&lt;br /&gt;
*Add a rotation transform (rotationTransformNode) that will be edited in Transforms module to specify rotation angles.&lt;br /&gt;
*Add a transform (finalTransformNode) and apply it (not harden) to those nodes (images, models, etc.) that you want to rotate around the center of rotation point.&lt;br /&gt;
&lt;br /&gt;
Then run the script below, go to Transforms module, select rotationTransformNode, and move rotation sliders.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# This markups fiducial node specifies the center of rotation&lt;br /&gt;
centerOfRotationMarkupsNode = getNode('F')&lt;br /&gt;
# This transform can be  edited in Transforms module&lt;br /&gt;
rotationTransformNode = getNode('LinearTransform_3')&lt;br /&gt;
# This transform has to be applied to the image, model, etc.&lt;br /&gt;
finalTransformNode = getNode('LinearTransform_4')&lt;br /&gt;
&lt;br /&gt;
def updateFinalTransform(unusedArg1=None, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
    rotationMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
    rotationTransformNode.GetMatrixTransformToParent(rotationMatrix)&lt;br /&gt;
    rotationCenterPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
    centerOfRotationMarkupsNode.GetNthControlPointPositionWorld(0, rotationCenterPointCoord)&lt;br /&gt;
    finalTransform = vtk.vtkTransform()&lt;br /&gt;
    finalTransform.Translate(rotationCenterPointCoord)&lt;br /&gt;
    finalTransform.Concatenate(rotationMatrix)&lt;br /&gt;
    finalTransform.Translate(-rotationCenterPointCoord[0], -rotationCenterPointCoord[1], -rotationCenterPointCoord[2])&lt;br /&gt;
    finalTransformNode.SetAndObserveMatrixTransformToParent(finalTransform.GetMatrix())&lt;br /&gt;
&lt;br /&gt;
# Manual initial update&lt;br /&gt;
updateFinalTransform()&lt;br /&gt;
&lt;br /&gt;
# Automatic update when point is moved or transform is modified&lt;br /&gt;
rotationTransformNodeObserver = rotationTransformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, updateFinalTransform)&lt;br /&gt;
centerOfRotationMarkupsNodeObserver = centerOfRotationMarkupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, updateFinalTransform)&lt;br /&gt;
&lt;br /&gt;
# Execute these lines to stop automatic updates:&lt;br /&gt;
# rotationTransformNode.RemoveObserver(rotationTransformNodeObserver)&lt;br /&gt;
# centerOfRotationMarkupsNode.RemoveObserver(centerOfRotationMarkupsNodeObserver)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate a node around a specified line==&lt;br /&gt;
&lt;br /&gt;
Set up the scene:&lt;br /&gt;
&lt;br /&gt;
*Add a markup line node (rotationAxisMarkupsNode) with 2 points to specify rotation axis.&lt;br /&gt;
*Add a rotation transform (rotationTransformNode) that will be edited in Transforms module to specify rotation angle.&lt;br /&gt;
*Add a transform (finalTransformNode) and apply it (not harden) to those nodes (images, models, etc.) that you want to rotate around the line.&lt;br /&gt;
&lt;br /&gt;
Then run the script below, go to Transforms module, select rotationTransformNode, and move Edit / Rotation / IS slider.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# This markups fiducial node specifies the center of rotation&lt;br /&gt;
rotationAxisMarkupsNode = getNode('L')&lt;br /&gt;
# This transform can be edited in Transforms module (Edit / Rotation / IS slider)&lt;br /&gt;
rotationTransformNode = getNode('LinearTransform_3')&lt;br /&gt;
# This transform has to be applied to the image, model, etc.&lt;br /&gt;
finalTransformNode = getNode('LinearTransform_4')&lt;br /&gt;
&lt;br /&gt;
def updateFinalTransform(unusedArg1=None, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
    import numpy as np&lt;br /&gt;
    rotationAxisPoint1_World = np.zeros(3)&lt;br /&gt;
    rotationAxisMarkupsNode.GetNthControlPointPositionWorld(0, rotationAxisPoint1_World)&lt;br /&gt;
    rotationAxisPoint2_World = np.zeros(3)&lt;br /&gt;
    rotationAxisMarkupsNode.GetNthControlPointPositionWorld(1, rotationAxisPoint2_World)&lt;br /&gt;
    axisDirectionZ_World = rotationAxisPoint2_World-rotationAxisPoint1_World&lt;br /&gt;
    axisDirectionZ_World = axisDirectionZ_World/np.linalg.norm(axisDirectionZ_World)&lt;br /&gt;
    # Get transformation between world coordinate system and rotation axis aligne coordinate system&lt;br /&gt;
    worldToRotationAxisTransform = vtk.vtkMatrix4x4()&lt;br /&gt;
    p=vtk.vtkPlaneSource()&lt;br /&gt;
    p.SetNormal(axisDirectionZ_World)&lt;br /&gt;
    axisOrigin = np.array(p.GetOrigin())&lt;br /&gt;
    axisDirectionX_World = np.array(p.GetPoint1())-axisOrigin&lt;br /&gt;
    axisDirectionY_World = np.array(p.GetPoint2())-axisOrigin&lt;br /&gt;
    rotationAxisToWorldTransform = np.row_stack((np.column_stack((axisDirectionX_World, axisDirectionY_World, axisDirectionZ_World, rotationAxisPoint1_World)), (0, 0, 0, 1)))&lt;br /&gt;
    rotationAxisToWorldTransformMatrix = slicer.util.vtkMatrixFromArray(rotationAxisToWorldTransform)&lt;br /&gt;
    worldToRotationAxisTransformMatrix = slicer.util.vtkMatrixFromArray(np.linalg.inv(rotationAxisToWorldTransform))&lt;br /&gt;
    # Compute transformation chain&lt;br /&gt;
    rotationMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
    rotationTransformNode.GetMatrixTransformToParent(rotationMatrix)&lt;br /&gt;
    finalTransform = vtk.vtkTransform()&lt;br /&gt;
    finalTransform.Concatenate(rotationAxisToWorldTransformMatrix)&lt;br /&gt;
    finalTransform.Concatenate(rotationMatrix)&lt;br /&gt;
    finalTransform.Concatenate(worldToRotationAxisTransformMatrix)&lt;br /&gt;
    finalTransformNode.SetAndObserveMatrixTransformToParent(finalTransform.GetMatrix())&lt;br /&gt;
&lt;br /&gt;
# Manual initial update&lt;br /&gt;
updateFinalTransform()&lt;br /&gt;
&lt;br /&gt;
# Automatic update when point is moved or transform is modified&lt;br /&gt;
rotationTransformNodeObserver = rotationTransformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, updateFinalTransform)&lt;br /&gt;
rotationAxisMarkupsNodeObserver = rotationAxisMarkupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, updateFinalTransform)&lt;br /&gt;
&lt;br /&gt;
# Execute these lines to stop automatic updates:&lt;br /&gt;
# rotationTransformNode.RemoveObserver(rotationTransformNodeObserver)&lt;br /&gt;
# rotationAxisMarkupsNode.RemoveObserver(rotationAxisMarkupsNodeObserver)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a context menu when a markup point is clicked in a slice or 3D view==&lt;br /&gt;
&lt;br /&gt;
Subject hierarchy plugins can offer actions in the view context menu when right-clicking objects that support such picking (such as Markups fiducials). A comprehensive [https://github.com/Slicer/Slicer/blob/master/Modules/Loadable/Annotations/SubjectHierarchyPlugins/AnnotationsSubjectHierarchyPlugin.py subject hierarchy plugin example] is for the Annotations module.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  def viewContextMenuActions(self):&lt;br /&gt;
    return [self.doSomething]&lt;br /&gt;
&lt;br /&gt;
  def showViewContextMenuActionsForItem(self, itemID, eventData):&lt;br /&gt;
    if not itemID:&lt;br /&gt;
      logging.error('Invalid item for view context menu ' + str(itemID))&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    pluginHandlerSingleton = slicer.qSlicerSubjectHierarchyPluginHandler.instance()&lt;br /&gt;
    shNode = pluginHandlerSingleton.subjectHierarchyNode()&lt;br /&gt;
    if shNode is None:&lt;br /&gt;
      logging.error('Failed to access subject hierarchy node')&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    associatedNode = shNode.GetItemDataNode(itemID)&lt;br /&gt;
    if not associatedNode or not associatedNode.IsA(&amp;quot;vtkMRMLMarkupsNode&amp;quot;):&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    self.viewMenuEventData = eventData&lt;br /&gt;
    self.viewMenuEventData['NodeID'] = associatedNode.GetID()&lt;br /&gt;
&lt;br /&gt;
  def onDoSomething(self):&lt;br /&gt;
    nodeID = self.viewMenuEventData['NodeID']&lt;br /&gt;
    markupsNode = slicer.mrmlScene.GetNodeByID(nodeID)&lt;br /&gt;
    if markupsNode is None or not markupsNode.IsA(&amp;quot;vtkMRMLMarkupsNode&amp;quot;):&lt;br /&gt;
      logging.error('Failed to get fiducial markups node by ID ' + str(nodeID))&lt;br /&gt;
      return&lt;br /&gt;
&lt;br /&gt;
    componentIndex = self.viewMenuEventData['ComponentIndex']&lt;br /&gt;
    markupID = markupsNode.GetNthMarkupID(componentIndex)&lt;br /&gt;
    &lt;br /&gt;
    # Do something with the clicked fiducial&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Write markup positions to JSON file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Write annotation ROI to JSON file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a simple surface mesh as a model node==&lt;br /&gt;
&lt;br /&gt;
This example shows how to display a simple surface mesh (a box, created by a VTK source filter) as a model node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create and set up polydata source&lt;br /&gt;
box = vtk.vtkCubeSource()&lt;br /&gt;
box.SetXLength(30)&lt;br /&gt;
box.SetYLength(20)&lt;br /&gt;
box.SetZLength(15)&lt;br /&gt;
box.SetCenter(10,20,5)&lt;br /&gt;
&lt;br /&gt;
# Create a model node that displays output of the source&lt;br /&gt;
boxNode = slicer.modules.models.logic().AddModel(box.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Adjust display properties&lt;br /&gt;
boxNode.GetDisplayNode().SetColor(1,0,0)&lt;br /&gt;
boxNode.GetDisplayNode().SetOpacity(0.8)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure distance of points from surface==&lt;br /&gt;
&lt;br /&gt;
This example computes closest distance of points (markups fiducial 'F') from a surface (model node 'mymodel') and writes results into a table.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
modelNode = getNode('mymodel')&lt;br /&gt;
&lt;br /&gt;
# Transform model polydata to world coordinate system&lt;br /&gt;
if modelNode.GetParentTransformNode():&lt;br /&gt;
    transformModelToWorld = vtk.vtkGeneralTransform()&lt;br /&gt;
    slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(modelNode.GetParentTransformNode(), None, transformModelToWorld)&lt;br /&gt;
    polyTransformToWorld = vtk.vtkTransformPolyDataFilter()&lt;br /&gt;
    polyTransformToWorld.SetTransform(transformModelToWorld)&lt;br /&gt;
    polyTransformToWorld.SetInputData(modelNode.GetPolyData())&lt;br /&gt;
    polyTransformToWorld.Update()&lt;br /&gt;
    surface_World = polyTransformToWorld.GetOutput()&lt;br /&gt;
else:&lt;br /&gt;
    surface_World = modelNode.GetPolyData()&lt;br /&gt;
&lt;br /&gt;
# Create arrays to store results&lt;br /&gt;
indexCol = vtk.vtkIntArray()&lt;br /&gt;
indexCol.SetName(&amp;quot;Index&amp;quot;)&lt;br /&gt;
labelCol = vtk.vtkStringArray()&lt;br /&gt;
labelCol.SetName(&amp;quot;Name&amp;quot;)&lt;br /&gt;
distanceCol = vtk.vtkDoubleArray()&lt;br /&gt;
distanceCol.SetName(&amp;quot;Distance&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
distanceFilter = vtk.vtkImplicitPolyDataDistance()&lt;br /&gt;
distanceFilter.SetInput(surface_World);&lt;br /&gt;
nOfFiduciallPoints = markupsNode.GetNumberOfFiducials()&lt;br /&gt;
for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    point_World = [0,0,0]&lt;br /&gt;
    markupsNode.GetNthControlPointPositionWorld(i, point_World)&lt;br /&gt;
    closestPointOnSurface_World = [0,0,0]&lt;br /&gt;
    closestPointDistance = distanceFilter.EvaluateFunctionAndGetClosestPoint(point_World, closestPointOnSurface_World)&lt;br /&gt;
    indexCol.InsertNextValue(i)&lt;br /&gt;
    labelCol.InsertNextValue(markupsNode.GetNthControlPointLabel(i))&lt;br /&gt;
    distanceCol.InsertNextValue(closestPointDistance)&lt;br /&gt;
&lt;br /&gt;
# Create a table from result arrays&lt;br /&gt;
resultTableNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;, &amp;quot;Points from surface distance&amp;quot;)&lt;br /&gt;
resultTableNode.AddColumn(indexCol)&lt;br /&gt;
resultTableNode.AddColumn(labelCol)&lt;br /&gt;
resultTableNode.AddColumn(distanceCol)&lt;br /&gt;
&lt;br /&gt;
# Show table in view layout&lt;br /&gt;
slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpTableView)&lt;br /&gt;
slicer.app.applicationLogic().GetSelectionNode().SetReferenceActiveTableID(resultTableNode.GetID())&lt;br /&gt;
slicer.app.applicationLogic().PropagateTableSelection()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Add a texture mapped plane to the scene as a model==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create model node&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
planeSource.SetOrigin(-50.0, -50.0, 0.0)&lt;br /&gt;
planeSource.SetPoint1(50.0, -50.0, 0.0)&lt;br /&gt;
planeSource.SetPoint2(-50.0, 50.0, 0.0)&lt;br /&gt;
model = slicer.modules.models.logic().AddModel(planeSource.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Tune display properties&lt;br /&gt;
modelDisplay = model.GetDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
&lt;br /&gt;
# Add texture (just use image of an ellipsoid)&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
modelDisplay.SetTextureImageDataConnection(e.GetOutputPort())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get scalar values at surface of a model==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Select cells of a model using markups fiducial points==&lt;br /&gt;
&lt;br /&gt;
The following script selects cells of a model node that are closest to positions of markups fiducial points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get input nodes&lt;br /&gt;
modelNode = slicer.util.getNode('Segment_1') # select cells in this model&lt;br /&gt;
markupsNode = slicer.util.getNode('F') # points will be selected at positions specified by this markups fiducial node&lt;br /&gt;
&lt;br /&gt;
# Create scalar array that will store selection state&lt;br /&gt;
cellScalars = modelNode.GetMesh().GetCellData()&lt;br /&gt;
selectionArray = cellScalars.GetArray('selection')&lt;br /&gt;
if not selectionArray:&lt;br /&gt;
    selectionArray = vtk.vtkIntArray()&lt;br /&gt;
    selectionArray.SetName('selection')&lt;br /&gt;
    selectionArray.SetNumberOfValues(modelNode.GetMesh().GetNumberOfCells())&lt;br /&gt;
    selectionArray.Fill(0)&lt;br /&gt;
    cellScalars.AddArray(selectionArray)&lt;br /&gt;
&lt;br /&gt;
# Set up coloring by selection array&lt;br /&gt;
modelNode.GetDisplayNode().SetActiveScalar(&amp;quot;selection&amp;quot;, vtk.vtkAssignAttribute.CELL_DATA)&lt;br /&gt;
modelNode.GetDisplayNode().SetAndObserveColorNodeID(&amp;quot;vtkMRMLColorTableNodeWarm1&amp;quot;)&lt;br /&gt;
modelNode.GetDisplayNode().SetScalarVisibility(True)&lt;br /&gt;
&lt;br /&gt;
# Initialize cell locator&lt;br /&gt;
cell = vtk.vtkCellLocator()&lt;br /&gt;
cell.SetDataSet(modelNode.GetMesh())&lt;br /&gt;
cell.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onPointsModified(observer=None, eventid=None):&lt;br /&gt;
    global markupsNode, selectionArray&lt;br /&gt;
    selectionArray.Fill(0) # set all cells to non-selected by default&lt;br /&gt;
    markupPoints = slicer.util.arrayFromMarkupsControlPoints(markupsNode)&lt;br /&gt;
    closestPoint = [0.0, 0.0, 0.0]&lt;br /&gt;
    cellObj = vtk.vtkGenericCell()&lt;br /&gt;
    cellId = vtk.mutable(0)&lt;br /&gt;
    subId = vtk.mutable(0)&lt;br /&gt;
    dist2 = vtk.mutable(0.0)&lt;br /&gt;
    for markupPoint in markupPoints:&lt;br /&gt;
        cell.FindClosestPoint(markupPoint, closestPoint, cellObj, cellId, subId, dist2)&lt;br /&gt;
        closestCell = cellId.get()&lt;br /&gt;
        if closestCell &amp;gt;=0:&lt;br /&gt;
            selectionArray.SetValue(closestCell, 100) # set selected cell's scalar value to non-zero&lt;br /&gt;
    selectionArray.Modified()&lt;br /&gt;
&lt;br /&gt;
# Initial update&lt;br /&gt;
onPointsModified()&lt;br /&gt;
# Automatic update each time when a markup point is modified&lt;br /&gt;
markupsNodeObserverTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsFiducialNode.PointModifiedEvent, onPointsModified)&lt;br /&gt;
&lt;br /&gt;
# To stop updating selection, run this:&lt;br /&gt;
# markupsNode.RemoveObserver(markupsNodeObserverTag)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export entire scene as VRML==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export model to Blender, including color by scalar==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export a tract (FiberBundle) to Blender, including color==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Iterate over tract (FiberBundle) streamline points==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Clone a node==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Clone a volume==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create a new volume==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
imageData.GetPointData().GetScalars().Fill(fillVoxelValue)&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get value of a volume at specific voxel coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel value of &amp;quot;volumeNode&amp;quot; at &amp;quot;ijk&amp;quot; volume voxel coordinates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
ijk = [20,40,30]  # volume voxel coordinates&lt;br /&gt;
&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)  # get voxels as a numpy array&lt;br /&gt;
voxelValue = voxels[ijk[2], ijk[1], ijk[0]]  # note that numpy array index order is kji (not ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Modify voxels in a volume==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get volume voxel coordinates from markup fiducial RAS coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get markup fiducial RAS coordinates from volume voxel coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get the values of all voxels for a label value==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Access values in a DTI tensor volume==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change window/level (brightness/contrast) or colormap of a volume==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Make mouse left-click and drag on the image adjust window/level==&lt;br /&gt;
&lt;br /&gt;
In older Slicer versions, by default, left-click and drag in a slice view adjusted window/level of the displayed image. Window/level adjustment is now a new mouse mode that can be activated by clicking on its toolbar button or running this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.applicationLogic().GetInteractionNode().SetCurrentInteractionMode(slicer.vtkMRMLInteractionNode.AdjustWindowLevel)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create custom color table==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manipulate a Slice View==&lt;br /&gt;
&lt;br /&gt;
===Change slice offset===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Change slice orientation===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Show slice views in 3D window===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Reset field of view to show background volume maximized===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rotate slice views to volume plane===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Iterate over current visible slice views, and set foreground and background images===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     compositeNode = layoutManager.sliceWidget(sliceViewName).sliceLogic().GetSliceCompositeNode()&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a volume in slice views==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change opacity of foreground volume in slice views==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Fit slice plane to markup fiducials==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.zeros(3)&lt;br /&gt;
p2 = np.zeros(3)&lt;br /&gt;
p3 = np.zeros(3)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0.0, 0.0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save a series of images from a Slice View==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rasterize a model and save it to a series of image files==&lt;br /&gt;
&lt;br /&gt;
This example shows how to generate a stack of image files from an STL file:&lt;br /&gt;
&lt;br /&gt;
 inputModelFile = &amp;quot;/some/input/folder/SomeShape.stl&amp;quot;&lt;br /&gt;
 outputDir = &amp;quot;/some/output/folder&amp;quot;&lt;br /&gt;
 outputVolumeLabelValue = 100&lt;br /&gt;
 outputVolumeSpacingMm = [0.5, 0.5, 0.5]&lt;br /&gt;
 outputVolumeMarginMm = [10.0, 10.0, 10.0]&lt;br /&gt;
 &lt;br /&gt;
 # Read model&lt;br /&gt;
 inputModel = slicer.util.loadModel(inputModelFile)&lt;br /&gt;
 &lt;br /&gt;
 # Determine output volume geometry and create a corresponding reference volume&lt;br /&gt;
 import math&lt;br /&gt;
 import numpy as np&lt;br /&gt;
 bounds = np.zeros(6)&lt;br /&gt;
 inputModel.GetBounds(bounds)&lt;br /&gt;
 imageData = vtk.vtkImageData()&lt;br /&gt;
 imageSize = [ int((bounds[axis*2+1]-bounds[axis*2]+outputVolumeMarginMm[axis]*2.0)/outputVolumeSpacingMm[axis]) for axis in range(3) ]&lt;br /&gt;
 imageOrigin = [ bounds[axis*2]-outputVolumeMarginMm[axis] for axis in range(3) ]&lt;br /&gt;
 imageData.SetDimensions(imageSize)&lt;br /&gt;
 imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1)&lt;br /&gt;
 imageData.GetPointData().GetScalars().Fill(0)&lt;br /&gt;
 referenceVolumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
 referenceVolumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
 referenceVolumeNode.SetSpacing(outputVolumeSpacingMm)&lt;br /&gt;
 referenceVolumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
 referenceVolumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
 &lt;br /&gt;
 # Convert model to labelmap&lt;br /&gt;
 seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
 seg.SetReferenceImageGeometryParameterFromVolumeNode(referenceVolumeNode)&lt;br /&gt;
 slicer.modules.segmentations.logic().ImportModelToSegmentationNode(inputModel, seg)&lt;br /&gt;
 seg.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
 outputLabelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
 slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(seg, outputLabelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
 outputLabelmapVolumeArray = (slicer.util.arrayFromVolume(outputLabelmapVolumeNode) * outputVolumeLabelValue).astype('int8')&lt;br /&gt;
 &lt;br /&gt;
 # Write labelmap volume to series of TIFF files&lt;br /&gt;
 pip_install(&amp;quot;imageio&amp;quot;)&lt;br /&gt;
 import imageio&lt;br /&gt;
 for i in range(len(outputLabelmapVolumeArray)):&lt;br /&gt;
     imageio.imwrite(f'{outputDir}/image_{i:03}.tiff', outputLabelmapVolumeArray[i])&lt;br /&gt;
&lt;br /&gt;
==Save the scene into a new directory==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save the scene into a single MRB file==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save a node to file==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Center the 3D View on the Scene==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Display text in a 3D view or slice view==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide slice view annotations (DataProbe)==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Turning off interpolation==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Customize viewer layout==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;layout type=&amp;quot;vertical&amp;quot; split=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLSliceNode&amp;quot; singletontag=&amp;quot;Red&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;orientation&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewcolor&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/layout&amp;gt;&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Built-in layout IDs are all below 100, so you can choose any large random number&lt;br /&gt;
# for your custom layout ID.&lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
&lt;br /&gt;
# Switch to the new custom layout &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
You can use this code snippet to add a button to the layout selector toolbar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Add button to layout selector toolbar for this custom layout&lt;br /&gt;
viewToolBar = mainWindow().findChild('QToolBar', 'ViewToolBar')&lt;br /&gt;
layoutMenu = viewToolBar.widgetForAction(viewToolBar.actions()[0]).menu()&lt;br /&gt;
layoutSwitchActionParent = layoutMenu  # use `layoutMenu` to add inside layout list, use `viewToolBar` to add next the standard layout list&lt;br /&gt;
layoutSwitchAction = layoutSwitchActionParent.addAction(&amp;quot;My view&amp;quot;) # add inside layout list&lt;br /&gt;
layoutSwitchAction.setData(layoutId)&lt;br /&gt;
layoutSwitchAction.setIcon(qt.QIcon(':Icons/Go.png'))&lt;br /&gt;
layoutSwitchAction.setToolTip('3D and slice view')&lt;br /&gt;
layoutSwitchAction.connect('triggered()', lambda layoutId = customLayoutId: slicer.app.layoutManager().setLayout(layoutId))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Customize keyboard shortcuts==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's an example for cycling through Segment Editor effects (requested [https://discourse.slicer.org/t/is-there-a-keystroke-to-cycle-through-effects-in-segment-editor/10117/2 on the forum] for the [http://slicermorph.org SlicerMorph] project).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def cycleEffect(delta=1):&lt;br /&gt;
    try:&lt;br /&gt;
        orderedNames = list(slicer.modules.SegmentEditorWidget.editor.effectNameOrder())&lt;br /&gt;
        allNames = slicer.modules.SegmentEditorWidget.editor.availableEffectNames()&lt;br /&gt;
        for name in allNames:&lt;br /&gt;
            try:&lt;br /&gt;
                orderedNames.index(name)&lt;br /&gt;
            except ValueError:&lt;br /&gt;
                orderedNames.append(name)&lt;br /&gt;
        orderedNames.insert(0, None)&lt;br /&gt;
        activeEffect = slicer.modules.SegmentEditorWidget.editor.activeEffect()&lt;br /&gt;
        if activeEffect:&lt;br /&gt;
            activeName = slicer.modules.SegmentEditorWidget.editor.activeEffect().name&lt;br /&gt;
        else:&lt;br /&gt;
            activeName = None&lt;br /&gt;
        newIndex = (orderedNames.index(activeName) + delta) % len(orderedNames)&lt;br /&gt;
        slicer.modules.SegmentEditorWidget.editor.setActiveEffectByName(orderedNames[newIndex])&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        # module not active&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('`', lambda: cycleEffect(-1)),&lt;br /&gt;
    ('~', lambda: cycleEffect(1)),&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Disable certain user interactions in slice views==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change default slice view orientation==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set all slice views linked by default==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set crosshair jump mode to centered by default==&lt;br /&gt;
&lt;br /&gt;
You can change default slice jump mode (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
crosshair=slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLCrosshairNode&amp;quot;)&lt;br /&gt;
crosshair.SetCrosshairBehavior(crosshair.CenteredJumpSlice)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set up custom units in slice view ruler==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in range(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a slice view outside the view layout==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;TS&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
viewNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(layoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
viewWidget.sliceViewName = layoutName&lt;br /&gt;
viewWidget.sliceViewLabel = layoutLabel&lt;br /&gt;
c = viewNode.GetLayoutColor()&lt;br /&gt;
viewWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLSliceNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a 3D view outside the view layout==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;Test3DView&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;T3&amp;quot;&lt;br /&gt;
layoutColor = [1.0, 1.0, 0.0]&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML node&lt;br /&gt;
viewNode = slicer.vtkMRMLViewNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(layoutColor)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLThreeDWidget()&lt;br /&gt;
viewWidget.viewLabel = layoutLabel&lt;br /&gt;
viewWidget.viewColor = qt.QColor.fromRgbF(*layoutColor)&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLViewNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get displayable manager of a certain type for a certain view==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelDisplayableManager = None&lt;br /&gt;
threeDViewWidget = slicer.app.layoutManager().threeDWidget(0)&lt;br /&gt;
managers = vtk.vtkCollection()&lt;br /&gt;
threeDViewWidget.getDisplayableManagers(managers)&lt;br /&gt;
for i in range(managers.GetNumberOfItems()):&lt;br /&gt;
  obj = managers.GetItemAsObject(i)&lt;br /&gt;
  if obj.IsA('vtkMRMLModelDisplayableManager'):&lt;br /&gt;
    modelDisplayableManager = obj&lt;br /&gt;
    break&lt;br /&gt;
if modelDisplayableManager is None:&lt;br /&gt;
  logging.error('Failed to find the model displayable manager')&lt;br /&gt;
  return&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Running an ITK filter in Python using SimpleITK==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
&lt;br /&gt;
*See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
*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&lt;br /&gt;
&lt;br /&gt;
==Get current mouse coordinates in a slice view==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get DataProbe text==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get reformatted image from a slice viewer as numpy array==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print voxels.shape&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Combine multiple volumes into one==&lt;br /&gt;
&lt;br /&gt;
This example combines two volumes into a new one by subtracting one from the other.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
[input1Volume, input2Volume] = SampleData.SampleDataLogic().downloadDentalSurgery()&lt;br /&gt;
&lt;br /&gt;
import slicer.util&lt;br /&gt;
a = slicer.util.arrayFromVolume(input1Volume)&lt;br /&gt;
b = slicer.util.arrayFromVolume(input2Volume)&lt;br /&gt;
&lt;br /&gt;
# 'a' and 'b' are numpy arrays,&lt;br /&gt;
# they can be combined using any numpy array operations&lt;br /&gt;
# to produce the result array 'c'&lt;br /&gt;
c = b-a&lt;br /&gt;
&lt;br /&gt;
volumeNode = slicer.modules.volumes.logic().CloneVolume(input1Volume, &amp;quot;Difference&amp;quot;)&lt;br /&gt;
slicer.util.updateVolumeFromArray(volumeNode, c)&lt;br /&gt;
setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Thick slab reconstruction and maximum/minimum intensity volume projections==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
==Change default file type for nodes (that have never been saved yet)==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
==Change file type for saving for all volumes (with already existing storage nodes)==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Sequences==&lt;br /&gt;
&lt;br /&gt;
===Concatenate all sequences in the scene into a new sequence===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Segmentations==&lt;br /&gt;
&lt;br /&gt;
===Create a segmentation from a labelmap volume and display in 3D===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
===Export labelmap node from segmentation node===&lt;br /&gt;
&lt;br /&gt;
Export smallest possible labelmap:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export labelmap that matches geometry of a chosen reference volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export by pressing Ctrl+Shift+s key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPath = &amp;quot;c:/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def exportLabelmap():&lt;br /&gt;
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLSegmentationNode&amp;quot;)&lt;br /&gt;
    referenceVolumeNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
    labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
    slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
    filepath = outputPath + &amp;quot;/&amp;quot; + referenceVolumeNode.GetName()+&amp;quot;-label.nrrd&amp;quot;&lt;br /&gt;
    slicer.util.saveNode(labelmapVolumeNode, filepath)&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode.GetDisplayNode().GetColorNode())&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
    slicer.util.delayDisplay(&amp;quot;Segmentation saved to &amp;quot;+filepath)&lt;br /&gt;
&lt;br /&gt;
shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
shortcut.setKey(qt.QKeySequence('Ctrl+Shift+s'))&lt;br /&gt;
shortcut.connect( 'activated()', exportLabelmap)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Export model nodes from segmentation node===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode(&amp;quot;Segmentation&amp;quot;)&lt;br /&gt;
shNode = slicer.mrmlScene.GetSubjectHierarchyNode()&lt;br /&gt;
exportFolderItemId = shNode.CreateFolderItem(shNode.GetSceneItemID(), &amp;quot;Segments&amp;quot;)&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModels(segmentationNode, exportFolderItemId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Show a segmentation in 3D===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get a representation of a segment===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = slicer.vtkOrientedImageData()&lt;br /&gt;
segmentationNode.GetBinaryLabelmapRepresentation(segmentID, image)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert all segments using default path and conversion parameters===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert all segments using custom path or conversion parameters===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Re-convert using a modified conversion parameter===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get centroid of a segment in world (RAS) coordinates===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to run segment editor effects from a script===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
*[https://gist.github.com/lassoan/ef30bc27a22a648ead7f82243f5cc7d5 AI-assisted brain tumor segmentation]&lt;br /&gt;
*[https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
*[https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
*[https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
*[https://gist.github.com/lassoan/4d0b94bda52d5b099432e424e03aa2b1 segment cranial cavity automatically in dry bone skull CT]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
==Quantifying segments==&lt;br /&gt;
&lt;br /&gt;
===Get size, position, and orientation of each segment===&lt;br /&gt;
&lt;br /&gt;
This example computes oriented bounding box for each segment and displays them using annotation ROI.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
&lt;br /&gt;
# Compute bounding boxes&lt;br /&gt;
import SegmentStatistics&lt;br /&gt;
segStatLogic = SegmentStatistics.SegmentStatisticsLogic()&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;Segmentation&amp;quot;, segmentationNode.GetID())&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_origin_ras.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_diameter_mm.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_x.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_y.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.getParameterNode().SetParameter(&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_z.enabled&amp;quot;,str(True))&lt;br /&gt;
segStatLogic.computeStatistics()&lt;br /&gt;
stats = segStatLogic.getStatistics()&lt;br /&gt;
&lt;br /&gt;
# Draw ROI for each oriented bounding box&lt;br /&gt;
import numpy as np&lt;br /&gt;
for segmentId in stats['SegmentIDs']:&lt;br /&gt;
    # Get bounding box&lt;br /&gt;
    obb_origin_ras = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_origin_ras&amp;quot;])&lt;br /&gt;
    obb_diameter_mm = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_diameter_mm&amp;quot;])&lt;br /&gt;
    obb_direction_ras_x = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_x&amp;quot;])&lt;br /&gt;
    obb_direction_ras_y = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_y&amp;quot;])&lt;br /&gt;
    obb_direction_ras_z = np.array(stats[segmentId,&amp;quot;LabelmapSegmentStatisticsPlugin.obb_direction_ras_z&amp;quot;])&lt;br /&gt;
    # Create ROI&lt;br /&gt;
    segment = segmentationNode.GetSegmentation().GetSegment(segmentId)&lt;br /&gt;
    roi=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLAnnotationROINode&amp;quot;)&lt;br /&gt;
    roi.SetName(segment.GetName()+' bounding box')&lt;br /&gt;
    roi.SetXYZ(0.0, 0.0, 0.0)&lt;br /&gt;
    roi.SetRadiusXYZ(*(0.5*obb_diameter_mm))&lt;br /&gt;
    # Position and orient ROI using a transform&lt;br /&gt;
    obb_center_ras = obb_origin_ras+0.5*(obb_diameter_mm[0] * obb_direction_ras_x + obb_diameter_mm[1] * obb_direction_ras_y + obb_diameter_mm[2] * obb_direction_ras_z)&lt;br /&gt;
    boundingBoxToRasTransform = np.row_stack((np.column_stack((obb_direction_ras_x, obb_direction_ras_y, obb_direction_ras_z, obb_center_ras)), (0, 0, 0, 1)))&lt;br /&gt;
    boundingBoxToRasTransformMatrix = slicer.util.vtkMatrixFromArray(boundingBoxToRasTransform)&lt;br /&gt;
    transformNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLTransformNode')&lt;br /&gt;
    transformNode.SetAndObserveMatrixTransformToParent(boundingBoxToRasTransformMatrix)&lt;br /&gt;
    roi.SetAndObserveTransformNodeID(transformNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Accessing views, renderers, and cameras==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide view controller bars==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Customize widgets in view controller bars==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceController = slicer.app.layoutManager().sliceWidget(&amp;quot;Red&amp;quot;).sliceController()&lt;br /&gt;
&lt;br /&gt;
# hide what is not needed&lt;br /&gt;
sliceController.pinButton().hide()&lt;br /&gt;
#sliceController.viewLabel().hide()&lt;br /&gt;
sliceController.fitToWindowToolButton().hide()&lt;br /&gt;
sliceController.sliceOffsetSlider().hide()&lt;br /&gt;
&lt;br /&gt;
# add custom widgets&lt;br /&gt;
myButton = qt.QPushButton(&amp;quot;My custom button&amp;quot;)&lt;br /&gt;
sliceController.barLayout().addWidget(b)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change 3D view background color==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNode = slicer.app.layoutManager().threeDWidget(0).mrmlViewNode()&lt;br /&gt;
viewNode.SetBackgroundColor(1,0,0)&lt;br /&gt;
viewNode.SetBackgroundColor2(1,0,0)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide Slicer logo from main window (to increase space)==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.findChild(slicer.util.mainWindow(), 'LogoLabel').visible = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subject hierarchy== &lt;br /&gt;
====Get the pseudo-singleton subject hierarchy node====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.mrmlScene.GetSubjectHierarchyNode()&lt;br /&gt;
&lt;br /&gt;
====Create subject hierarchy item====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
====Get subject hierarchy item====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
====Traverse children of a subject hierarchy item====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in range(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
====Manipulate subject hierarchy item====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data node associated to an item&lt;br /&gt;
  shNode.SetItemDisplayVisibility(itemID, 1)&lt;br /&gt;
  # Set visibility of whole branch&lt;br /&gt;
  # Note: Folder-type items (fodler, subject, study, etc.) create their own display nodes when show/hiding from UI.&lt;br /&gt;
  #       The displayable managers use SH information to determine visibility of an item, so no need to show/hide individual leaf nodes any more.&lt;br /&gt;
  #       Once the folder display node is created, it can be shown hidden simply using shNode.SetItemDisplayVisibility&lt;br /&gt;
  # From python, this is how to trigger creating a folder display node&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler().instance()&lt;br /&gt;
  folderPlugin = pluginHandler.pluginByName('Folder')&lt;br /&gt;
  folderPlugin.setDisplayVisibility(folderItemID, 1)&lt;br /&gt;
&lt;br /&gt;
====Filter items in TreeView or ComboBox====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
===Listen to subject hierarchy item events===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
===Use whitelist to customize view menu===&lt;br /&gt;
When right-clicking certain types of nodes in the 2D/3D views, a subject hierarchy menu pops up. If menu actions need to be removed, a whitelist can be used to specify the ones that should show up.&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler.instance()&lt;br /&gt;
  pluginLogic = pluginHandler.pluginLogic()&lt;br /&gt;
  menuActions = pluginLogic.availableViewMenuActionNames()&lt;br /&gt;
  # Returns ('RenamePointAction', 'DeletePointAction', 'ToggleSelectPointAction', 'EditPropertiesAction')&lt;br /&gt;
  newActions = ['RenamePointAction']&lt;br /&gt;
  pluginLogic.setDisplayedViewMenuActionNames(newActions)&lt;br /&gt;
&lt;br /&gt;
==Plotting==&lt;br /&gt;
&lt;br /&gt;
===Slicer plots displayed in view layout===&lt;br /&gt;
&lt;br /&gt;
Create histogram plot of a volume and show it embedded in the view layout. More information: https://www.slicer.org/wiki/Documentation/Nightly/Developers/Plots&lt;br /&gt;
&lt;br /&gt;
====Using &amp;lt;code&amp;gt;slicer.util.plot&amp;lt;/code&amp;gt; utility function====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
chartNode = slicer.util.plot(histogram, xColumnIndex = 1)&lt;br /&gt;
chartNode.SetYAxisRangeAuto(False)&lt;br /&gt;
chartNode.SetYAxisRange(0, 4e5)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:SlicerPlot.png]]&lt;br /&gt;
&lt;br /&gt;
====Using MRML classes only====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using matplotlib===&lt;br /&gt;
&lt;br /&gt;
Matplotlib may be used from within Slicer, but the default Tk backend locks up and crashes Slicer. However, Matplotlib may still be used through other backends. More details can be found on the [http://matplotlib.sourceforge.net/ MatPlotLib] pages.&lt;br /&gt;
&lt;br /&gt;
====Non-interactive plot====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
&lt;br /&gt;
# Static image view&lt;br /&gt;
pm = qt.QPixmap(&amp;quot;MatplotlibExample.png&amp;quot;)&lt;br /&gt;
imageWidget = qt.QLabel()&lt;br /&gt;
imageWidget.setPixmap(pm)&lt;br /&gt;
imageWidget.setScaledContents(True)&lt;br /&gt;
imageWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:MatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
====Plot in Slicer Jupyter notebook====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
display(filename='MatplotlibExample.png', type=&amp;quot;image/png&amp;quot;, binary=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:JupyterNotebookMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
====Interactive plot using wxWidgets GUI toolkit====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
  import wx&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib wxPython')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Set matplotlib to use WXAgg backend&lt;br /&gt;
import matplotlib&lt;br /&gt;
matplotlib.use('WXAgg')&lt;br /&gt;
&lt;br /&gt;
# Show an interactive plot&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
fig, ax = plt.subplots()&lt;br /&gt;
ax.plot(histogram[1][1:], histogram[0].astype(float))&lt;br /&gt;
ax.grid(True)&lt;br /&gt;
ax.set_ylim((0, 4e5))&lt;br /&gt;
plt.show(block=False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:InteractiveMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==Execute external applications==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
===Run process in default environment===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;br /&gt;
&lt;br /&gt;
==Manage extensions==&lt;br /&gt;
&lt;br /&gt;
===Download and install extension===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensionName = 'SlicerIGT'&lt;br /&gt;
em = slicer.app.extensionsManagerModel()&lt;br /&gt;
if not em.isExtensionInstalled(extensionName):&lt;br /&gt;
    extensionMetaData = em.retrieveExtensionMetadataByName(extensionName)&lt;br /&gt;
    url = em.serverUrl().toString()+'/download/item/'+extensionMetaData['item_id']&lt;br /&gt;
    extensionPackageFilename = slicer.app.temporaryPath+'/'+extensionMetaData['md5']&lt;br /&gt;
    slicer.util.downloadFile(url, extensionPackageFilename)&lt;br /&gt;
    em.installExtension(extensionPackageFilename)&lt;br /&gt;
    slicer.util.restart()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/SegmentComparison&amp;diff=63091</id>
		<title>Documentation/Nightly/Modules/SegmentComparison</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/SegmentComparison&amp;diff=63091"/>
		<updated>2020-03-02T09:50:10Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
This work is part of the SparKit project, funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health and Long-Term Care and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&amp;lt;br&amp;gt;&lt;br /&gt;
Author: Csaba Pinter (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contact: Csaba Pinter, &amp;lt;email&amp;gt;csaba.pinter@queensu.ca&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Documentation/Nightly/Extensions/SlicerRT|Back to SlicerRT home]]&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
|{{collaborator|logo|sparkit}}|{{collaborator|longname|sparkit}}&lt;br /&gt;
|{{collaborator|logo|ocairo}}|{{collaborator|longname|ocairo}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
The {{documentation/modulename}} module provides comparison metrics for segments (i.e. contours, structures)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
&lt;br /&gt;
*Compare segments using Hausdorff distances&lt;br /&gt;
*Compare segments using Dice similarity metrics&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
See [[Documentation/{{documentation/version}}/Extensions/SlicerRT|SlicerRT extension page]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
&lt;br /&gt;
*'''Input'''&lt;br /&gt;
**'''Reference segment:''' The input structure that serves as reference for the comparison. Select segmentation first, then the individual segment&lt;br /&gt;
**'''Compare segment:''' The input structure that serves as the second input (compare) for the comparison. Select segmentation first, then the individual segment&lt;br /&gt;
*'''Hausdorff distance metrics'''&lt;br /&gt;
**'''Compute Hausdorff distances button:''' Click this to compute Hausdorff distances on the specified input structures&lt;br /&gt;
*'''Dice similarity metrics'''&lt;br /&gt;
**'''Compute Dice metrics button:''' Click this to compute Dice similarity metrics on the specified input structures&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{documentation/{{documentation/version}}/module-parametersdescription}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
&lt;br /&gt;
*[[Documentation/{{documentation/version}}/Modules/Segmentations|Segmentations]]&lt;br /&gt;
*[[Documentation/{{documentation/version}}/Modules/SegmentMorphology|Segment morphology]]&lt;br /&gt;
*This module is the successor of [[Documentation/{{documentation/version}}/Modules/ContourComparison|Contour comparison]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
&lt;br /&gt;
*Information about the Plastimatch Hausdorff algorithm used [http://plastimatch.org/doxygen/classHausdorff__distance.html here]&lt;br /&gt;
*Information about the Plastimatch Dice algorithm used [http://plastimatch.org/doxygen/classDice__statistics.html here]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
N/A&lt;br /&gt;
&lt;br /&gt;
|[[File:20150714_0.17_SegmentComparison_ModuleUI.png|thumb|477px| Segment comparison module GUI]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Training&amp;diff=63081</id>
		<title>Documentation/Nightly/Training</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Training&amp;diff=63081"/>
		<updated>2020-02-13T16:56:52Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Slicer4 Image Segmentation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
=Introduction: Slicer {{documentation/version}} Tutorials=&lt;br /&gt;
&lt;br /&gt;
*This page contains &amp;quot;How to&amp;quot; tutorials with matched sample data sets. They demonstrate how to use the 3D Slicer environment (version {{documentation/version}} release) to accomplish certain tasks.&lt;br /&gt;
*For tutorials for other versions of Slicer, please visit the [[Training| Slicer training portal]].&lt;br /&gt;
*For &amp;quot;reference manual&amp;quot; style documentation, please visit the [[Documentation/{{documentation/version}}|Slicer {{documentation/version}} documentation page]]&lt;br /&gt;
*For questions related to the Slicer4 Training Compendium, please send an e-mail to '''[https://scholar.harvard.edu/soniapujol/home Sonia Pujol, Ph.D., Director of Training of 3D Slicer.]'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Some of these tutorials are based on older releases of 3D Slicer and are being upgraded to Slicer4.10. The concepts are still useful but some interface elements and features may be different in updated versions.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Quick Start Guide=&lt;br /&gt;
&lt;br /&gt;
==Downloading and Installing Slicer==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/gtir3x6e007snkx/QuickStartGuide_3DSlicer_SoniaPujol.pdf?dl=0| Quick Start Guide] shows how to install and start 3D Slicer&lt;br /&gt;
*Author: Sonia Pujol, Ph.D.&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[image:QuickStart_image.png|250px|SlicerWelcome tutorial]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=General Introduction=&lt;br /&gt;
&lt;br /&gt;
==Slicer Welcome Tutorial==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/vn8sqlof2kag2kk/SlicerWelcome-tutorial_Slicer4.8_SoniaPujol.pdf?dl=0  Slicer Welcome tutorial] is an introduction to Slicer.&lt;br /&gt;
*Author: Sonia Pujol, Ph.D.&lt;br /&gt;
*Audience: First-time users who want a general introduction to the software&lt;br /&gt;
*Modules: Welcome to Slicer, Sample Data&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[image:SlicerWelcome-image.png|250px|SlicerWelcome tutorial]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Slicer4Minute Tutorial==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/9jfsyhhgude5hf1/Slicer4.8minute_SoniaPujol.pdf?dl=0| Slicer4 Minute Tutorial]  is a brief introduction to the advanced 3D visualization capabilities of Slicer 4.8.&lt;br /&gt;
*Author: Sonia Pujol, Ph.D.&lt;br /&gt;
*Audience: First-time users who want to discover Slicer in 4 minutes&lt;br /&gt;
*Modules: Welcome to Slicer, Models&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
*The [[Media:Slicer4minute.zip|Slicer4Minute dataset]] contains an MR scan of the brain and 3D reconstructions of the anatomy&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[image:Slicer4minute-image.png|250px|right|Slicer4Minute tutorial]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=3D Visualization=&lt;br /&gt;
==Slicer4 Data Loading and 3D Visualization==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
*Slicer 4.10&lt;br /&gt;
**The [http://slicer.kitware.com/midas3/download/item/356408/20180430_DataLoadingAndVisualizationTutorial.pdf Data loading and visualization] ([http://slicer.kitware.com/midas3/download/item/356409/20180430_DataLoadingAndVisualizationTutorial.pptx pptx]) course guides through the basics of loading and viewing volumes and 3D models in Slicer 4.10.&lt;br /&gt;
**Author: Csaba Pinter&lt;br /&gt;
**Modules: Welcome to Slicer, Data, Volume Rendering, Models.&lt;br /&gt;
**Audience: End-users&lt;br /&gt;
**Based on: 3D Slicer version 4.10&lt;br /&gt;
**The [http://slicer.kitware.com/midas3/download/?items=330421,1 3DVisualization dataset] contain an MR scan and a series of 3D models of the brain.&lt;br /&gt;
&lt;br /&gt;
*Slicer 4.5&lt;br /&gt;
**The [[Media:3DDataLoadingandVisualization Slicer4.5 SoniaPujol.pdf| Data loading and 3D visualization]] course guides through the basics of loading and viewing volumes and 3D models in Slicer 4.5.&lt;br /&gt;
**Author: Sonia Pujol, Ph.D.&lt;br /&gt;
**Modules: Welcome to Slicer, Sample Data, Models.&lt;br /&gt;
**Audience: End-users&lt;br /&gt;
**Based on: 3D Slicer version 4.5&lt;br /&gt;
**The [http://slicer.kitware.com/midas3/download/?items=330421,1 3DVisualization dataset] contain an MR scan and a series of 3D models of the brain.&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[Image:20180426_DataLoadingAndVisualizationTutorial.png|right|250px|]]&lt;br /&gt;
[[Image:Slicer4DataLoading_tutorial.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Slicer4 3D Visualization of DICOM images for Radiology Applications==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/9jcjpl33qfh5pi6/3DVisualizationDICOM_Slicer4.8_SoniaPujol.pdf?dl=0 3D Visualization of DICOM images]  course guides through 3D data loading and visualization of DICOM images for Radiology Applications in Slicer4.&lt;br /&gt;
*Author: Sonia Pujol, Ph.D., Kitt Shaffer, M.D., Ph.D., Ron Kikinis, M.D.&lt;br /&gt;
*Audience: Radiologists and users of Slicer who need a more comprehensive overview over Slicer4 visualization capabilities.&lt;br /&gt;
*Modules: DICOM, Volumes, Volume Rendering, Models.&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
*The [[Media:3DVisualization DICOM images part1.zip| 3DVisualizationDICOM_part1]] and [[Media:3DVisualization DICOM images part2.zip| 3DVisualizationDICOM_part2]] datasets contain a series of MR and CT scans, and 3D models of the brain, lung and liver.&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[Image:Slicer4RSNA_2.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Tutorials for software developers=&lt;br /&gt;
&lt;br /&gt;
==Slicer4 Programming Tutorial==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/wrhrvvmplosiis1/Slicer4_ProgrammingTutorial_SPujol-SPieper_Nightly.pdf?dl=0# Slicer Programming tutorial] guides through the integration of a python module in Slicer4.&lt;br /&gt;
*Author: Sonia Pujol, Ph.D., Steve Pieper, Ph.D.&lt;br /&gt;
*Audience: Developers&lt;br /&gt;
*Based on: 3D Slicer version 4.7&lt;br /&gt;
*The [https://www.dropbox.com/s/6yxu8qepmvywk0n/HelloPython_Nightly.zip?dl=0 HelloPython dataset] contains sample data set (MR scan of the brain) and complete Python module examples.&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[Image:HelloPythonTutorial.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==PerkLab's Slicer bootcamp training materials==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [http://perk.cs.queensu.ca/ Laboratory for Percutaneous Surgery at Queen's University] has made available training material of its internal yearly bootcamp, covering topics, such as 3D Slicer overview, basic visualization, segmentation, registration, scripting and module development, surgical navigation, DICOM, reproducible medical image computing research methodology, version control, and research project management.&lt;br /&gt;
**[https://github.com/PerkLab/PerkLabBootcamp/blob/master/Doc/day3_2_SlicerProgramming.pptx?raw=true Scripting and module development tutorial]&lt;br /&gt;
**[https://github.com/PerkLab/PerkLabBootcamp/tree/master/Doc All other tutorials]&lt;br /&gt;
*Author: Andras Lasso, Csaba Pinter, Tamas Ungi, Csaba Pinter, Matthew Holden, Kyle Sunderland&lt;br /&gt;
*Audience: Developers, Users&lt;br /&gt;
*Based on: 3D Slicer version 4.10&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[Image:PerkLabSlicerProgrammingTutorial.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Slicer script repository==&lt;br /&gt;
&lt;br /&gt;
For additional Python scripts examples, please visit the [[Documentation/{{documentation/version}}/ScriptRepository|Script Repository page]]&lt;br /&gt;
&lt;br /&gt;
==Developing and contributing extensions for 3D Slicer==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [http://goo.gl/IP4cdg Developing and contributing extensions for 3D Slicer tutorial] is an introduction to the internals of 3D Slicer and the process of contributing a 3D Slicer extension.&lt;br /&gt;
*Authors: Andrey Fedorov, Jean-Christophe Fillion-Robin, Steve Pieper&lt;br /&gt;
*Audience: Developers&lt;br /&gt;
*Based on: 3D Slicer version 4.4&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[Image:Contributing3DSlicerExtension.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Segmentation=&lt;br /&gt;
==Slicer4 Image Segmentation==&lt;br /&gt;
&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*Segmentation for 3D printing: shows how to use the Segment Editor module for combining CAD designed parts with patient-specific models.&lt;br /&gt;
**'''[https://discourse.slicer.org/t/new-video-tutorial-for-segment-editor-lumbar-spine-segmentation-for-3d-printing/700 Video tutorial]'''. Author: Hillary Lia.&lt;br /&gt;
**'''[[Documentation/{{documentation/version}}/Training#Segmentation_for_3D_printing|Segmentation for 3D printing Step-by-step tutorial]]'''. Author: Csaba Pinter&lt;br /&gt;
**Audience: Users and developers interested in segmentation and 3D printing&lt;br /&gt;
**Dataset: [[:File:BasePiece.zip|Phantom base STL model]] Source: [http://perk-software.cs.queensu.ca/plus/doc/nightly/modelcatalog/ PerkLab].&lt;br /&gt;
**Based on: 3D Slicer version 4.7&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |[[Image:20170717_3DPrintingTutorialYoutube.PNG|280px]]&lt;br /&gt;
|---&lt;br /&gt;
|&lt;br /&gt;
*'''[https://youtu.be/BJoIexIvtGo Video tutorial: Whole heart segmentation from cardiac CT]''' shows how to use the Segment Editor module for segmenting heart ventricles, atria, and great vessels from cardiac CT volumes.&lt;br /&gt;
**Author: Andras Lasso, PhD&lt;br /&gt;
**Audience: Users who need to segment heart structures, for example for visualization, quantification, or simulation.&lt;br /&gt;
**Sample data set: http://slicer.kitware.com/midas3/download/bitstream/738905/CTA-cardio2.nrrd&lt;br /&gt;
**Based on: 3D Slicer version 4.8&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |[[Image:WholeHeartSegYoutube.png|280px]]&lt;br /&gt;
|---&lt;br /&gt;
|&lt;br /&gt;
*'''[https://youtu.be/0at15gjk-Ns Video tutorial: Femur and pelvis segmentation from CT]''' shows how to use the Segment Editor module for segmenting pelvis and femur from CT volumes.&lt;br /&gt;
**Author: Andras Lasso, PhD&lt;br /&gt;
**Audience: Users who need to segment bones in CT images for visualization, quantification, or simulation.&lt;br /&gt;
**Sample data set: https://wiki.cancerimagingarchive.net/display/Public/TCGA-PRAD (Subject TCGA-VP-A878)&lt;br /&gt;
**Based on: 3D Slicer version 4.8&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |[[Image:FemurSegmentationYoutube.png|280px]]&lt;br /&gt;
|---&lt;br /&gt;
|&lt;br /&gt;
*[https://lassoan.github.io/SlicerSegmentationRecipes/ Slicer Segmentation Recipes]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Registration=&lt;br /&gt;
&lt;br /&gt;
==Slicer4 Image Registration==&lt;br /&gt;
&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/chrugp2j2as5gop/ImageRegistration_Slicer4.8_SoniaPujol.pdf?dl=0 Registration tutorial] shows how to perform intra- and inter-subject registration within Slicer.&lt;br /&gt;
*Authors: Sonia Pujol, Ph.D., Dominik Meier, Ph.D., Ron Kikinis, M.D.&lt;br /&gt;
*Audience: Users and developers interested in image registration&lt;br /&gt;
*Dataset: [[Media:RegistrationData.zip| 3D Slicer Registration Data]]&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |[[File:registration_Slicer4.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Slicer Registration Case Library==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The ''[[Documentation/{{documentation/version}}/Registration/RegistrationLibrary|Slicer Registration Case Library]]'' provides real-life example cases of using the Slicer registration tools. They include pre-computed dataset and step-by-step instructions for users to follow.&lt;br /&gt;
&lt;br /&gt;
:Author: Dominik Meier, Ph.D.&lt;br /&gt;
:Audience:  users interested learning/applying Slicer image registration technology&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |[[Image:RegLib_table.png|250px|link=https://www.slicer.org/wiki/Documentation/{{documentation/version}}/Registration/RegistrationLibrary]]&amp;lt;nowiki&amp;gt;|}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
=Slicer Extensions=&lt;br /&gt;
==Slicer4 Diffusion Tensor Imaging Tutorial==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*Please visit [http://dmri.slicer.org/docs/ dmri.slicer.org/docs] for the latest documentation of SlicerDMRI.&lt;br /&gt;
*The [https://www.dropbox.com/s/m7rzeblbdzr49bc/DiffusionMRIAnalysis_Slicer4.8_SoniaPujol.pdf?dl=0| Diffusion Tensor Imaging]  course is an introduction to the basics of loading Diffusion Weighted images in Slicer, estimating tensors and generating fiber tracts.&lt;br /&gt;
*Author: Sonia Pujol, Ph.D.&lt;br /&gt;
*Audience: End-users and developers&lt;br /&gt;
*Modules: Data, Volumes, DWI to DTI Estimation, Diffusion Tensor Scalar Measurements, Editor, Markups,Tractography Label Map Seeding, Tractography Interactive Seeding&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
*The [[Media:Dti tutorial data.zip|DTI dataset]] contains an MR Diffusion Weighted Imaging scan of the brain.&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[Image:Slicer4DTI Tutorial.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Slicer4 Neurosurgical Planning Tutorial==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://spujol.github.io/NeurosurgicalPlanningTutorial/ Neurosurgical Planning tutorial] course guides end-users through the generation of fiber tracts in the vicinity of a tumor.&lt;br /&gt;
*Author: Sonia Pujol, Ph.D., Ron Kikinis, M.D.&lt;br /&gt;
*Audience: Clinicians and Clinical Researchers&lt;br /&gt;
*Modules: Segment Editor, Tractography&lt;br /&gt;
*Based on 3D Slicer version 4.10&lt;br /&gt;
*The [[Media:WhiteMatterExplorationData.zip| White Matter Exploration dataset]] contains a Diffusion Weighted Imaging scan of a brain tumor patient.&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[Image:NeurosurgicalPlanningTutorial.png|right|250px|link=http://vimeo.com/67336069]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Slicer4 Quantitative Imaging tutorial==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [[Media:QuantitativeImaging Slicer4.5.pdf| Slicer4 Quantitative Imaging tutorial]]  guides through the use for Slicer for quantifying small volumetric changes in slow-growing tumors, and for calculating Standardized Uptake Value (SUV) from PET/CT data.&lt;br /&gt;
*Authors: Sonia Pujol, Ph.D., Katarzyna Macura, M.D., Ron Kikinis, M.D.&lt;br /&gt;
*Audience: Radiologists and users of Slicer who need a more comprehensive overview over Slicer4 quantitative imaging capabilities.&lt;br /&gt;
*Modules: Data, Volumes, Models, Change Tracker, PET Standard Uptake Value Computation&lt;br /&gt;
*Based on: 3D Slicer version 4.5&lt;br /&gt;
*The [[Media:QuantitativeImaging.zip| Quantitative Imaging dataset]]  contains a series of MR and PET/CT data.&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[Image:Slicer4_QuantitativeImaging.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Slicer4 IGT==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*[http://www.slicerigt.org/wp/user-tutorial/ Slicer IGT tutorials]&lt;br /&gt;
*Authors: Tamas Ungi, M.D, Ph.D., Junichi Tokuda, Ph.D.&lt;br /&gt;
*Audience: End-users interested in using Slicer for real-time navigated procedures. E.g. navigated needle insertions or other minimally invasive medical procedures.&lt;br /&gt;
*Modules: SlicerIGT Extension&lt;br /&gt;
*Based on: Slicer4.3.1-2014.09.14&lt;br /&gt;
*Data: [https://onedrive.live.com/redir?resid=7230D4DEC6058018!2937&amp;amp;authkey=!AGQkSCZOwjVYXw8&amp;amp;ithint=folder%2cpptx Slicer-IGT datasets]&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[Image:SlicetIGT.png|right|150px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Slicer4 Radiation Therapy Tutorial==&lt;br /&gt;
&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SlicerRT_WorldCongress_TutorialIGRT.pdf SlicerRT tutorial] is an introduction to the Radiation Therapy functionalities of Slicer.&lt;br /&gt;
*Author: Csaba Pinter, Andras Lasso, An Wang, Gregory C. Sharp, David Jaffray, Gabor Fichtinger.&lt;br /&gt;
*Dataset: [http://slicer.kitware.com/midas3/download/item/205404/SlicerRT_WorldCongress_TutorialIGRT_Dataset.zip download] from MIDAS server&lt;br /&gt;
*Based on Slicer 4.7&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
&amp;lt;!-- [[Image:TUTORIAL-IMAGE-HERE.png|right|150px|]] --&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Slicer Pathology==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [[Documentation/{{documentation/version}}/Extensions/SlicerPathology|Slicer Pathology Tutorial]] describes how to use the corresponding tools for automatic and semi-automatic pathology image segmentation.&lt;br /&gt;
*Author: Erich Bremer (Stonybrook), Andriy Fedorov (Brigham and Women’s Hospital)&lt;br /&gt;
*Dataset:  Available directly with the Slicer Pathology Slicer extension.&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[File:SlicerPathologyScreenShot8.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==SPHARM-PDM==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.nitrc.org/docman/view.php/308/1982/SPHARM-PDM_Tutorial_July2015.pdf SPHARM-PDM Tutorial] describes how to use SPHARM-PDM and ShapePopulationViewer Slicer extensions to respectively compute point-based models using a parametric boundary description for the computing of Shape Analysis and perform the quality control between the different models.&lt;br /&gt;
*Author: Jonathan Perdomo (UNC), Beatriz Paniagua (Kitware Inc.)&lt;br /&gt;
*Dataset:  [https://www.nitrc.org/docman/view.php/308/1981/SPHARM_Tutorial_Data_July2015.zip Tutorial Data]&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-SPHARM-PDM.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Fiber Bundle Volume Measurement==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [http://www.na-mic.org/Wiki/images/5/57/Fiber_Bundle_Volume_Measurement.pptx Fiber Bundle Volume Measurement Tutorial] aim is to calculate the volume of the fiber bundle that passes through the Corpus Callosum(CC). Following this tutorial, you’ll be able to (1) convert fiber bundles to label map and (2) calculate volume measurements from the fiber bundles.&lt;br /&gt;
*Author: Shun Gong (Shanghai Changzheng Hospital, China)&lt;br /&gt;
*Dataset:  [http://www.na-mic.org/Wiki/images/4/4c/FiberVolume_data.zip Tutorial data]: The following data are provided: Baseline image, Down sampled whole brain tractography (conducted as in the [[Documentation/{{documentation/version}}/Training#Slicer4_Diffusion_Tensor_Imaging_Tutorial|DWI tutorial]] and down-sampled to about 10000 fibers using Tractography Display module), Corpus callosum label map (drawn as in the [[Documentation/{{documentation/version}}/Training#Slicer4_Diffusion_Tensor_Imaging_Tutorial|DWI tutorial]]).&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-FiberBundleVolumeMeasurements.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=3D Slicer version 4.7 Tutorial Contest=&lt;br /&gt;
&lt;br /&gt;
For previous editions of the contest, please visit the [https://na-mic.org/wiki/Tutorial_Contests 3D Slicer Tutorial Contests page]&lt;br /&gt;
&lt;br /&gt;
===Segmentation for 3D printing===&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SegmentationFor3DPrinting_TutorialContestWinter2017.pdf Segmentation for 3D printing Tutorial] ([https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SegmentationFor3DPrinting_TutorialContestWinter2017.pptx pptx]) is an introduction to the new [[Documentation/{{documentation/version}}/Modules/SegmentEditor|Segment Editor]] module, demonstrated through the popular topic of 3D printing.&lt;br /&gt;
*Author: Csaba Pinter (Queen's University, Canada)&lt;br /&gt;
*[https://www.youtube.com/watch?v=Uht6Fwtr9hE Narrated video version on YouTube].&lt;br /&gt;
*Dataset: [[:File:BasePiece.zip|Phantom base STL model]] Source: [http://perk-software.cs.queensu.ca/plus/doc/nightly/modelcatalog/ PerkLab].&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-Segmentation-for-3d-printing.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Slicer Pathology===&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [[Documentation/{{documentation/version}}/Extensions/SlicerPathology|Slicer Pathology Tutorial]] describes how to use the corresponding tools for automatic and semi-automatic pathology image segmentation.&lt;br /&gt;
*Author: Erich Bremer (Stonybrook), Andriy Fedorov (Brigham and Women’s Hospital)&lt;br /&gt;
*Dataset:  Available directly with the Slicer Pathology Slicer extension.&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[File:SlicerPathologyScreenShot8.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Simple Python Tool for Quality Control of DWI data===&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [http://www.na-mic.org/Wiki/images/3/3a/SimpleDiffusionGradientInformationExtractorTutorial_Chauvin_Jan2017.pptx Simple Multi-shell Diffusion Gradients Information Extractor Tutorial] describes how to use a simple Python script for parsing multi-shell sensitizing gradients information from nifti file format (separated bvecs, bvals files).&lt;br /&gt;
*Author: Laurent Chauvin (ETS Montreal)&lt;br /&gt;
*Dataset:  Not available.&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-SimpleDiffusionGradientInformationExtractorTutorial.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===SPHARM-PDM===&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.nitrc.org/docman/view.php/308/1982/SPHARM-PDM_Tutorial_July2015.pdf SPHARM-PDM Tutorial] describes how to use SPHARM-PDM and ShapePopulationViewer Slicer extensions to respectively compute point-based models using a parametric boundary description for the computing of Shape Analysis and perform the quality control between the different models.&lt;br /&gt;
*Author: Jonathan Perdomo (UNC), Beatriz Paniagua (Kitware Inc.)&lt;br /&gt;
*Dataset:  [https://www.nitrc.org/docman/view.php/308/1981/SPHARM_Tutorial_Data_July2015.zip Tutorial Data]&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-SPHARM-PDM.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Integration of Robot Operating System (ROS) and 3D Slicer using OpenIGTLink===&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.na-mic.org/Wiki/images/a/ab/ROSIGTLTutorial_Tokuda_Jan2017.pptx Integration of Robot Operating System (ROS) and 3D Slicer using OpenIGTLink Tutorial] describes the software architecture of surgical robot systems and allows to acquire hands-on experience of software-hardware integration for medical robotics.&lt;br /&gt;
*Author: Junichi Tokuda (Brigham and Women’s Hospital)&lt;br /&gt;
*Dataset:  Not available.&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-Integration-ROS-3DSlicer-OpenIGTLink.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Fiber Bundle Volume Measurement===&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [http://www.na-mic.org/Wiki/images/5/57/Fiber_Bundle_Volume_Measurement.pptx Fiber Bundle Volume Measurement Tutorial] aim is to calculate the volume of the fiber bundle that passes through the Corpus Callosum(CC). Following this tutorial, you’ll be able to (1) convert fiber bundles to label map and (2) calculate volume measurements from the fiber bundles.&lt;br /&gt;
*Author: Shun Gong (Shanghai Changzheng Hospital, China)&lt;br /&gt;
*Dataset:  [http://www.na-mic.org/Wiki/images/4/4c/FiberVolume_data.zip Tutorial data]: The following data are provided: Baseline image, Down sampled whole brain tractography (conducted as in the [[Documentation/{{documentation/version}}/Training#Slicer4_Diffusion_Tensor_Imaging_Tutorial|DWI tutorial]] and down-sampled to about 10000 fibers using Tractography Display module), Corpus callosum label map (drawn as in the [[Documentation/{{documentation/version}}/Training#Slicer4_Diffusion_Tensor_Imaging_Tutorial|DWI tutorial]]).&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-FiberBundleVolumeMeasurements.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=YouTube videos=&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;5&amp;quot; width=&amp;quot;1200px&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:20%&amp;quot; |[[Image:Verterbra.png|right|250px|]] [https://www.youtube.com/watch?v=Uht6Fwtr9hE How to segment multiple vertebrae in spine CT for 3D printing - Author: Hillary Lia]&lt;br /&gt;
| style=&amp;quot;width:20%&amp;quot; |[[Image:Femurmodel.png|right|250px|]] [https://www.youtube.com/watch?v=0at15gjk-Ns Creating a femur model from CT volume using 3D Slicer - Author: PerkLab]&lt;br /&gt;
| style=&amp;quot;width:20%&amp;quot; |[[Image:3DPrinting.png|right|250px|]] [https://www.youtube.com/watch?v=MKLWzD0PiIc Preparing data for 3D printing - Author: Nabgha Farhat]&lt;br /&gt;
| style=&amp;quot;width:20%&amp;quot; |[[Image:DICOM2.png|right|250px|]] [https://www.youtube.com/watch?v=nzWf4xHy1BM&amp;amp; How to export CT and segmentation data to DICOM - Author: Andras Lasso, Csaba Pinter]&lt;br /&gt;
| style=&amp;quot;width:20%&amp;quot; |[[Image:LocalThresholdEffect.png|right|250px|]] [https://www.youtube.com/watch?time_continue=26&amp;amp;v=cevlMLyhfK8&amp;amp;feature=emb_logo  Local Threshold Effect - Author: Kyle Sunderland]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additional [http://www.youtube.com/results?search_query=3d+slicer&amp;amp;sm=3 non-curated videos-based demonstrations using 3D Slicer are accessible on YouTube].&lt;br /&gt;
&lt;br /&gt;
=Teams Contributions=&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*This ''Slicer 4.1 [http://vimeo.com/41096643 webinar]'' presents the new features and improvements of the release, and a brief overview of work for the next release.&lt;br /&gt;
*Authors: Steve Pieper Ph.D.&lt;br /&gt;
*Audience: First time users and developers interested in Slicer 4.1 new features.&lt;br /&gt;
*Length: 0h20m&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |[[Image:Webinar-Slicer-4.1.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*This ''Intro to Slicer 4.0 [http://vimeo.com/37671358 webinar]'' provides an introduction to 3DSlicer, and demonstrates core functionalities such as loading, visualizing and saving data. Basic processing tools, including manual registration, manual segmentation and tractography tools are also highlighted. This webinar is a general overview. For in depth information see the modules above and the documentation pages.&lt;br /&gt;
*Authors: Julien Finet, M.S., Steve Pieper, Ph.D., Jean-Christophe Fillion-Robin, M.S.&lt;br /&gt;
*Audience: First time users interested in a broad overview of Slicer’s features and tools.&lt;br /&gt;
*Length: 1h20m&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |[[Image:Webinar.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==International resources==&lt;br /&gt;
&lt;br /&gt;
==Resources in Chinese==&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
A 3D Slicer community on WeChat in China offers many tutorials and clinical examples in Chinese.  Note that the images are of interest to non-Chinese speakers and Google Translate does a reasonable job of translating some of the text.&lt;br /&gt;
&lt;br /&gt;
*[https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247486116&amp;amp;idx=1&amp;amp;sn=772e9d431ac32cbb73d08cf0e6bc219a&amp;amp;chksm=eacc0096ddbb89805d93ac4be181d1a35058031bac673d7a91b3b44dccee2bfd1d8461397635#rd Getting started 大脑前动脉远端动脉瘤手术夹闭治疗]&lt;br /&gt;
&lt;br /&gt;
*[https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247484787&amp;amp;idx=1&amp;amp;sn=1f6279bdccab168fc79b7275e9fe91ca&amp;amp;chksm=eacc0f41ddbb8657be92f617661133d87bb55a4ecf12f786e97a8b7d5249a05d11e0cd620c3f#rd distal anterior cerebral artery aneurysm 3D Slicer：漂亮得不像实力派]&lt;br /&gt;
&lt;br /&gt;
*[https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247486360&amp;amp;idx=1&amp;amp;sn=f833b13a26f543aa9175419a03df7f52&amp;amp;chksm=eacc01aaddbb88bcb004773a4db8a9b3c7633d21cda3956f84b96515252eb861c5eb1e75a60b&amp;amp;mpshare=1&amp;amp;scene=24&amp;amp;srcid=0212LIfOkBRm9CvA7ImHCpRt#rd meningioma skull resection 脑膜瘤患者颅骨切除一期修补的3DSlicer方案]&lt;br /&gt;
&lt;br /&gt;
*[https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247486079&amp;amp;idx=1&amp;amp;sn=9b926dc398a408e3441082b9e0ffde61&amp;amp;chksm=eacc004dddbb895bf9b60f5f1bc443513196e4cb90a6caf6f348a4da7b7fc22eb658661aeb49&amp;amp;mpshare=1&amp;amp;scene=24&amp;amp;srcid=0212AFtT2Wq7K7bvkMGTdyih#rd Cerebral hemorrhage by forehead positioning method 脑出血经额手术定位法（五]&lt;br /&gt;
&lt;br /&gt;
*[https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247485356&amp;amp;idx=1&amp;amp;sn=044f5899b651b35994db00c32ab688ee&amp;amp;chksm=eacc0d9eddbb8488f16ff82bb1dda8456a4011790fed024781972d578783e67781443cf4a319&amp;amp;mpshare=1&amp;amp;scene=24&amp;amp;srcid=0212G45TadrPnX8tp9eaNXUs#rd Hematoma modeling 血肿建模的第11种方法]&lt;br /&gt;
&lt;br /&gt;
*[https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247486025&amp;amp;idx=1&amp;amp;sn=b281324893be4ab116d20826f1b426c3&amp;amp;chksm=eacc007bddbb896d9deb096f209278f40c0b52c6410a8a9ff3ce8c3697c99304f18eb678f11e&amp;amp;mpshare=1&amp;amp;scene=24&amp;amp;srcid=02125v1kxvIGmfkxx7mUZcCM#rd Mobile phone positioning and AR application 手机定位及AR应用的初步探索]&lt;br /&gt;
&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |&lt;br /&gt;
[[image:Wechat-hemorage-2018-02-12.png|250px|Example WeChat tutorial slides]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Resources in German==&lt;br /&gt;
&lt;br /&gt;
*[https://www.youtube.com/watch?v=sl-00kGpuPk&amp;amp;list=PLJWCUXz3GeAfmYLiFcKus_c0jcsMnVsgb A series of four YouTube videos on python programming in Slicer] (German narration with English subtitles)&lt;br /&gt;
&lt;br /&gt;
==Murat Maga's blog posts about using 3D Slicer for biology==&lt;br /&gt;
&lt;br /&gt;
*[https://blogs.uw.edu/maga/2017/04/11/getting-started-with-3d-slicer-as-a-biologist/ Slicer for Biologists]&lt;br /&gt;
*[https://blogs.uw.edu/maga/2017/04/11/a-worked-example-getting-and-visualizing-data-from-digimorph/ Loading data from DigiMorph]&lt;br /&gt;
*[https://blogs.uw.edu/maga/2017/04/11/morphosource-data-and-dealing-with-dicom-series-in-slicer/ Fixing problem DICOM]&lt;br /&gt;
*[https://blogs.uw.edu/maga/2017/04/12/scissors-tool-is-awesome/ Scissors tool is awesom]&lt;br /&gt;
 &lt;br /&gt;
==Using the (legacy) Editor==&lt;br /&gt;
&lt;br /&gt;
===Fast GrowCut===&lt;br /&gt;
&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [[Media:FastGrowCutTutorial.pdf|Fast GrowCut tutorial]]  shows how to perform a segmentation using the Fast GrowCut effect in Slicer.&lt;br /&gt;
*Authors: Hillary Lia&lt;br /&gt;
*Audience: Users interested in segmentation&lt;br /&gt;
| align=&amp;quot;right&amp;quot; |[[File:FastGrowCutLogo.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Use case: Slicer in paleontology===&lt;br /&gt;
&lt;br /&gt;
This set of tutorials about the use of slicer in paleontology is very well written and provides step-by-step instructions.  Even though it covers slicer version 3.4, many of the concepts and techniques have applicability to the new version and to any 3D imaging field:&lt;br /&gt;
&lt;br /&gt;
*[http://openpaleo.blogspot.com/2008/12/3d-slicer-tutorial.html Open Source Paleontologist: 3D Slicer: The Tutorial]&lt;br /&gt;
*[http://openpaleo.blogspot.com/2008/12/3d-slicer-tutorial-part-ii.html Open Source Paleontologist: 3D Slicer: The Tutorial Part II]&lt;br /&gt;
*[http://openpaleo.blogspot.com/2008/12/3d-slicer-tutorial-part-iii.html Open Source Paleontologist: 3D Slicer: The Tutorial Part III]&lt;br /&gt;
*[http://openpaleo.blogspot.com/2008/12/3d-slicer-tutorial-part-iv.html Open Source Paleontologist: 3D Slicer: The Tutorial Part IV]&lt;br /&gt;
*[http://openpaleo.blogspot.com/2009/03/3d-slicer-tutorial-part-v.html Open Source Paleontologist: 3D Slicer: The Tutorial Part V]&lt;br /&gt;
*[http://openpaleo.blogspot.com/2009/03/3d-slicer-tutorial-part-vi.html Open Source Paleontologist: 3D Slicer: The Tutorial Part VI]&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Labs/Slicer5-roadmap&amp;diff=62792</id>
		<title>Documentation/Labs/Slicer5-roadmap</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Labs/Slicer5-roadmap&amp;diff=62792"/>
		<updated>2020-01-21T11:09:08Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Coordinate system in files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The major version number upgrade to 5 provides an opportunity to make changes that affect the&lt;br /&gt;
application, the API, or the code in a way that was not possible in the past seven or so years.&lt;br /&gt;
&lt;br /&gt;
This page collects community suggestions related to the transition plan for Slicer 4.10 and major changes for Slicer 5.x&lt;br /&gt;
&lt;br /&gt;
Related forum post: https://discourse.slicer.org/t/slicer-5-0-deprecation-discussion-wiki/2377&lt;br /&gt;
&lt;br /&gt;
==Overall Goals==&lt;br /&gt;
&lt;br /&gt;
*Improve user experience&lt;br /&gt;
**More logical interface&lt;br /&gt;
**Perform most common tasks easily&lt;br /&gt;
**Easier to discover advanced features&lt;br /&gt;
**Improve asynchronous behavior (like loading data in a background thread)&lt;br /&gt;
*Defining core and extensions&lt;br /&gt;
**Core functionality is:&lt;br /&gt;
***DICOM and other format I/O, Subject management&lt;br /&gt;
***Visualization 2D/3D/4D&lt;br /&gt;
***Segmentation&lt;br /&gt;
***Transforms and Registration&lt;br /&gt;
***Annotations and Markups&lt;br /&gt;
***Programmability and Extensibility&lt;br /&gt;
**Move some extensions to core (Sequences, DICOMPlugins...)&lt;br /&gt;
**Move some core to extensions (SimpleITK, Editor...)&lt;br /&gt;
*Simplify maintenance&lt;br /&gt;
**Remove legacy code that adds more complexity than value&lt;br /&gt;
**Deprecate support for older build options and platforms (old libs, old compilers, etc)&lt;br /&gt;
**Simplify documentation creation and use&lt;br /&gt;
**Streamline the build and release process&lt;br /&gt;
**Use unmodified upstream libraries&lt;br /&gt;
*Developer experience&lt;br /&gt;
**Improve API / Scripting documentation organization / search engine optimization&lt;br /&gt;
**Simplify/accelerate build process on all platforms (options to use prebuilt sdk for example)&lt;br /&gt;
**Use standard packages (Qt, Python, VTK, ITK)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Specific Change Proposals==&lt;br /&gt;
&lt;br /&gt;
===Slicer 5.0: Backward incompatible changes===&lt;br /&gt;
&lt;br /&gt;
====Third-party library updates====&lt;br /&gt;
&lt;br /&gt;
*Update to latest VTK: may fix issues in rendering (Virtual Reality Qt widget, [https://discourse.slicer.org/t/setting-of-markerstyle-does-not-work/9073/6 plot line markers])&lt;br /&gt;
*Update to latest Qt: May fix [https://discourse.slicer.org/t/extension-wizard-file-open-dialogs-hang-ui-for-several-seconds/7881/9 Qt temporary hang] on startup and when showing file dialog&lt;br /&gt;
&lt;br /&gt;
====Python3====&lt;br /&gt;
&lt;br /&gt;
Switch to Python3 and use the same compiler as official Python distribution. This would allow installation of any Python package inside Slicer's Python environment.&lt;br /&gt;
&lt;br /&gt;
Tasks:&lt;br /&gt;
&lt;br /&gt;
*Update of CTK: Build system, CTK Python console and [https://github.com/commontk/CTK/blob/master/CMake/ctkWrapPythonQt.py ctkWrapPythonQt.py] - '''DONE''' {{done}}&lt;br /&gt;
*Update [https://github.com/Slicer/Slicer/blob/master/SuperBuild/External_python.cmake External_python.cmake] - '''DONE''' {{done}}&lt;br /&gt;
*Update of &amp;quot;C++ to python bridge&amp;quot; classes ([https://github.com/Slicer/Slicer/blob/master/Base/QTCore/qSlicerScriptedUtils_p.h qSlicerScriptedUtils_p.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTGUI/qSlicerScriptedLoadableModule.h qSlicerScriptedLoadableModule.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTGUI/qSlicerScriptedFileDialog.h qSlicerScriptedFileDialog.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTGUI/qSlicerScriptedLoadableModuleWidget.h qSlicerScriptedLoadableModuleWidget.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTCore/qSlicerScriptedFileWriter.h qSlicerScriptedFileWriter.h], ...) - '''DONE''' {{done}}&lt;br /&gt;
*Update of install rules and macos fixup - '''DONE''' {{done}}&lt;br /&gt;
*Update of python scripts to be compliant with python 3 - '''DONE''' {{done}}&lt;br /&gt;
&lt;br /&gt;
Some of the issues discovered after integration of Python 3:&lt;br /&gt;
&lt;br /&gt;
*Fix iomodule.c build error with VS2017. See https://github.com/Slicer/Slicer/pull/1118#issuecomment-482436689. Fixed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=28138 r28138] - '''DONE''' {{done}}&lt;br /&gt;
*Fix crash in Debug build. See https://github.com/lassoan/Slicer/tree/python-startup-hang-in-debug-mode. Fixed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=28141 r28141] - '''DONE''' {{done}}&lt;br /&gt;
*&amp;lt;tt&amp;gt;restart()&amp;lt;/tt&amp;gt; Python function does not work. Fixed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=28143 r28143] - '''DONE''' {{done}}&lt;br /&gt;
&lt;br /&gt;
References:&lt;br /&gt;
&lt;br /&gt;
*discourse post: https://discourse.slicer.org/t/updating-slicer-to-work-with-python-3/4662/14&lt;br /&gt;
*GitHub PR: https://github.com/Slicer/Slicer/pull/1118&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Revisit MRML Copy API====&lt;br /&gt;
&lt;br /&gt;
Copy method does not perform complete deep-copy in some classes. For Sequences, we need both DeepCopy (for node modifications) and ShallowCopy (for fast replay possible).&lt;br /&gt;
&lt;br /&gt;
There are also too many variants of node copy methods, which makes it difficult to use them correctly.&lt;br /&gt;
&lt;br /&gt;
See also https://issues.slicer.org/view.php?id=2608.&lt;br /&gt;
&lt;br /&gt;
====Coordinate system in files====&lt;br /&gt;
&lt;br /&gt;
To be consistent with the rest of the world: Save models and markups in LPS coordinate system by default. If no coordinate system is specified in input file, assume LPS. See https://issues.slicer.org/view.php?id=4445&lt;br /&gt;
&lt;br /&gt;
====Acquisition transform====&lt;br /&gt;
&lt;br /&gt;
Enable acquisition transform by default, to show correct loading of tilted gantry images. It has proven to work well.  See https://github.com/Slicer/Slicer/commit/b7650af3c27f34fc894bfdd587f2a4c02ba62a8b&lt;br /&gt;
&lt;br /&gt;
====Model Hierarchies====&lt;br /&gt;
&lt;br /&gt;
Remove Model Hierarchy feature and make sure that Subject Hierarchy covers all use cases.  This will impact ModelMaker, which should be converted to a simpler version that only returns models and not semantics.  Need to check extensions, especially SlicerDMRI, for any dependencies on Model Hierarchy. - '''DONE''' {{done}}&lt;br /&gt;
&lt;br /&gt;
==== Extension description file format ====&lt;br /&gt;
&lt;br /&gt;
Transition from [[Documentation/Nightly/Developers/Extensions/DescriptionFile|`.s4ext` text file]] to a json or yaml.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Slicer 5.2: Backward incompatible changes===&lt;br /&gt;
&lt;br /&gt;
====Build System Simplification====&lt;br /&gt;
&lt;br /&gt;
*Pick the most recent reasonable CMake version and remove any complexities in the build system are only there to work around limitations of old CMake versions.&lt;br /&gt;
&lt;br /&gt;
*Consider any ways to streamline/simplify the configure and build process, even it if may require changing extensions.&lt;br /&gt;
&lt;br /&gt;
*Look for ways to minimize the effect of long directory path-related build issues.  Currently on mac and windows we are pushing the limit of path length unless very short paths are used (e.g. /s5 or d:\s5).  Reorganizing the build tree might give us more headroom.&lt;br /&gt;
&lt;br /&gt;
====Remove remote data support from MRML====&lt;br /&gt;
&lt;br /&gt;
MRML theoretically supports downloading files through http, but this feature has not seen much use. This will not likely to change in the future because there is a wide range of data access and authentication protocols, which would not be practical at MRML level.&lt;br /&gt;
&lt;br /&gt;
It would be better to remove remote data support from MRML to simplify data storage. We can keep useful utility classes, such as cache manager for keeping track of local temporary files (downloaded using SampleData or other modules that download significant amount of temporary data).&lt;br /&gt;
&lt;br /&gt;
See also https://discourse.slicer.org/t/improving-testing-data-management-for-self-test/5014/4.&lt;br /&gt;
&lt;br /&gt;
====Improve layout manager====&lt;br /&gt;
&lt;br /&gt;
*Support multiple displays: Currently, it is very hard to leverage multiple displays (need to stretch the Slicer window over multiple screens and align splitter manually to the screen boundary). Allow defining single-display and multi-display layouts. Single-display layouts could be selected for each display independently, while multi-monitor layouts would set views on several displays at once. Keeping a single layout manager (and enhance it with to allow creation of multiple widgets) would make it easier to maintain backward compatibility for existing modules.&lt;br /&gt;
*View layout IDs: View layout IDs are currently integer values, which makes it difficult to ensure that modules always choose unique IDs. We should switch to using string IDs. String IDs can may be prefixed with modulename+&amp;quot;.&amp;quot; as we do it for singleton tags and node attributes. We may remain somewhat backward compatible by having SetLayoutID(int) method that maps known layout integer IDs to the new string IDs. See discussion here: https://github.com/Slicer/Slicer/pull/1061#discussion_r241825827&lt;br /&gt;
&lt;br /&gt;
====SceneViews====&lt;br /&gt;
&lt;br /&gt;
The scene views feature does not work well for a long time now, and there is no consensus about what should be the scope it supports.&lt;br /&gt;
&lt;br /&gt;
Suggestion:&lt;br /&gt;
&lt;br /&gt;
*Do not save the state of all nodes: Support only display, view and hierarchy nodes.&lt;br /&gt;
*Make SceneViews as stable as possible for these cases and remove support for data notes etc.&lt;br /&gt;
*If a node is removed, update associated scene views&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
*2018-12-13: Jc: Following discussion with Ron, we should keep the SceneView functionality. All data should be associated with the &amp;quot;master&amp;quot; view, and scene view should be different combination of viewing parameters (layout, camera, visibility, etc ...). A mrb to consider for testing is the [http://slicer.kitware.com/midas3/slicerdatastore/view?itemId=126553&amp;amp;layout=layout LungSegments_scene.mrb]&lt;br /&gt;
*Another suggestion from Sonia is that SceneViews could be read-only for certain classes of nodes.  It's not clear how that would be implemented, but it could address the instability problems while enabling the use of SceneViews for training.&lt;br /&gt;
&lt;br /&gt;
====Undo/Redo====&lt;br /&gt;
Similarly to SceneViews, it is a great feature but in time it started breaking.&lt;br /&gt;
Need to decide if we want to keep it, and if yes fix it.&lt;br /&gt;
&lt;br /&gt;
Potential fix (currently being tested by Kyle Sunderland and Andras Lasso): Add an &amp;quot;undo enabled&amp;quot; flag to vtkMRMLNode, disable it by default, only enable it for nodes that undo/redo has tested to work correctly. Preliminary tests show that the feature largely works, but there are complications with undo/redo of node add/remove actions and node references.&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
*2018-12-13: Jc: Following discussion with Ron, would be nice to also have undo/redo for camera settings, field of view, etc ... within a given view. It is easy to inadvertently modify settings ... (e.g when trying to pan using a trackpad with shift+left click but inadvertently using only left click)&lt;br /&gt;
&lt;br /&gt;
====Removal of Charts based infrastructure====&lt;br /&gt;
&lt;br /&gt;
With Slicer 5.0, the idea is to remove the [[Documentation/Nightly/Developers/Charts|Charts]] infrastructure based on jqPlot, and only keep&lt;br /&gt;
the [[Documentation/Nightly/Developers/Plots|Plots]] infrastructure based on VTK Charts.&lt;br /&gt;
&lt;br /&gt;
Ron's request: enable anti-aliasing (MSAA or FXAA) and use less subtle default colors (https://www.slicer.org/wiki/Slicer4:2012_GenericChartColors) to improve appearance.&lt;br /&gt;
&lt;br /&gt;
===Remove deprecated modules and/or Migrate to extension===&lt;br /&gt;
&lt;br /&gt;
====Editor====&lt;br /&gt;
The module already directs users to Segment Editor, which provides all the functionality of Editor and more, and&lt;br /&gt;
is the successor module that will be improved and maintained. Removing it would decrease confusion of both old&lt;br /&gt;
and new Slicer users&lt;br /&gt;
&lt;br /&gt;
*Potentially the hack about modules with names ending with the string &amp;quot;Lib&amp;quot; can also be removed after the Editor module will not require it. It is [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Base/QTCore/qSlicerUtils.cxx?r1=26891&amp;amp;r2=26890&amp;amp;pathrev=26891 around here].&lt;br /&gt;
&lt;br /&gt;
*'''Make Editor hidden in 4.10, advertise its removal (some extensions still use it), then remove it in 5.0'''. Remove it from toolbar, move Editor to legacy category in 4.10&lt;br /&gt;
&lt;br /&gt;
*Investigate if the module could easily be moved to an extension&lt;br /&gt;
&lt;br /&gt;
====VectorToScalarVolume====&lt;br /&gt;
&lt;br /&gt;
The plan would be to improve the Volume module so that vector volume could be converted to scalar volume, similarly to scalar to labelmap conversion option. Then, this module could be removed.&lt;br /&gt;
&lt;br /&gt;
====Unused module code====&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;s&amp;gt;MultiVolumeRendering: A [https://github.com/Slicer/Slicer/tree/master/Modules/Loadable/MultiVolumeRendering module] that was effectively not developed since 2012, and is not currently compiled with Slicer.&amp;lt;/s&amp;gt; - Removed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27087 r27087]&lt;br /&gt;
*&amp;lt;s&amp;gt;Measurements: Same argument as MultiVolumeRendering&amp;lt;/s&amp;gt; - Removed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27087 r27087]&lt;br /&gt;
*&amp;lt;s&amp;gt;AtlasCreator Loadable module logic&amp;lt;/s&amp;gt; - Removed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27088 r27088]&lt;br /&gt;
&lt;br /&gt;
====CLI modules====&lt;br /&gt;
&lt;br /&gt;
*Model to Label Map: Has too many limitations and bugs (cannot handle concave structures, can cause Slicer to hang or crash, etc.), and is not maintained any more. It might be better to remove it than to fix it, especially that there is an algorithm for the same thing in Slicer that works much better&lt;br /&gt;
**The model node to labelmap node conversion feature could be added as a subject hierarchy plugin, if the route via segmentation node is not convenient enough&lt;br /&gt;
&lt;br /&gt;
*Review CLI modules&lt;br /&gt;
**BlobDetection&lt;br /&gt;
**ConnectedComponent&lt;br /&gt;
**GrayscaleModelMaker, ModelMaker: The modules are too different to combine them. Each have specific use cases.&lt;br /&gt;
**DiffusionTensorTest, ROITest, TestGridTransformRegistration: Already excluded from package by specifying &amp;lt;tt&amp;gt;NO_INSTALL&amp;lt;/tt&amp;gt;&lt;br /&gt;
**Resample Scalar Volume: Resample Scalar/Vector/DWI Volume module (which Crop Volume uses as well) can do everything it does already, except for four extra interpolation options. Probably can be removed&lt;br /&gt;
&lt;br /&gt;
====Migrate to extension====&lt;br /&gt;
&lt;br /&gt;
Existing [https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/DMRIInstall/DMRIInstall.py DMRIInstall] scripted module will be re-factored and moved into a &amp;lt;tt&amp;gt;Modules/Scripted/InstallSuggestions&amp;lt;/tt&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Then, after transitioning them to extension, the following module will be added to the &amp;quot;InstallSuggestions&amp;quot; so that the user knows how to install them:&lt;br /&gt;
&lt;br /&gt;
*BRAINSTools (also add SlicerElastix to the suggestions)&lt;br /&gt;
*SimpleITK: Only used in the editor&lt;br /&gt;
*EMSegment: already disabled in Slicer-4.10, so it may be completely removed from build scripts instead of moving it to an extension&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
*2018-12-13: Jc: Following discussion with Ron, we need to make sure to have at least one non-rigid registration method and one ICP based method (e.g Landmark Registration) available in the main distribution.&lt;br /&gt;
&lt;br /&gt;
====PETStandardUptakeValueComputation====&lt;br /&gt;
&lt;br /&gt;
Remove PETStandardUptakeValueComputation from Slicer core, as a more advanced version of this is available in an extension: https://github.com/QIICR/Slicer-PETDICOMExtension. See details here: https://github.com/Slicer/Slicer/pull/1068#issuecomment-450905887&lt;br /&gt;
&lt;br /&gt;
===Coding Style===&lt;br /&gt;
&lt;br /&gt;
====Slicer 5.0: Indentation of curly braces====&lt;br /&gt;
In Slicer the curly braces have a two-space indentation everywhere within functions. As this was inherited from VTK, but VTK changed its convention to align the braces with the statements (if etc.), it could make sense to make the change in Slicer too. This is considered a major change because it affects almost all cxx files.&lt;br /&gt;
&lt;br /&gt;
====Simpler VTK smart pointer usage====&lt;br /&gt;
Use &amp;lt;code&amp;gt;vtkNew&amp;lt;type&amp;gt; var;&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;vtkSmartPointer&amp;lt;type&amp;gt; var = vtkSmartPointer&amp;lt;type&amp;gt;::New();&amp;lt;/code&amp;gt; and remove now unnecessary &amp;lt;code&amp;gt;.GetPointer()&amp;lt;/code&amp;gt; calls.&lt;br /&gt;
&lt;br /&gt;
===Usability===&lt;br /&gt;
&lt;br /&gt;
====Volume Rendering Activation Method====&lt;br /&gt;
&lt;br /&gt;
We have had lots of issues with people finding the eye icon.&lt;br /&gt;
&lt;br /&gt;
===Miscellaneous===&lt;br /&gt;
&lt;br /&gt;
====Tcl codes====&lt;br /&gt;
&amp;lt;s&amp;gt;Most of the TCL code seems to be a heritage from Slicer3. Can they be removed?&amp;lt;/s&amp;gt; - Done in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27091 r27091]&lt;br /&gt;
&lt;br /&gt;
====Remove self-test modules from the All modules list====&lt;br /&gt;
Users already find the all modules list very long, and as the self tests are for developers only (and can be found in the modules list under the Testing category), they could be removed from the list.  Make sure they are available in Developer mode.&lt;br /&gt;
&lt;br /&gt;
====Remove BTX/ETX pairs====&lt;br /&gt;
Once VTK7 is no longer supported, the old way for disabling python wrapping is no longer needed. According to my tests (Csaba), wrapping works fine in all of those cases, so the new way (#ifndef __VTK_WRAP__) is not needed either.&lt;br /&gt;
&lt;br /&gt;
==Additional proposed changes to be discussed==&lt;br /&gt;
&lt;br /&gt;
*Bundle IPython package in Slicer installer - Slicer Jupyter extension has been added, do we need more?&lt;br /&gt;
**Do we want history across sessions?&lt;br /&gt;
**Quick access to script repository&lt;br /&gt;
*[https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Install using brew]&lt;br /&gt;
*Add opt-in collection of usage statistics for various features (e.g. could be triggered when a module is entered).&lt;br /&gt;
*Enable geometry correction by default (e.g. gantry tilt as [https://discourse.slicer.org/t/actual-size-of-stl-models/5005/21 discussed here]).&lt;br /&gt;
*Remove legacy 1.0 pydicom and only bundle latest (see https://pydicom.github.io/pydicom/stable/transition_to_pydicom1.html#).  Import name changed from 'dicom' to 'pydicom' (See also: https://github.com/Slicer/Slicer/pull/1231)&lt;br /&gt;
*Remove DICOM Networking (DIMSE) code https://discourse.slicer.org/t/dicom-retrieve-on-windows-10-there-is-no-service-listening-dicom-communications-no-telnet-connection-to-ports&lt;br /&gt;
*Update the logo along [https://discourse.slicer.org/t/slicer-module-panel-icon-in-dark-mode/8353/3 as discussed here].&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Labs/Slicer5-roadmap&amp;diff=62788</id>
		<title>Documentation/Labs/Slicer5-roadmap</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Labs/Slicer5-roadmap&amp;diff=62788"/>
		<updated>2020-01-13T10:20:17Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Specific Change Proposals */ Mark Model Hierarchies task as done&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The major version number upgrade to 5 provides an opportunity to make changes that affect the&lt;br /&gt;
application, the API, or the code in a way that was not possible in the past seven or so years.&lt;br /&gt;
&lt;br /&gt;
This page collects community suggestions related to the transition plan for Slicer 4.10 and major changes for Slicer 5.x&lt;br /&gt;
&lt;br /&gt;
Related forum post: https://discourse.slicer.org/t/slicer-5-0-deprecation-discussion-wiki/2377&lt;br /&gt;
&lt;br /&gt;
==Overall Goals==&lt;br /&gt;
&lt;br /&gt;
*Improve user experience&lt;br /&gt;
**More logical interface&lt;br /&gt;
**Perform most common tasks easily&lt;br /&gt;
**Easier to discover advanced features&lt;br /&gt;
**Improve asynchronous behavior (like loading data in a background thread)&lt;br /&gt;
*Defining core and extensions&lt;br /&gt;
**Core functionality is:&lt;br /&gt;
***DICOM and other format I/O, Subject management&lt;br /&gt;
***Visualization 2D/3D/4D&lt;br /&gt;
***Segmentation&lt;br /&gt;
***Transforms and Registration&lt;br /&gt;
***Annotations and Markups&lt;br /&gt;
***Programmability and Extensibility&lt;br /&gt;
**Move some extensions to core (Sequences, DICOMPlugins...)&lt;br /&gt;
**Move some core to extensions (SimpleITK, Editor...)&lt;br /&gt;
*Simplify maintenance&lt;br /&gt;
**Remove legacy code that adds more complexity than value&lt;br /&gt;
**Deprecate support for older build options and platforms (old libs, old compilers, etc)&lt;br /&gt;
**Simplify documentation creation and use&lt;br /&gt;
**Streamline the build and release process&lt;br /&gt;
**Use unmodified upstream libraries&lt;br /&gt;
*Developer experience&lt;br /&gt;
**Improve API / Scripting documentation organization / search engine optimization&lt;br /&gt;
**Simplify/accelerate build process on all platforms (options to use prebuilt sdk for example)&lt;br /&gt;
**Use standard packages (Qt, Python, VTK, ITK)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Specific Change Proposals==&lt;br /&gt;
&lt;br /&gt;
===Slicer 5.0: Backward incompatible changes===&lt;br /&gt;
&lt;br /&gt;
====Third-party library updates====&lt;br /&gt;
&lt;br /&gt;
*Update to latest VTK: may fix issues in rendering (Virtual Reality Qt widget, [https://discourse.slicer.org/t/setting-of-markerstyle-does-not-work/9073/6 plot line markers])&lt;br /&gt;
*Update to latest Qt: May fix [https://discourse.slicer.org/t/extension-wizard-file-open-dialogs-hang-ui-for-several-seconds/7881/9 Qt temporary hang] on startup and when showing file dialog&lt;br /&gt;
&lt;br /&gt;
====Python3====&lt;br /&gt;
&lt;br /&gt;
Switch to Python3 and use the same compiler as official Python distribution. This would allow installation of any Python package inside Slicer's Python environment.&lt;br /&gt;
&lt;br /&gt;
Tasks:&lt;br /&gt;
&lt;br /&gt;
*Update of CTK: Build system, CTK Python console and [https://github.com/commontk/CTK/blob/master/CMake/ctkWrapPythonQt.py ctkWrapPythonQt.py] - '''DONE''' {{done}}&lt;br /&gt;
*Update [https://github.com/Slicer/Slicer/blob/master/SuperBuild/External_python.cmake External_python.cmake] - '''DONE''' {{done}}&lt;br /&gt;
*Update of &amp;quot;C++ to python bridge&amp;quot; classes ([https://github.com/Slicer/Slicer/blob/master/Base/QTCore/qSlicerScriptedUtils_p.h qSlicerScriptedUtils_p.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTGUI/qSlicerScriptedLoadableModule.h qSlicerScriptedLoadableModule.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTGUI/qSlicerScriptedFileDialog.h qSlicerScriptedFileDialog.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTGUI/qSlicerScriptedLoadableModuleWidget.h qSlicerScriptedLoadableModuleWidget.h], [https://github.com/Slicer/Slicer/blob/master/Base/QTCore/qSlicerScriptedFileWriter.h qSlicerScriptedFileWriter.h], ...) - '''DONE''' {{done}}&lt;br /&gt;
*Update of install rules and macos fixup - '''DONE''' {{done}}&lt;br /&gt;
*Update of python scripts to be compliant with python 3 - '''DONE''' {{done}}&lt;br /&gt;
&lt;br /&gt;
Some of the issues discovered after integration of Python 3:&lt;br /&gt;
&lt;br /&gt;
*Fix iomodule.c build error with VS2017. See https://github.com/Slicer/Slicer/pull/1118#issuecomment-482436689. Fixed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=28138 r28138] - '''DONE''' {{done}}&lt;br /&gt;
*Fix crash in Debug build. See https://github.com/lassoan/Slicer/tree/python-startup-hang-in-debug-mode. Fixed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=28141 r28141] - '''DONE''' {{done}}&lt;br /&gt;
*&amp;lt;tt&amp;gt;restart()&amp;lt;/tt&amp;gt; Python function does not work. Fixed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=28143 r28143] - '''DONE''' {{done}}&lt;br /&gt;
&lt;br /&gt;
References:&lt;br /&gt;
&lt;br /&gt;
*discourse post: https://discourse.slicer.org/t/updating-slicer-to-work-with-python-3/4662/14&lt;br /&gt;
*GitHub PR: https://github.com/Slicer/Slicer/pull/1118&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Revisit MRML Copy API====&lt;br /&gt;
&lt;br /&gt;
Copy method does not perform complete deep-copy in some classes. For Sequences, we need both DeepCopy (for node modifications) and ShallowCopy (for fast replay possible).&lt;br /&gt;
&lt;br /&gt;
There are also too many variants of node copy methods, which makes it difficult to use them correctly.&lt;br /&gt;
&lt;br /&gt;
See also https://issues.slicer.org/view.php?id=2608.&lt;br /&gt;
&lt;br /&gt;
====Coordinate system in files====&lt;br /&gt;
&lt;br /&gt;
To be consistent with the rest of the world: Save models and markups in LPS coordinate system by default. If no coordinate system is specified in input file, assume LPS.&lt;br /&gt;
&lt;br /&gt;
====Acquisition transform====&lt;br /&gt;
&lt;br /&gt;
Enable acquisition transform by default, to show correct loading of tilted gantry images. It has proven to work well.  See https://github.com/Slicer/Slicer/commit/b7650af3c27f34fc894bfdd587f2a4c02ba62a8b&lt;br /&gt;
&lt;br /&gt;
====Model Hierarchies====&lt;br /&gt;
&lt;br /&gt;
Remove Model Hierarchy feature and make sure that Subject Hierarchy covers all use cases.  This will impact ModelMaker, which should be converted to a simpler version that only returns models and not semantics.  Need to check extensions, especially SlicerDMRI, for any dependencies on Model Hierarchy. - '''DONE''' {{done}}&lt;br /&gt;
&lt;br /&gt;
==== Extension description file format ====&lt;br /&gt;
&lt;br /&gt;
Transition from [[Documentation/Nightly/Developers/Extensions/DescriptionFile|`.s4ext` text file]] to a json or yaml.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Slicer 5.2: Backward incompatible changes===&lt;br /&gt;
&lt;br /&gt;
====Build System Simplification====&lt;br /&gt;
&lt;br /&gt;
*Pick the most recent reasonable CMake version and remove any complexities in the build system are only there to work around limitations of old CMake versions.&lt;br /&gt;
&lt;br /&gt;
*Consider any ways to streamline/simplify the configure and build process, even it if may require changing extensions.&lt;br /&gt;
&lt;br /&gt;
*Look for ways to minimize the effect of long directory path-related build issues.  Currently on mac and windows we are pushing the limit of path length unless very short paths are used (e.g. /s5 or d:\s5).  Reorganizing the build tree might give us more headroom.&lt;br /&gt;
&lt;br /&gt;
====Remove remote data support from MRML====&lt;br /&gt;
&lt;br /&gt;
MRML theoretically supports downloading files through http, but this feature has not seen much use. This will not likely to change in the future because there is a wide range of data access and authentication protocols, which would not be practical at MRML level.&lt;br /&gt;
&lt;br /&gt;
It would be better to remove remote data support from MRML to simplify data storage. We can keep useful utility classes, such as cache manager for keeping track of local temporary files (downloaded using SampleData or other modules that download significant amount of temporary data).&lt;br /&gt;
&lt;br /&gt;
See also https://discourse.slicer.org/t/improving-testing-data-management-for-self-test/5014/4.&lt;br /&gt;
&lt;br /&gt;
====Improve layout manager====&lt;br /&gt;
&lt;br /&gt;
*Support multiple displays: Currently, it is very hard to leverage multiple displays (need to stretch the Slicer window over multiple screens and align splitter manually to the screen boundary). Allow defining single-display and multi-display layouts. Single-display layouts could be selected for each display independently, while multi-monitor layouts would set views on several displays at once. Keeping a single layout manager (and enhance it with to allow creation of multiple widgets) would make it easier to maintain backward compatibility for existing modules.&lt;br /&gt;
*View layout IDs: View layout IDs are currently integer values, which makes it difficult to ensure that modules always choose unique IDs. We should switch to using string IDs. String IDs can may be prefixed with modulename+&amp;quot;.&amp;quot; as we do it for singleton tags and node attributes. We may remain somewhat backward compatible by having SetLayoutID(int) method that maps known layout integer IDs to the new string IDs. See discussion here: https://github.com/Slicer/Slicer/pull/1061#discussion_r241825827&lt;br /&gt;
&lt;br /&gt;
====SceneViews====&lt;br /&gt;
&lt;br /&gt;
The scene views feature does not work well for a long time now, and there is no consensus about what should be the scope it supports.&lt;br /&gt;
&lt;br /&gt;
Suggestion:&lt;br /&gt;
&lt;br /&gt;
*Do not save the state of all nodes: Support only display, view and hierarchy nodes.&lt;br /&gt;
*Make SceneViews as stable as possible for these cases and remove support for data notes etc.&lt;br /&gt;
*If a node is removed, update associated scene views&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
*2018-12-13: Jc: Following discussion with Ron, we should keep the SceneView functionality. All data should be associated with the &amp;quot;master&amp;quot; view, and scene view should be different combination of viewing parameters (layout, camera, visibility, etc ...). A mrb to consider for testing is the [http://slicer.kitware.com/midas3/slicerdatastore/view?itemId=126553&amp;amp;layout=layout LungSegments_scene.mrb]&lt;br /&gt;
*Another suggestion from Sonia is that SceneViews could be read-only for certain classes of nodes.  It's not clear how that would be implemented, but it could address the instability problems while enabling the use of SceneViews for training.&lt;br /&gt;
&lt;br /&gt;
====Undo/Redo====&lt;br /&gt;
Similarly to SceneViews, it is a great feature but in time it started breaking.&lt;br /&gt;
Need to decide if we want to keep it, and if yes fix it.&lt;br /&gt;
&lt;br /&gt;
Potential fix (currently being tested by Kyle Sunderland and Andras Lasso): Add an &amp;quot;undo enabled&amp;quot; flag to vtkMRMLNode, disable it by default, only enable it for nodes that undo/redo has tested to work correctly. Preliminary tests show that the feature largely works, but there are complications with undo/redo of node add/remove actions and node references.&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
*2018-12-13: Jc: Following discussion with Ron, would be nice to also have undo/redo for camera settings, field of view, etc ... within a given view. It is easy to inadvertently modify settings ... (e.g when trying to pan using a trackpad with shift+left click but inadvertently using only left click)&lt;br /&gt;
&lt;br /&gt;
====Removal of Charts based infrastructure====&lt;br /&gt;
&lt;br /&gt;
With Slicer 5.0, the idea is to remove the [[Documentation/Nightly/Developers/Charts|Charts]] infrastructure based on jqPlot, and only keep&lt;br /&gt;
the [[Documentation/Nightly/Developers/Plots|Plots]] infrastructure based on VTK Charts.&lt;br /&gt;
&lt;br /&gt;
Ron's request: enable anti-aliasing (MSAA or FXAA) and use less subtle default colors (https://www.slicer.org/wiki/Slicer4:2012_GenericChartColors) to improve appearance.&lt;br /&gt;
&lt;br /&gt;
===Remove deprecated modules and/or Migrate to extension===&lt;br /&gt;
&lt;br /&gt;
====Editor====&lt;br /&gt;
The module already directs users to Segment Editor, which provides all the functionality of Editor and more, and&lt;br /&gt;
is the successor module that will be improved and maintained. Removing it would decrease confusion of both old&lt;br /&gt;
and new Slicer users&lt;br /&gt;
&lt;br /&gt;
*Potentially the hack about modules with names ending with the string &amp;quot;Lib&amp;quot; can also be removed after the Editor module will not require it. It is [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Base/QTCore/qSlicerUtils.cxx?r1=26891&amp;amp;r2=26890&amp;amp;pathrev=26891 around here].&lt;br /&gt;
&lt;br /&gt;
*'''Make Editor hidden in 4.10, advertise its removal (some extensions still use it), then remove it in 5.0'''. Remove it from toolbar, move Editor to legacy category in 4.10&lt;br /&gt;
&lt;br /&gt;
*Investigate if the module could easily be moved to an extension&lt;br /&gt;
&lt;br /&gt;
====VectorToScalarVolume====&lt;br /&gt;
&lt;br /&gt;
The plan would be to improve the Volume module so that vector volume could be converted to scalar volume, similarly to scalar to labelmap conversion option. Then, this module could be removed.&lt;br /&gt;
&lt;br /&gt;
====Unused module code====&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;s&amp;gt;MultiVolumeRendering: A [https://github.com/Slicer/Slicer/tree/master/Modules/Loadable/MultiVolumeRendering module] that was effectively not developed since 2012, and is not currently compiled with Slicer.&amp;lt;/s&amp;gt; - Removed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27087 r27087]&lt;br /&gt;
*&amp;lt;s&amp;gt;Measurements: Same argument as MultiVolumeRendering&amp;lt;/s&amp;gt; - Removed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27087 r27087]&lt;br /&gt;
*&amp;lt;s&amp;gt;AtlasCreator Loadable module logic&amp;lt;/s&amp;gt; - Removed in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27088 r27088]&lt;br /&gt;
&lt;br /&gt;
====CLI modules====&lt;br /&gt;
&lt;br /&gt;
*Model to Label Map: Has too many limitations and bugs (cannot handle concave structures, can cause Slicer to hang or crash, etc.), and is not maintained any more. It might be better to remove it than to fix it, especially that there is an algorithm for the same thing in Slicer that works much better&lt;br /&gt;
**The model node to labelmap node conversion feature could be added as a subject hierarchy plugin, if the route via segmentation node is not convenient enough&lt;br /&gt;
&lt;br /&gt;
*Review CLI modules&lt;br /&gt;
**BlobDetection&lt;br /&gt;
**ConnectedComponent&lt;br /&gt;
**GrayscaleModelMaker, ModelMaker: The modules are too different to combine them. Each have specific use cases.&lt;br /&gt;
**DiffusionTensorTest, ROITest, TestGridTransformRegistration: Already excluded from package by specifying &amp;lt;tt&amp;gt;NO_INSTALL&amp;lt;/tt&amp;gt;&lt;br /&gt;
**Resample Scalar Volume: Resample Scalar/Vector/DWI Volume module (which Crop Volume uses as well) can do everything it does already, except for four extra interpolation options. Probably can be removed&lt;br /&gt;
&lt;br /&gt;
====Migrate to extension====&lt;br /&gt;
&lt;br /&gt;
Existing [https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/DMRIInstall/DMRIInstall.py DMRIInstall] scripted module will be re-factored and moved into a &amp;lt;tt&amp;gt;Modules/Scripted/InstallSuggestions&amp;lt;/tt&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Then, after transitioning them to extension, the following module will be added to the &amp;quot;InstallSuggestions&amp;quot; so that the user knows how to install them:&lt;br /&gt;
&lt;br /&gt;
*BRAINSTools (also add SlicerElastix to the suggestions)&lt;br /&gt;
*SimpleITK: Only used in the editor&lt;br /&gt;
*EMSegment: already disabled in Slicer-4.10, so it may be completely removed from build scripts instead of moving it to an extension&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
*2018-12-13: Jc: Following discussion with Ron, we need to make sure to have at least one non-rigid registration method and one ICP based method (e.g Landmark Registration) available in the main distribution.&lt;br /&gt;
&lt;br /&gt;
====PETStandardUptakeValueComputation====&lt;br /&gt;
&lt;br /&gt;
Remove PETStandardUptakeValueComputation from Slicer core, as a more advanced version of this is available in an extension: https://github.com/QIICR/Slicer-PETDICOMExtension. See details here: https://github.com/Slicer/Slicer/pull/1068#issuecomment-450905887&lt;br /&gt;
&lt;br /&gt;
===Coding Style===&lt;br /&gt;
&lt;br /&gt;
====Slicer 5.0: Indentation of curly braces====&lt;br /&gt;
In Slicer the curly braces have a two-space indentation everywhere within functions. As this was inherited from VTK, but VTK changed its convention to align the braces with the statements (if etc.), it could make sense to make the change in Slicer too. This is considered a major change because it affects almost all cxx files.&lt;br /&gt;
&lt;br /&gt;
====Simpler VTK smart pointer usage====&lt;br /&gt;
Use &amp;lt;code&amp;gt;vtkNew&amp;lt;type&amp;gt; var;&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;vtkSmartPointer&amp;lt;type&amp;gt; var = vtkSmartPointer&amp;lt;type&amp;gt;::New();&amp;lt;/code&amp;gt; and remove now unnecessary &amp;lt;code&amp;gt;.GetPointer()&amp;lt;/code&amp;gt; calls.&lt;br /&gt;
&lt;br /&gt;
===Usability===&lt;br /&gt;
&lt;br /&gt;
====Volume Rendering Activation Method====&lt;br /&gt;
&lt;br /&gt;
We have had lots of issues with people finding the eye icon.&lt;br /&gt;
&lt;br /&gt;
===Miscellaneous===&lt;br /&gt;
&lt;br /&gt;
====Tcl codes====&lt;br /&gt;
&amp;lt;s&amp;gt;Most of the TCL code seems to be a heritage from Slicer3. Can they be removed?&amp;lt;/s&amp;gt; - Done in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&amp;amp;revision=27091 r27091]&lt;br /&gt;
&lt;br /&gt;
====Remove self-test modules from the All modules list====&lt;br /&gt;
Users already find the all modules list very long, and as the self tests are for developers only (and can be found in the modules list under the Testing category), they could be removed from the list.  Make sure they are available in Developer mode.&lt;br /&gt;
&lt;br /&gt;
====Remove BTX/ETX pairs====&lt;br /&gt;
Once VTK7 is no longer supported, the old way for disabling python wrapping is no longer needed. According to my tests (Csaba), wrapping works fine in all of those cases, so the new way (#ifndef __VTK_WRAP__) is not needed either.&lt;br /&gt;
&lt;br /&gt;
==Additional proposed changes to be discussed==&lt;br /&gt;
&lt;br /&gt;
*Bundle IPython package in Slicer installer - Slicer Jupyter extension has been added, do we need more?&lt;br /&gt;
**Do we want history across sessions?&lt;br /&gt;
**Quick access to script repository&lt;br /&gt;
*[https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Install using brew]&lt;br /&gt;
*Add opt-in collection of usage statistics for various features (e.g. could be triggered when a module is entered).&lt;br /&gt;
*Enable geometry correction by default (e.g. gantry tilt as [https://discourse.slicer.org/t/actual-size-of-stl-models/5005/21 discussed here]).&lt;br /&gt;
*Remove legacy 1.0 pydicom and only bundle latest (see https://pydicom.github.io/pydicom/stable/transition_to_pydicom1.html#).  Import name changed from 'dicom' to 'pydicom' (See also: https://github.com/Slicer/Slicer/pull/1231)&lt;br /&gt;
*Remove DICOM Networking (DIMSE) code https://discourse.slicer.org/t/dicom-retrieve-on-windows-10-there-is-no-service-listening-dicom-communications-no-telnet-connection-to-ports&lt;br /&gt;
*Update the logo along [https://discourse.slicer.org/t/slicer-module-panel-icon-in-dark-mode/8353/3 as discussed here].&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=62768</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=62768"/>
		<updated>2019-12-09T14:43:01Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Use whitelist to customize view menu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=  &lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the[[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
&lt;br /&gt;
*[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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
*[https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
&lt;br /&gt;
*Capture the full Slicer screen and save it into a file&lt;br /&gt;
&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
&lt;br /&gt;
*Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
*Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
&lt;br /&gt;
*How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loadedVolumeNode = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Automatically load volumes that are copied into a folder==&lt;br /&gt;
&lt;br /&gt;
This example shows how to implement a simple background task by using a timer. The background task is to check for any new volume files in folder and if there is any then automatically load it.&lt;br /&gt;
&lt;br /&gt;
There are more efficient methods for file system monitoring or exchanging image data in real-time (for example, using OpenIGTLink), the example below is just for demonstration purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
incomingVolumeFolder = &amp;quot;c:/tmp/incoming&amp;quot;&lt;br /&gt;
incomingVolumesProcessed = []&lt;br /&gt;
&lt;br /&gt;
def checkForNewVolumes():&lt;br /&gt;
  # Check if there is a new file in the &lt;br /&gt;
  from os import listdir&lt;br /&gt;
  from os.path import isfile, join&lt;br /&gt;
  for f in listdir(incomingVolumeFolder):&lt;br /&gt;
    if f in incomingVolumesProcessed:&lt;br /&gt;
      # this is an incoming file, it was already there&lt;br /&gt;
      continue&lt;br /&gt;
    filePath = join(incomingVolumeFolder, f)&lt;br /&gt;
    if not isfile(filePath):&lt;br /&gt;
      # ignore directories&lt;br /&gt;
      continue&lt;br /&gt;
    logging.info(&amp;quot;Loading new file: &amp;quot;+f)&lt;br /&gt;
    incomingVolumesProcessed.append(f)&lt;br /&gt;
    slicer.util.loadVolume(filePath)&lt;br /&gt;
  # Check again in 3000ms&lt;br /&gt;
  qt.QTimer.singleShot(3000, checkForNewVolumes)&lt;br /&gt;
&lt;br /&gt;
# Start monitoring&lt;br /&gt;
checkForNewVolumes()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
===How to access top level tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # Note, fileValue accesses the database of cached top level tags&lt;br /&gt;
  # (nested tags are not included)&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
===How to access DICOM tags nested in a sequence===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # use pydicom to access the full header, which requires&lt;br /&gt;
  # re-reading the dataset instead of using the database cache&lt;br /&gt;
  import pydicom&lt;br /&gt;
  pydicom.dcmread(fileList[0])&lt;br /&gt;
  ds.CTExposureSequence[0].ExposureModulationType&lt;br /&gt;
&lt;br /&gt;
===How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
===How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
===How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
===How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm'); slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
===Export a volume to DICOM file format===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Customize table columns in DICOM browser===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database() # Need to go this way, do not use slicer.dicomDatabase for this&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
&lt;br /&gt;
*How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
for viewNode in viewNodes:&lt;br /&gt;
  viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
&lt;br /&gt;
*How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two slice planes==&lt;br /&gt;
&lt;br /&gt;
Measure angle between red and yellow slice nodes. Whenever any of the slice nodes are moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeIds = ['vtkMRMLSliceNodeRed', 'vtkMRMLSliceNodeYellow']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    sliceNormalVector = []&lt;br /&gt;
    for sliceNodeId in sliceNodeIds:&lt;br /&gt;
        sliceToRAS = slicer.mrmlScene.GetNodeByID(sliceNodeId).GetSliceToRAS()&lt;br /&gt;
        sliceNormalVector.append([sliceToRAS.GetElement(0,2), sliceToRAS.GetElement(1,2), sliceToRAS.GetElement(2,2)])&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(sliceNormalVector[0], sliceNormalVector[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between slice planes = {0:0.3f}'.format(angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe slice node changes&lt;br /&gt;
for sliceNodeId in sliceNodeIds:&lt;br /&gt;
    slicer.mrmlScene.GetNodeByID(sliceNodeId).AddObserver(vtk.vtkCommand.ModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from a normal vector and position==&lt;br /&gt;
&lt;br /&gt;
This code snippet shows how to display a slice view defined by a normal vector and position in an anatomically sensible way: rotating slice view so that &amp;quot;up&amp;quot; direction (or &amp;quot;right&amp;quot; direction) is towards an anatomical axis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition, defaultViewUpDirection=None, backupViewRightDirection=None):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Set slice pose from the provided plane normal and position. View up direction is determined automatically,&lt;br /&gt;
    to make view up point towards defaultViewUpDirection.&lt;br /&gt;
    :param defaultViewUpDirection Slice view will be spinned in-plane to match point approximately this up direction. Default: patient superior.&lt;br /&gt;
    :param backupViewRightDirection Slice view will be spinned in-plane to match point approximately this right direction&lt;br /&gt;
        if defaultViewUpDirection is too similar to sliceNormal. Default: patient left.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Fix up input directions&lt;br /&gt;
    if defaultViewUpDirection is None:&lt;br /&gt;
        defaultViewUpDirection = [0,0,1]&lt;br /&gt;
    if backupViewRightDirection is None:&lt;br /&gt;
        backupViewRightDirection = [-1,0,0]&lt;br /&gt;
    if sliceNormal[1]&amp;gt;=0:&lt;br /&gt;
        sliceNormalStandardized = sliceNormal&lt;br /&gt;
    else:&lt;br /&gt;
        sliceNormalStandardized = [-sliceNormal[0], -sliceNormal[1], -sliceNormal[2]]&lt;br /&gt;
    # Compute slice axes&lt;br /&gt;
    sliceNormalViewUpAngle = vtk.vtkMath.AngleBetweenVectors(sliceNormalStandardized, defaultViewUpDirection)&lt;br /&gt;
    angleTooSmallThresholdRad = 0.25 # about 15 degrees&lt;br /&gt;
    if sliceNormalViewUpAngle &amp;gt; angleTooSmallThresholdRad and sliceNormalViewUpAngle &amp;lt; vtk.vtkMath.Pi() - angleTooSmallThresholdRad:&lt;br /&gt;
        viewUpDirection = defaultViewUpDirection&lt;br /&gt;
        sliceAxisY = viewUpDirection&lt;br /&gt;
        sliceAxisX = [0, 0, 0]&lt;br /&gt;
        vtk.vtkMath.Cross(sliceAxisY, sliceNormalStandardized, sliceAxisX)&lt;br /&gt;
    else:&lt;br /&gt;
        sliceAxisX = backupViewRightDirection&lt;br /&gt;
    # Set slice axes&lt;br /&gt;
    sliceNode.SetSliceToRASByNTP(sliceNormalStandardized[0], sliceNormalStandardized[1], sliceNormalStandardized[2],&lt;br /&gt;
        sliceAxisX[0], sliceAxisX[1], sliceAxisX[2],&lt;br /&gt;
        slicePosition[0], slicePosition[1], slicePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Example usage:&lt;br /&gt;
sliceNode = getNode('vtkMRMLSliceNodeRed')&lt;br /&gt;
transformNode = getNode('Transform_3')&lt;br /&gt;
transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
transformNode.GetMatrixTransformToParent(transformMatrix)&lt;br /&gt;
sliceNormal = [transformMatrix.GetElement(0,2), transformMatrix.GetElement(1,2), transformMatrix.GetElement(2,2)]&lt;br /&gt;
slicePosition = [transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)]&lt;br /&gt;
setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Switching to markup fiducial placement mode==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change markup fiducial display properties==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get a notification if a markup point position is modified==&lt;br /&gt;
&lt;br /&gt;
Event management of Slicer-4.11 version is still subject to change. The example below shows how point manipulation can be observed now.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupChanged(caller,event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    if movingMarkupIndex &amp;gt;= 0:&lt;br /&gt;
        pos = [0,0,0]&lt;br /&gt;
        markupsNode.GetNthFiducialPosition(movingMarkupIndex, pos)&lt;br /&gt;
        isPreview = markupsNode.GetNthControlPointPositionStatus(movingMarkupIndex) == slicer.vtkMRMLMarkupsNode.PositionPreview&lt;br /&gt;
        if isPreview:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} is previewed at {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
        else:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} was moved {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
    else:&lt;br /&gt;
        logging.info(&amp;quot;Points modified: slice view = {0}&amp;quot;.format(sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupStartInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()    &lt;br /&gt;
    logging.info(&amp;quot;Start interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupEndInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    logging.info(&amp;quot;End interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, onMarkupChanged)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointStartInteractionEvent, onMarkupStartInteraction)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointEndInteractionEvent, onMarkupEndInteraction)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get a notification if a transform is modified==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate a node around a specified point==&lt;br /&gt;
&lt;br /&gt;
Set up the scene:&lt;br /&gt;
* Add a markup fiducial node (centerOfRotationMarkupsNode) with a single point to specify center of rotation.&lt;br /&gt;
* Add a rotation transform (rotationTransformNode) that will be edited in Transforms module to specify rotation angles.&lt;br /&gt;
* Add a transform (finalTransformNode) and apply it (not harden) to those nodes (images, models, etc.) that you want to rotate around the center of rotation point.&lt;br /&gt;
&lt;br /&gt;
Then run the script below, go to Transforms module, select rotationTransformNode, and move rotation sliders.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# This markups fiducial node specifies the center of rotation&lt;br /&gt;
centerOfRotationMarkupsNode = getNode('F')&lt;br /&gt;
# This transform can be  edited in Transforms module&lt;br /&gt;
rotationTransformNode = getNode('LinearTransform_3')&lt;br /&gt;
# This transform has to be applied to the image, model, etc.&lt;br /&gt;
finalTransformNode = getNode('LinearTransform_4')&lt;br /&gt;
&lt;br /&gt;
def updateFinalTransform(unusedArg1=None, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
    rotationMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
    rotationTransformNode.GetMatrixTransformToParent(rotationMatrix)&lt;br /&gt;
    rotationCenterPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
    centerOfRotationMarkupsNode.GetNthControlPointPositionWorld(0, rotationCenterPointCoord)&lt;br /&gt;
    finalTransform = vtk.vtkTransform()&lt;br /&gt;
    finalTransform.Translate(rotationCenterPointCoord)&lt;br /&gt;
    finalTransform.Concatenate(rotationMatrix)&lt;br /&gt;
    finalTransform.Translate(-rotationCenterPointCoord[0], -rotationCenterPointCoord[1], -rotationCenterPointCoord[2])&lt;br /&gt;
    finalTransformNode.SetAndObserveMatrixTransformToParent(finalTransform.GetMatrix())&lt;br /&gt;
&lt;br /&gt;
# Manual initial update&lt;br /&gt;
updateFinalTransform()&lt;br /&gt;
&lt;br /&gt;
# Automatic update when point is moved or transform is modified&lt;br /&gt;
rotationTransformNodeObserver = rotationTransformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, updateFinalTransform)&lt;br /&gt;
centerOfRotationMarkupsNodeObserver = centerOfRotationMarkupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, updateFinalTransform)&lt;br /&gt;
&lt;br /&gt;
# Execute these lines to stop automatic updates:&lt;br /&gt;
# rotationTransformNode.RemoveObserver(rotationTransformNodeObserver)&lt;br /&gt;
# centerOfRotationMarkupsNode.RemoveObserver(centerOfRotationMarkupsNodeObserver)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a context menu when a markup point is clicked in a slice or 3D view==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Example actions to perform&lt;br /&gt;
&lt;br /&gt;
def action1():&lt;br /&gt;
  print('Action1 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action2():&lt;br /&gt;
  print('Action2 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action3():&lt;br /&gt;
  print('Action3 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
# Clicked markup index is saved here to let the action&lt;br /&gt;
# know which markup needs to be manipulated.&lt;br /&gt;
slicer.clickedMarkupIndex = -1&lt;br /&gt;
  &lt;br /&gt;
# Create a simple menu&lt;br /&gt;
&lt;br /&gt;
menu = qt.QMenu()&lt;br /&gt;
a1 = qt.QAction(&amp;quot;Test&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a1.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a1)&lt;br /&gt;
a2 = qt.QAction(&amp;quot;Action&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a2.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a2)&lt;br /&gt;
a3 = qt.QAction(&amp;quot;Here&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a3.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a3)&lt;br /&gt;
&lt;br /&gt;
# Add observer to a markup fiducial list&lt;br /&gt;
&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_INT)&lt;br /&gt;
def markupClickedCallback(caller, eventId, callData):&lt;br /&gt;
  slicer.clickedMarkupIndex = callData&lt;br /&gt;
  print('Open menu on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
  menu.move(qt.QCursor.pos())&lt;br /&gt;
  menu.show()&lt;br /&gt;
&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
observerTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointClickedEvent, markupClickedCallback)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Write markup positions to JSON file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Write annotation ROI to JSON file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a simple surface mesh as a model node==&lt;br /&gt;
&lt;br /&gt;
This example shows how to display a simple surface mesh (a box, created by a VTK source filter) as a model node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create and set up polydata source&lt;br /&gt;
box = vtk.vtkCubeSource()&lt;br /&gt;
box.SetXLength(30)&lt;br /&gt;
box.SetYLength(20)&lt;br /&gt;
box.SetZLength(15)&lt;br /&gt;
box.SetCenter(10,20,5)&lt;br /&gt;
&lt;br /&gt;
# Create a model node that displays output of the source&lt;br /&gt;
boxNode = slicer.modules.models.logic().AddModel(box.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Adjust display properties&lt;br /&gt;
boxNode.GetDisplayNode().SetColor(1,0,0)&lt;br /&gt;
boxNode.GetDisplayNode().SetOpacity(0.8)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Add a texture mapped plane to the scene as a model==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# use dummy image data here&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
&lt;br /&gt;
scene = slicer.mrmlScene&lt;br /&gt;
&lt;br /&gt;
# Create model node&lt;br /&gt;
model = slicer.vtkMRMLModelNode()&lt;br /&gt;
model.SetScene(scene)&lt;br /&gt;
model.SetName(scene.GenerateUniqueName(&amp;quot;2DImageModel&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
model.SetAndObservePolyData(planeSource.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create display node&lt;br /&gt;
modelDisplay = slicer.vtkMRMLModelDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
modelDisplay.SetScene(scene)&lt;br /&gt;
scene.AddNode(modelDisplay)&lt;br /&gt;
model.SetAndObserveDisplayNodeID(modelDisplay.GetID())&lt;br /&gt;
&lt;br /&gt;
# Add to scene&lt;br /&gt;
modelDisplay.SetAndObserveTextureImageData(e.GetOutput())&lt;br /&gt;
scene.AddNode(model) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
transform = slicer.vtkMRMLLinearTransformNode()&lt;br /&gt;
scene.AddNode(transform) &lt;br /&gt;
model.SetAndObserveTransformNodeID(transform.GetID())&lt;br /&gt;
&lt;br /&gt;
vTransform = vtk.vtkTransform()&lt;br /&gt;
vTransform.Scale(50,50,50)&lt;br /&gt;
vTransform.RotateX(30)&lt;br /&gt;
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get scalar values at surface of a model==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Select cells of a using markups fiducial points==&lt;br /&gt;
&lt;br /&gt;
The following script selects cells of a model node that are closest to positions of markups fiducial points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get input nodes&lt;br /&gt;
modelNode = slicer.util.getNode('Segment_1') # select cells in this model&lt;br /&gt;
markupsNode = slicer.util.getNode('F') # points will be selected at positions specified by this markups fiducial node&lt;br /&gt;
&lt;br /&gt;
# Create scalar array that will store selection state&lt;br /&gt;
cellScalars = modelNode.GetMesh().GetCellData()&lt;br /&gt;
selectionArray = cellScalars.GetArray('selection')&lt;br /&gt;
if not selectionArray:&lt;br /&gt;
    selectionArray = vtk.vtkIntArray()&lt;br /&gt;
    selectionArray.SetName('selection')&lt;br /&gt;
    selectionArray.SetNumberOfValues(modelNode.GetMesh().GetNumberOfCells())&lt;br /&gt;
    selectionArray.Fill(0)&lt;br /&gt;
    cellScalars.AddArray(selectionArray)&lt;br /&gt;
&lt;br /&gt;
# Set up coloring by selection array&lt;br /&gt;
modelNode.GetDisplayNode().SetActiveScalar(&amp;quot;selection&amp;quot;, vtk.vtkAssignAttribute.CELL_DATA)&lt;br /&gt;
modelNode.GetDisplayNode().SetAndObserveColorNodeID(&amp;quot;vtkMRMLColorTableNodeWarm1&amp;quot;)&lt;br /&gt;
modelNode.GetDisplayNode().SetScalarVisibility(True)&lt;br /&gt;
&lt;br /&gt;
# Initialize cell locator&lt;br /&gt;
cell = vtk.vtkCellLocator()&lt;br /&gt;
cell.SetDataSet(modelNode.GetMesh())&lt;br /&gt;
cell.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onPointsModified(observer=None, eventid=None):&lt;br /&gt;
    global markupsNode, selectionArray&lt;br /&gt;
    selectionArray.Fill(0) # set all cells to non-selected by default&lt;br /&gt;
    markupPoints = slicer.util.arrayFromMarkupsControlPoints(markupsNode)&lt;br /&gt;
    closestPoint = [0.0, 0.0, 0.0]&lt;br /&gt;
    cellObj = vtk.vtkGenericCell()&lt;br /&gt;
    cellId = vtk.mutable(0)&lt;br /&gt;
    subId = vtk.mutable(0)&lt;br /&gt;
    dist2 = vtk.mutable(0.0)&lt;br /&gt;
    for markupPoint in markupPoints:&lt;br /&gt;
        cell.FindClosestPoint(markupPoint, closestPoint, cellObj, cellId, subId, dist2)&lt;br /&gt;
        closestCell = cellId.get()&lt;br /&gt;
        if closestCell &amp;gt;=0:&lt;br /&gt;
            selectionArray.SetValue(closestCell, 100) # set selected cell's scalar value to non-zero&lt;br /&gt;
    selectionArray.Modified()&lt;br /&gt;
&lt;br /&gt;
# Initial update&lt;br /&gt;
onPointsModified()&lt;br /&gt;
# Automatic update each time when a markup point is modified&lt;br /&gt;
markupsNodeObserverTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsFiducialNode.PointModifiedEvent, onPointsModified)&lt;br /&gt;
&lt;br /&gt;
# To stop updating selection, run this:&lt;br /&gt;
# markupsNode.RemoveObserver(markupsNodeObserverTag)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export entire scene as VRML==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export model to Blender, including color by scalar==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export a tract (FiberBundle) to Blender, including color==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Iterate over tract (FiberBundle) streamline points==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Clone a node==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Clone a volume==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create a new volume==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
imageData.GetPointData().GetScalars().Fill(fillVoxelValue)&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get value of a volume at specific voxel coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel value of &amp;quot;volumeNode&amp;quot; at &amp;quot;ijk&amp;quot; volume voxel coordinates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
ijk = [20,40,30]  # volume voxel coordinates&lt;br /&gt;
&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)  # get voxels as a numpy array&lt;br /&gt;
voxelValue = voxels[ijk[2], ijk[1], ijk[0]]  # note that numpy array index order is kji (not ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Modify voxels in a volume==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get volume voxel coordinates from markup fiducial RAS coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get markup fiducial RAS coordinates from volume voxel coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get the values of all voxels for a label value==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Access values in a DTI tensor volume==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change window/level (brightness/contrast) or colormap of a volume==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Make mouse left-click and drag on the image adjust window/level==&lt;br /&gt;
&lt;br /&gt;
In older Slicer versions, by default, left-click and drag in a slice view adjusted window/level of the displayed image. Window/level adjustment is now a new mouse mode that can be activated by clicking on its toolbar button or running this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.applicationLogic().GetInteractionNode().SetCurrentInteractionMode(slicer.vtkMRMLInteractionNode.AdjustWindowLevel)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create custom color table==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manipulate a Slice View==&lt;br /&gt;
&lt;br /&gt;
===Change slice offset===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Change slice orientation===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Show slice views in 3D window===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Reset field of view to show background volume maximized===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rotate slice views to volume plane===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Iterate over current visible slice views, and set foreground and background images===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     compositeNode = layoutManager.sliceWidget(sliceViewName).sliceLogic().GetSliceCompositeNode()&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a volume in slice views==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change opacity of foreground volume in slice views==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Fit slice plane to markup fiducials==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.array([0,0,0])&lt;br /&gt;
p2 = np.array([0,0,0])&lt;br /&gt;
p3 = np.array([0,0,0])&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0, 0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save a series of images from a Slice View==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rasterize a model and save it to a series of image files==&lt;br /&gt;
&lt;br /&gt;
This example shows how to generate a stack of image files from an STL file:&lt;br /&gt;
&lt;br /&gt;
 inputModelFile = &amp;quot;/some/input/folder/SomeShape.stl&amp;quot;&lt;br /&gt;
 outputDir = &amp;quot;/some/output/folder&amp;quot;&lt;br /&gt;
 outputVolumeLabelValue = 100&lt;br /&gt;
 outputVolumeSpacingMm = [0.5, 0.5, 0.5]&lt;br /&gt;
 outputVolumeMarginMm = [10.0, 10.0, 10.0]&lt;br /&gt;
 &lt;br /&gt;
 # Read model&lt;br /&gt;
 inputModel = slicer.util.loadModel(inputModelFile)&lt;br /&gt;
 &lt;br /&gt;
 # Determine output volume geometry and create a corresponding reference volume&lt;br /&gt;
 import math&lt;br /&gt;
 import numpy as np&lt;br /&gt;
 bounds = np.zeros(6)&lt;br /&gt;
 inputModel.GetBounds(bounds)&lt;br /&gt;
 imageData = vtk.vtkImageData()&lt;br /&gt;
 imageSize = [ int((bounds[axis*2+1]-bounds[axis*2]+outputVolumeMarginMm[axis]*2.0)/outputVolumeSpacingMm[axis]) for axis in range(3) ]&lt;br /&gt;
 imageOrigin = [ bounds[axis*2]-outputVolumeMarginMm[axis] for axis in range(3) ]&lt;br /&gt;
 imageData.SetDimensions(imageSize)&lt;br /&gt;
 imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1)&lt;br /&gt;
 imageData.GetPointData().GetScalars().Fill(0)&lt;br /&gt;
 referenceVolumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
 referenceVolumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
 referenceVolumeNode.SetSpacing(outputVolumeSpacingMm)&lt;br /&gt;
 referenceVolumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
 referenceVolumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
 &lt;br /&gt;
 # Convert model to labelmap&lt;br /&gt;
 seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
 seg.SetReferenceImageGeometryParameterFromVolumeNode(referenceVolumeNode)&lt;br /&gt;
 slicer.modules.segmentations.logic().ImportModelToSegmentationNode(inputModel, seg)&lt;br /&gt;
 seg.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
 outputLabelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
 slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(seg, outputLabelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
 outputLabelmapVolumeArray = (slicer.util.arrayFromVolume(outputLabelmapVolumeNode) * outputVolumeLabelValue).astype('int8')&lt;br /&gt;
 &lt;br /&gt;
 # Write labelmap volume to series of TIFF files&lt;br /&gt;
 pip_install(&amp;quot;imageio&amp;quot;)&lt;br /&gt;
 import imageio&lt;br /&gt;
 for i in range(len(outputLabelmapVolumeArray)):&lt;br /&gt;
     imageio.imwrite(f'{outputDir}/image_{i:03}.tiff', outputLabelmapVolumeArray[i])&lt;br /&gt;
&lt;br /&gt;
==Save the scene into a new directory==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save the scene into a single MRB file==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save a node to file==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Center the 3D View on the Scene==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Display text in a 3D view or slice view==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide slice view annotations (DataProbe)==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Turning off interpolation==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Customize viewer layout==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;layout type=&amp;quot;vertical&amp;quot; split=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLSliceNode&amp;quot; singletontag=&amp;quot;Red&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;orientation&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewcolor&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/layout&amp;gt;&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Built-in layout IDs are all below 100, so you can choose any large random number&lt;br /&gt;
# for your custom layout ID.&lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
&lt;br /&gt;
# Switch to the new custom layout &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
You can use this code snippet to add a button to the layout selector toolbar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Add button to layout selector toolbar for this custom layout&lt;br /&gt;
viewToolBar = mainWindow().findChild('QToolBar', 'ViewToolBar')&lt;br /&gt;
layoutMenu = viewToolBar.widgetForAction(viewToolBar.actions()[0]).menu()&lt;br /&gt;
layoutSwitchActionParent = layoutMenu  # use `layoutMenu` to add inside layout list, use `viewToolBar` to add next the standard layout list&lt;br /&gt;
layoutSwitchAction = layoutSwitchActionParent.addAction(&amp;quot;My view&amp;quot;) # add inside layout list&lt;br /&gt;
layoutSwitchAction.setData(layoutId)&lt;br /&gt;
layoutSwitchAction.setIcon(qt.QIcon(':Icons/Go.png'))&lt;br /&gt;
layoutSwitchAction.setToolTip('3D and slice view')&lt;br /&gt;
layoutSwitchAction.connect('triggered()', lambda layoutId = customLayoutId: slicer.app.layoutManager().setLayout(layoutId))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Customize keyboard shortcuts==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Disable certain user interactions in slice views==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change default slice view orientation==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set all slice views linked by default==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set crosshair jump mode to centered by default==&lt;br /&gt;
&lt;br /&gt;
You can change default slice jump mode (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
crosshair=slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLCrosshairNode&amp;quot;)&lt;br /&gt;
crosshair.SetCrosshairBehavior(crosshair.CenteredJumpSlice)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set up custom units in slice view ruler==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in range(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a slice view outside the view layout==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;TS&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
viewNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(layoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
viewWidget.sliceViewName = layoutName&lt;br /&gt;
viewWidget.sliceViewLabel = layoutLabel&lt;br /&gt;
c = viewNode.GetLayoutColor()&lt;br /&gt;
viewWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLSliceNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a 3D view outside the view layout==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;Test3DView&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;T3&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML node&lt;br /&gt;
viewNode = slicer.vtkMRMLViewNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLThreeDWidget()&lt;br /&gt;
viewWidget.viewLabel = layoutLabel&lt;br /&gt;
viewWidget.viewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLViewNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get displayable manager of a certain type for a certain view==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelDisplayableManager = None&lt;br /&gt;
threeDViewWidget = slicer.app.layoutManager().threeDWidget(0)&lt;br /&gt;
managers = vtk.vtkCollection()&lt;br /&gt;
threeDViewWidget.getDisplayableManagers(managers)&lt;br /&gt;
for i in range(managers.GetNumberOfItems()):&lt;br /&gt;
  obj = managers.GetItemAsObject(i)&lt;br /&gt;
  if obj.IsA('vtkMRMLModelDisplayableManager'):&lt;br /&gt;
    modelDisplayableManager = obj&lt;br /&gt;
    break&lt;br /&gt;
if modelDisplayableManager is None:&lt;br /&gt;
  logging.error('Failed to find the model displayable manager')&lt;br /&gt;
  return&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Running an ITK filter in Python using SimpleITK==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
&lt;br /&gt;
*See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
*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&lt;br /&gt;
&lt;br /&gt;
==Get current mouse coordinates in a slice view==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get DataProbe text==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get reformatted image from a slice viewer as numpy array==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print voxels.shape&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Combine multiple volumes into one==&lt;br /&gt;
&lt;br /&gt;
This example combines two volumes into a new one by subtracting one from the other.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
[input1Volume, input2Volume] = SampleData.SampleDataLogic().downloadDentalSurgery()&lt;br /&gt;
&lt;br /&gt;
import slicer.util&lt;br /&gt;
a = slicer.util.arrayFromVolume(input1Volume)&lt;br /&gt;
b = slicer.util.arrayFromVolume(input2Volume)&lt;br /&gt;
&lt;br /&gt;
# 'a' and 'b' are numpy arrays,&lt;br /&gt;
# they can be combined using any numpy array operations&lt;br /&gt;
# to produce the result array 'c'&lt;br /&gt;
c = b-a&lt;br /&gt;
&lt;br /&gt;
volumeNode = slicer.modules.volumes.logic().CloneVolume(input1Volume, &amp;quot;Difference&amp;quot;)&lt;br /&gt;
slicer.util.updateVolumeFromArray(volumeNode, c)&lt;br /&gt;
setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Thick slab reconstruction and maximum/minimum intensity volume projections==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
==Change default file type for nodes (that have never been saved yet)==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
==Change file type for saving for all volumes (with already existing storage nodes)==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Sequences==&lt;br /&gt;
&lt;br /&gt;
===Concatenate all sequences in the scene into a new sequence===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Segmentations==&lt;br /&gt;
&lt;br /&gt;
===Create a segmentation from a labelmap volume and display in 3D===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
===Export labelmap node from segmentation node===&lt;br /&gt;
&lt;br /&gt;
Export smallest possible labelmap:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export labelmap that matches geometry of a chosen reference volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export by pressing Ctrl+Shift+s key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPath = &amp;quot;c:/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def exportLabelmap():&lt;br /&gt;
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLSegmentationNode&amp;quot;)&lt;br /&gt;
    referenceVolumeNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
    labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
    slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
    filepath = outputPath + &amp;quot;/&amp;quot; + referenceVolumeNode.GetName()+&amp;quot;-label.nrrd&amp;quot;&lt;br /&gt;
    slicer.util.saveNode(labelmapVolumeNode, filepath)&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode.GetDisplayNode().GetColorNode())&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
    slicer.util.delayDisplay(&amp;quot;Segmentation saved to &amp;quot;+filepath)&lt;br /&gt;
&lt;br /&gt;
shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
shortcut.setKey(qt.QKeySequence('Ctrl+Shift+s'))&lt;br /&gt;
shortcut.connect( 'activated()', exportLabelmap)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Export model nodes from segmentation node===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
exportedModelsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelHierarchyNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModelHierarchy(seg, exportedModelsNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Show a segmentation in 3D===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get a representation of a segment===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = segmentationNode.GetBinaryLabelmapRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert all segments using default path and conversion parameters===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert all segments using custom path or conversion parameters===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Re-convert using a modified conversion parameter===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get centroid of a segment in world (RAS) coordinates===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to run segment editor effects from a script===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
*[https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
*[https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
*[https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
==Accessing views, renderers, and cameras==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide view controller bars==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Customize widgets in view controller bars==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceController = slicer.app.layoutManager().sliceWidget(&amp;quot;Red&amp;quot;).sliceController()&lt;br /&gt;
&lt;br /&gt;
# hide what is not needed&lt;br /&gt;
sliceController.pinButton().hide()&lt;br /&gt;
#sliceController.viewLabel().hide()&lt;br /&gt;
sliceController.fitToWindowToolButton().hide()&lt;br /&gt;
sliceController.sliceOffsetSlider().hide()&lt;br /&gt;
&lt;br /&gt;
# add custom widgets&lt;br /&gt;
myButton = qt.QPushButton(&amp;quot;My custom button&amp;quot;)&lt;br /&gt;
sliceController.barLayout().addWidget(b)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change 3D view background color==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderer = renderWindow.GetRenderers().GetFirstRenderer()&lt;br /&gt;
renderer.SetBackground(1,0,0)&lt;br /&gt;
renderer.SetBackground2(1,0,0)&lt;br /&gt;
renderWindow.Render()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide Slicer logo from main window (to increase space)==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.findChild(slicer.util.mainWindow(), 'LogoLabel').visible = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subject hierarchy== &lt;br /&gt;
====Get the pseudo-singleton subject hierarchy node====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.mrmlScene.GetSubjectHierarchyNode()&lt;br /&gt;
&lt;br /&gt;
====Create subject hierarchy item====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
====Get subject hierarchy item====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
====Traverse children of a subject hierarchy item====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in range(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
====Manipulate subject hierarchy item====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data node associated to an item&lt;br /&gt;
  shNode.SetItemDisplayVisibility(itemID, 1)&lt;br /&gt;
  # Set visibility of whole branch&lt;br /&gt;
  # Note: Folder-type items (fodler, subject, study, etc.) create their own display nodes when show/hiding from UI.&lt;br /&gt;
  #       The displayable managers use SH information to determine visibility of an item, so no need to show/hide individual leaf nodes any more.&lt;br /&gt;
  #       Once the folder display node is created, it can be shown hidden simply using shNode.SetItemDisplayVisibility&lt;br /&gt;
  # From python, this is how to trigger creating a folder display node&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler().instance()&lt;br /&gt;
  folderPlugin = pluginHandler.pluginByName('Folder')&lt;br /&gt;
  folderPlugin.setDisplayVisibility(folderItemID, 1)&lt;br /&gt;
&lt;br /&gt;
====Filter items in TreeView or ComboBox====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
===Listen to subject hierarchy item events===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
===Use whitelist to customize view menu===&lt;br /&gt;
When right-clicking certain types of nodes in the 2D/3D views, a subject hierarchy menu pops up. If menu actions need to be removed, a whitelist can be used to specify the ones that should show up.&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler.instance()&lt;br /&gt;
  pluginLogic = pluginHandler.pluginLogic()&lt;br /&gt;
  menuActions = pluginLogic.availableViewMenuActionNames()&lt;br /&gt;
  # Returns ('RenamePointAction', 'DeletePointAction', 'ToggleSelectPointAction', 'EditPropertiesAction')&lt;br /&gt;
  newActions = ['RenamePointAction']&lt;br /&gt;
  pluginLogic.setDisplayedViewMenuActionNames(newActions)&lt;br /&gt;
&lt;br /&gt;
==Plotting==&lt;br /&gt;
&lt;br /&gt;
===Slicer plots displayed in view layout===&lt;br /&gt;
&lt;br /&gt;
Create histogram plot of a volume and show it embedded in the view layout. More information: https://www.slicer.org/wiki/Documentation/Nightly/Developers/Plots&lt;br /&gt;
&lt;br /&gt;
====Using &amp;lt;code&amp;gt;slicer.util.plot&amp;lt;/code&amp;gt; utility function====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
chartNode = slicer.util.plot(histogram, xColumnIndex = 1)&lt;br /&gt;
chartNode.SetYAxisRangeAuto(False)&lt;br /&gt;
chartNode.SetYAxisRange(0, 4e5)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:SlicerPlot.png]]&lt;br /&gt;
&lt;br /&gt;
====Using MRML classes only====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using matplotlib===&lt;br /&gt;
&lt;br /&gt;
Matplotlib may be used from within Slicer, but the default Tk backend locks up and crashes Slicer. However, Matplotlib may still be used through other backends. More details can be found on the [http://matplotlib.sourceforge.net/ MatPlotLib] pages.&lt;br /&gt;
&lt;br /&gt;
====Non-interactive plot====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
&lt;br /&gt;
# Static image view&lt;br /&gt;
pm = qt.QPixmap(&amp;quot;MatplotlibExample.png&amp;quot;)&lt;br /&gt;
imageWidget = qt.QLabel()&lt;br /&gt;
imageWidget.setPixmap(pm)&lt;br /&gt;
imageWidget.setScaledContents(True)&lt;br /&gt;
imageWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:MatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
====Plot in Slicer Jupyter notebook====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
display(filename='MatplotlibExample.png', type=&amp;quot;image/png&amp;quot;, binary=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:JupyterNotebookMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
====Interactive plot using wxWidgets GUI toolkit====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
  import wx&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib wxPython')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Set matplotlib to use WXAgg backend&lt;br /&gt;
import matplotlib&lt;br /&gt;
matplotlib.use('WXAgg')&lt;br /&gt;
&lt;br /&gt;
# Show an interactive plot&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
fig, ax = plt.subplots()&lt;br /&gt;
ax.plot(histogram[1][1:], histogram[0].astype(float))&lt;br /&gt;
ax.grid(True)&lt;br /&gt;
ax.set_ylim((0, 4e5))&lt;br /&gt;
plt.show(block=False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:InteractiveMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==Execute external applications==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
===Run process in default environment===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;br /&gt;
&lt;br /&gt;
==Manage extensions==&lt;br /&gt;
&lt;br /&gt;
===Download and install extension===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensionName = 'SlicerIGT'&lt;br /&gt;
em = slicer.app.extensionsManagerModel()&lt;br /&gt;
if not em.isExtensionInstalled(extensionName):&lt;br /&gt;
    extensionMetaData = em.retrieveExtensionMetadataByName(extensionName)&lt;br /&gt;
    url = em.serverUrl().toString()+'/download/item/'+extensionMetaData['item_id']&lt;br /&gt;
    extensionPackageFilename = slicer.app.temporaryPath+'/'+extensionMetaData['md5']&lt;br /&gt;
    slicer.util.downloadFile(url, extensionPackageFilename)&lt;br /&gt;
    em.installExtension(extensionPackageFilename)&lt;br /&gt;
    slicer.util.restart()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=62712</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=62712"/>
		<updated>2019-12-06T15:48:01Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Subject hierarchy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=  &lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the[[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
&lt;br /&gt;
*[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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
*[https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
&lt;br /&gt;
*Capture the full Slicer screen and save it into a file&lt;br /&gt;
&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
&lt;br /&gt;
*Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
*Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
&lt;br /&gt;
*How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loadedVolumeNode = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Automatically load volumes that are copied into a folder==&lt;br /&gt;
&lt;br /&gt;
This example shows how to implement a simple background task by using a timer. The background task is to check for any new volume files in folder and if there is any then automatically load it.&lt;br /&gt;
&lt;br /&gt;
There are more efficient methods for file system monitoring or exchanging image data in real-time (for example, using OpenIGTLink), the example below is just for demonstration purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
incomingVolumeFolder = &amp;quot;c:/tmp/incoming&amp;quot;&lt;br /&gt;
incomingVolumesProcessed = []&lt;br /&gt;
&lt;br /&gt;
def checkForNewVolumes():&lt;br /&gt;
  # Check if there is a new file in the &lt;br /&gt;
  from os import listdir&lt;br /&gt;
  from os.path import isfile, join&lt;br /&gt;
  for f in listdir(incomingVolumeFolder):&lt;br /&gt;
    if f in incomingVolumesProcessed:&lt;br /&gt;
      # this is an incoming file, it was already there&lt;br /&gt;
      continue&lt;br /&gt;
    filePath = join(incomingVolumeFolder, f)&lt;br /&gt;
    if not isfile(filePath):&lt;br /&gt;
      # ignore directories&lt;br /&gt;
      continue&lt;br /&gt;
    logging.info(&amp;quot;Loading new file: &amp;quot;+f)&lt;br /&gt;
    incomingVolumesProcessed.append(f)&lt;br /&gt;
    slicer.util.loadVolume(filePath)&lt;br /&gt;
  # Check again in 3000ms&lt;br /&gt;
  qt.QTimer.singleShot(3000, checkForNewVolumes)&lt;br /&gt;
&lt;br /&gt;
# Start monitoring&lt;br /&gt;
checkForNewVolumes()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
===How to access top level tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # Note, fileValue accesses the database of cached top level tags&lt;br /&gt;
  # (nested tags are not included)&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
===How to access DICOM tags nested in a sequence===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # use pydicom to access the full header, which requires&lt;br /&gt;
  # re-reading the dataset instead of using the database cache&lt;br /&gt;
  import pydicom&lt;br /&gt;
  pydicom.dcmread(fileList[0])&lt;br /&gt;
  ds.CTExposureSequence[0].ExposureModulationType&lt;br /&gt;
&lt;br /&gt;
===How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
===How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
===How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
===How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm'); slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
===Export a volume to DICOM file format===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Customize table columns in DICOM browser===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database() # Need to go this way, do not use slicer.dicomDatabase for this&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
&lt;br /&gt;
*How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
for viewNode in viewNodes:&lt;br /&gt;
  viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
&lt;br /&gt;
*How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two slice planes==&lt;br /&gt;
&lt;br /&gt;
Measure angle between red and yellow slice nodes. Whenever any of the slice nodes are moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeIds = ['vtkMRMLSliceNodeRed', 'vtkMRMLSliceNodeYellow']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    sliceNormalVector = []&lt;br /&gt;
    for sliceNodeId in sliceNodeIds:&lt;br /&gt;
        sliceToRAS = slicer.mrmlScene.GetNodeByID(sliceNodeId).GetSliceToRAS()&lt;br /&gt;
        sliceNormalVector.append([sliceToRAS.GetElement(0,2), sliceToRAS.GetElement(1,2), sliceToRAS.GetElement(2,2)])&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(sliceNormalVector[0], sliceNormalVector[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between slice planes = {0:0.3f}'.format(angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe slice node changes&lt;br /&gt;
for sliceNodeId in sliceNodeIds:&lt;br /&gt;
    slicer.mrmlScene.GetNodeByID(sliceNodeId).AddObserver(vtk.vtkCommand.ModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from a normal vector and position==&lt;br /&gt;
&lt;br /&gt;
This code snippet shows how to display a slice view defined by a normal vector and position in an anatomically sensible way: rotating slice view so that &amp;quot;up&amp;quot; direction (or &amp;quot;right&amp;quot; direction) is towards an anatomical axis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition, defaultViewUpDirection=None, backupViewRightDirection=None):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Set slice pose from the provided plane normal and position. View up direction is determined automatically,&lt;br /&gt;
    to make view up point towards defaultViewUpDirection.&lt;br /&gt;
    :param defaultViewUpDirection Slice view will be spinned in-plane to match point approximately this up direction. Default: patient superior.&lt;br /&gt;
    :param backupViewRightDirection Slice view will be spinned in-plane to match point approximately this right direction&lt;br /&gt;
        if defaultViewUpDirection is too similar to sliceNormal. Default: patient left.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Fix up input directions&lt;br /&gt;
    if defaultViewUpDirection is None:&lt;br /&gt;
        defaultViewUpDirection = [0,0,1]&lt;br /&gt;
    if backupViewRightDirection is None:&lt;br /&gt;
        backupViewRightDirection = [-1,0,0]&lt;br /&gt;
    if sliceNormal[1]&amp;gt;=0:&lt;br /&gt;
        sliceNormalStandardized = sliceNormal&lt;br /&gt;
    else:&lt;br /&gt;
        sliceNormalStandardized = [-sliceNormal[0], -sliceNormal[1], -sliceNormal[2]]&lt;br /&gt;
    # Compute slice axes&lt;br /&gt;
    sliceNormalViewUpAngle = vtk.vtkMath.AngleBetweenVectors(sliceNormalStandardized, defaultViewUpDirection)&lt;br /&gt;
    angleTooSmallThresholdRad = 0.25 # about 15 degrees&lt;br /&gt;
    if sliceNormalViewUpAngle &amp;gt; angleTooSmallThresholdRad and sliceNormalViewUpAngle &amp;lt; vtk.vtkMath.Pi() - angleTooSmallThresholdRad:&lt;br /&gt;
        viewUpDirection = defaultViewUpDirection&lt;br /&gt;
        sliceAxisY = viewUpDirection&lt;br /&gt;
        sliceAxisX = [0, 0, 0]&lt;br /&gt;
        vtk.vtkMath.Cross(sliceAxisY, sliceNormalStandardized, sliceAxisX)&lt;br /&gt;
    else:&lt;br /&gt;
        sliceAxisX = backupViewRightDirection&lt;br /&gt;
    # Set slice axes&lt;br /&gt;
    sliceNode.SetSliceToRASByNTP(sliceNormalStandardized[0], sliceNormalStandardized[1], sliceNormalStandardized[2],&lt;br /&gt;
        sliceAxisX[0], sliceAxisX[1], sliceAxisX[2],&lt;br /&gt;
        slicePosition[0], slicePosition[1], slicePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Example usage:&lt;br /&gt;
sliceNode = getNode('vtkMRMLSliceNodeRed')&lt;br /&gt;
transformNode = getNode('Transform_3')&lt;br /&gt;
transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
transformNode.GetMatrixTransformToParent(transformMatrix)&lt;br /&gt;
sliceNormal = [transformMatrix.GetElement(0,2), transformMatrix.GetElement(1,2), transformMatrix.GetElement(2,2)]&lt;br /&gt;
slicePosition = [transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)]&lt;br /&gt;
setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Switching to markup fiducial placement mode==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change markup fiducial display properties==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get a notification if a markup point position is modified==&lt;br /&gt;
&lt;br /&gt;
Event management of Slicer-4.11 version is still subject to change. The example below shows how point manipulation can be observed now.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupChanged(caller,event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    if movingMarkupIndex &amp;gt;= 0:&lt;br /&gt;
        pos = [0,0,0]&lt;br /&gt;
        markupsNode.GetNthFiducialPosition(movingMarkupIndex, pos)&lt;br /&gt;
        isPreview = markupsNode.GetNthControlPointPositionStatus(movingMarkupIndex) == slicer.vtkMRMLMarkupsNode.PositionPreview&lt;br /&gt;
        if isPreview:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} is previewed at {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
        else:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} was moved {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
    else:&lt;br /&gt;
        logging.info(&amp;quot;Points modified: slice view = {0}&amp;quot;.format(sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupStartInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()    &lt;br /&gt;
    logging.info(&amp;quot;Start interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupEndInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    logging.info(&amp;quot;End interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, onMarkupChanged)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointStartInteractionEvent, onMarkupStartInteraction)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointEndInteractionEvent, onMarkupEndInteraction)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get a notification if a transform is modified==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate a node around a specified point==&lt;br /&gt;
&lt;br /&gt;
Set up the scene:&lt;br /&gt;
* Add a markup fiducial node (centerOfRotationMarkupsNode) with a single point to specify center of rotation.&lt;br /&gt;
* Add a rotation transform (rotationTransformNode) that will be edited in Transforms module to specify rotation angles.&lt;br /&gt;
* Add a transform (finalTransformNode) and apply it (not harden) to those nodes (images, models, etc.) that you want to rotate around the center of rotation point.&lt;br /&gt;
&lt;br /&gt;
Then run the script below, go to Transforms module, select rotationTransformNode, and move rotation sliders.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# This markups fiducial node specifies the center of rotation&lt;br /&gt;
centerOfRotationMarkupsNode = getNode('F')&lt;br /&gt;
# This transform can be  edited in Transforms module&lt;br /&gt;
rotationTransformNode = getNode('LinearTransform_3')&lt;br /&gt;
# This transform has to be applied to the image, model, etc.&lt;br /&gt;
finalTransformNode = getNode('LinearTransform_4')&lt;br /&gt;
&lt;br /&gt;
def updateFinalTransform(unusedArg1=None, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
    rotationMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
    rotationTransformNode.GetMatrixTransformToParent(rotationMatrix)&lt;br /&gt;
    rotationCenterPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
    centerOfRotationMarkupsNode.GetNthControlPointPositionWorld(0, rotationCenterPointCoord)&lt;br /&gt;
    finalTransform = vtk.vtkTransform()&lt;br /&gt;
    finalTransform.Translate(rotationCenterPointCoord)&lt;br /&gt;
    finalTransform.Concatenate(rotationMatrix)&lt;br /&gt;
    finalTransform.Translate(-rotationCenterPointCoord[0], -rotationCenterPointCoord[1], -rotationCenterPointCoord[2])&lt;br /&gt;
    finalTransformNode.SetAndObserveMatrixTransformToParent(finalTransform.GetMatrix())&lt;br /&gt;
&lt;br /&gt;
# Manual initial update&lt;br /&gt;
updateFinalTransform()&lt;br /&gt;
&lt;br /&gt;
# Automatic update when point is moved or transform is modified&lt;br /&gt;
rotationTransformNodeObserver = rotationTransformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, updateFinalTransform)&lt;br /&gt;
centerOfRotationMarkupsNodeObserver = centerOfRotationMarkupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, updateFinalTransform)&lt;br /&gt;
&lt;br /&gt;
# Execute these lines to stop automatic updates:&lt;br /&gt;
# rotationTransformNode.RemoveObserver(rotationTransformNodeObserver)&lt;br /&gt;
# centerOfRotationMarkupsNode.RemoveObserver(centerOfRotationMarkupsNodeObserver)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a context menu when a markup point is clicked in a slice or 3D view==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Example actions to perform&lt;br /&gt;
&lt;br /&gt;
def action1():&lt;br /&gt;
  print('Action1 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action2():&lt;br /&gt;
  print('Action2 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action3():&lt;br /&gt;
  print('Action3 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
# Clicked markup index is saved here to let the action&lt;br /&gt;
# know which markup needs to be manipulated.&lt;br /&gt;
slicer.clickedMarkupIndex = -1&lt;br /&gt;
  &lt;br /&gt;
# Create a simple menu&lt;br /&gt;
&lt;br /&gt;
menu = qt.QMenu()&lt;br /&gt;
a1 = qt.QAction(&amp;quot;Test&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a1.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a1)&lt;br /&gt;
a2 = qt.QAction(&amp;quot;Action&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a2.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a2)&lt;br /&gt;
a3 = qt.QAction(&amp;quot;Here&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a3.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a3)&lt;br /&gt;
&lt;br /&gt;
# Add observer to a markup fiducial list&lt;br /&gt;
&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_INT)&lt;br /&gt;
def markupClickedCallback(caller, eventId, callData):&lt;br /&gt;
  slicer.clickedMarkupIndex = callData&lt;br /&gt;
  print('Open menu on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
  menu.move(qt.QCursor.pos())&lt;br /&gt;
  menu.show()&lt;br /&gt;
&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
observerTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointClickedEvent, markupClickedCallback)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Write markup positions to JSON file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Write annotation ROI to JSON file==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a simple surface mesh as a model node==&lt;br /&gt;
&lt;br /&gt;
This example shows how to display a simple surface mesh (a box, created by a VTK source filter) as a model node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create and set up polydata source&lt;br /&gt;
box = vtk.vtkCubeSource()&lt;br /&gt;
box.SetXLength(30)&lt;br /&gt;
box.SetYLength(20)&lt;br /&gt;
box.SetZLength(15)&lt;br /&gt;
box.SetCenter(10,20,5)&lt;br /&gt;
&lt;br /&gt;
# Create a model node that displays output of the source&lt;br /&gt;
boxNode = slicer.modules.models.logic().AddModel(box.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Adjust display properties&lt;br /&gt;
boxNode.GetDisplayNode().SetColor(1,0,0)&lt;br /&gt;
boxNode.GetDisplayNode().SetOpacity(0.8)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Add a texture mapped plane to the scene as a model==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# use dummy image data here&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
&lt;br /&gt;
scene = slicer.mrmlScene&lt;br /&gt;
&lt;br /&gt;
# Create model node&lt;br /&gt;
model = slicer.vtkMRMLModelNode()&lt;br /&gt;
model.SetScene(scene)&lt;br /&gt;
model.SetName(scene.GenerateUniqueName(&amp;quot;2DImageModel&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
model.SetAndObservePolyData(planeSource.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create display node&lt;br /&gt;
modelDisplay = slicer.vtkMRMLModelDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
modelDisplay.SetScene(scene)&lt;br /&gt;
scene.AddNode(modelDisplay)&lt;br /&gt;
model.SetAndObserveDisplayNodeID(modelDisplay.GetID())&lt;br /&gt;
&lt;br /&gt;
# Add to scene&lt;br /&gt;
modelDisplay.SetAndObserveTextureImageData(e.GetOutput())&lt;br /&gt;
scene.AddNode(model) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
transform = slicer.vtkMRMLLinearTransformNode()&lt;br /&gt;
scene.AddNode(transform) &lt;br /&gt;
model.SetAndObserveTransformNodeID(transform.GetID())&lt;br /&gt;
&lt;br /&gt;
vTransform = vtk.vtkTransform()&lt;br /&gt;
vTransform.Scale(50,50,50)&lt;br /&gt;
vTransform.RotateX(30)&lt;br /&gt;
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get scalar values at surface of a model==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Select cells of a using markups fiducial points==&lt;br /&gt;
&lt;br /&gt;
The following script selects cells of a model node that are closest to positions of markups fiducial points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get input nodes&lt;br /&gt;
modelNode = slicer.util.getNode('Segment_1') # select cells in this model&lt;br /&gt;
markupsNode = slicer.util.getNode('F') # points will be selected at positions specified by this markups fiducial node&lt;br /&gt;
&lt;br /&gt;
# Create scalar array that will store selection state&lt;br /&gt;
cellScalars = modelNode.GetMesh().GetCellData()&lt;br /&gt;
selectionArray = cellScalars.GetArray('selection')&lt;br /&gt;
if not selectionArray:&lt;br /&gt;
    selectionArray = vtk.vtkIntArray()&lt;br /&gt;
    selectionArray.SetName('selection')&lt;br /&gt;
    selectionArray.SetNumberOfValues(modelNode.GetMesh().GetNumberOfCells())&lt;br /&gt;
    selectionArray.Fill(0)&lt;br /&gt;
    cellScalars.AddArray(selectionArray)&lt;br /&gt;
&lt;br /&gt;
# Set up coloring by selection array&lt;br /&gt;
modelNode.GetDisplayNode().SetActiveScalar(&amp;quot;selection&amp;quot;, vtk.vtkAssignAttribute.CELL_DATA)&lt;br /&gt;
modelNode.GetDisplayNode().SetAndObserveColorNodeID(&amp;quot;vtkMRMLColorTableNodeWarm1&amp;quot;)&lt;br /&gt;
modelNode.GetDisplayNode().SetScalarVisibility(True)&lt;br /&gt;
&lt;br /&gt;
# Initialize cell locator&lt;br /&gt;
cell = vtk.vtkCellLocator()&lt;br /&gt;
cell.SetDataSet(modelNode.GetMesh())&lt;br /&gt;
cell.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onPointsModified(observer=None, eventid=None):&lt;br /&gt;
    global markupsNode, selectionArray&lt;br /&gt;
    selectionArray.Fill(0) # set all cells to non-selected by default&lt;br /&gt;
    markupPoints = slicer.util.arrayFromMarkupsControlPoints(markupsNode)&lt;br /&gt;
    closestPoint = [0.0, 0.0, 0.0]&lt;br /&gt;
    cellObj = vtk.vtkGenericCell()&lt;br /&gt;
    cellId = vtk.mutable(0)&lt;br /&gt;
    subId = vtk.mutable(0)&lt;br /&gt;
    dist2 = vtk.mutable(0.0)&lt;br /&gt;
    for markupPoint in markupPoints:&lt;br /&gt;
        cell.FindClosestPoint(markupPoint, closestPoint, cellObj, cellId, subId, dist2)&lt;br /&gt;
        closestCell = cellId.get()&lt;br /&gt;
        if closestCell &amp;gt;=0:&lt;br /&gt;
            selectionArray.SetValue(closestCell, 100) # set selected cell's scalar value to non-zero&lt;br /&gt;
    selectionArray.Modified()&lt;br /&gt;
&lt;br /&gt;
# Initial update&lt;br /&gt;
onPointsModified()&lt;br /&gt;
# Automatic update each time when a markup point is modified&lt;br /&gt;
markupsNodeObserverTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsFiducialNode.PointModifiedEvent, onPointsModified)&lt;br /&gt;
&lt;br /&gt;
# To stop updating selection, run this:&lt;br /&gt;
# markupsNode.RemoveObserver(markupsNodeObserverTag)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export entire scene as VRML==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export model to Blender, including color by scalar==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Export a tract (FiberBundle) to Blender, including color==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Iterate over tract (FiberBundle) streamline points==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Clone a node==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Clone a volume==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create a new volume==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
imageData.GetPointData().GetScalars().Fill(fillVoxelValue)&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get value of a volume at specific voxel coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel value of &amp;quot;volumeNode&amp;quot; at &amp;quot;ijk&amp;quot; volume voxel coordinates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
ijk = [20,40,30]  # volume voxel coordinates&lt;br /&gt;
&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)  # get voxels as a numpy array&lt;br /&gt;
voxelValue = voxels[ijk[2], ijk[1], ijk[0]]  # note that numpy array index order is kji (not ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Modify voxels in a volume==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get volume voxel coordinates from markup fiducial RAS coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get markup fiducial RAS coordinates from volume voxel coordinates==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get the values of all voxels for a label value==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Access values in a DTI tensor volume==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change window/level (brightness/contrast) or colormap of a volume==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Make mouse left-click and drag on the image adjust window/level==&lt;br /&gt;
&lt;br /&gt;
In older Slicer versions, by default, left-click and drag in a slice view adjusted window/level of the displayed image. Window/level adjustment is now a new mouse mode that can be activated by clicking on its toolbar button or running this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.applicationLogic().GetInteractionNode().SetCurrentInteractionMode(slicer.vtkMRMLInteractionNode.AdjustWindowLevel)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create custom color table==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manipulate a Slice View==&lt;br /&gt;
&lt;br /&gt;
===Change slice offset===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Change slice orientation===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Show slice views in 3D window===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Reset field of view to show background volume maximized===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Rotate slice views to volume plane===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Iterate over current visible slice views, and set foreground and background images===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     compositeNode = layoutManager.sliceWidget(sliceViewName).sliceLogic().GetSliceCompositeNode()&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a volume in slice views==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change opacity of foreground volume in slice views==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Fit slice plane to markup fiducials==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.array([0,0,0])&lt;br /&gt;
p2 = np.array([0,0,0])&lt;br /&gt;
p3 = np.array([0,0,0])&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0, 0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save a series of images from a Slice View==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rasterize a model and save it to a series of image files==&lt;br /&gt;
&lt;br /&gt;
This example shows how to generate a stack of image files from an STL file:&lt;br /&gt;
&lt;br /&gt;
 inputModelFile = &amp;quot;/some/input/folder/SomeShape.stl&amp;quot;&lt;br /&gt;
 outputDir = &amp;quot;/some/output/folder&amp;quot;&lt;br /&gt;
 outputVolumeLabelValue = 100&lt;br /&gt;
 outputVolumeSpacingMm = [0.5, 0.5, 0.5]&lt;br /&gt;
 outputVolumeMarginMm = [10.0, 10.0, 10.0]&lt;br /&gt;
 &lt;br /&gt;
 # Read model&lt;br /&gt;
 inputModel = slicer.util.loadModel(inputModelFile)&lt;br /&gt;
 &lt;br /&gt;
 # Determine output volume geometry and create a corresponding reference volume&lt;br /&gt;
 import math&lt;br /&gt;
 import numpy as np&lt;br /&gt;
 bounds = np.zeros(6)&lt;br /&gt;
 inputModel.GetBounds(bounds)&lt;br /&gt;
 imageData = vtk.vtkImageData()&lt;br /&gt;
 imageSize = [ int((bounds[axis*2+1]-bounds[axis*2]+outputVolumeMarginMm[axis]*2.0)/outputVolumeSpacingMm[axis]) for axis in range(3) ]&lt;br /&gt;
 imageOrigin = [ bounds[axis*2]-outputVolumeMarginMm[axis] for axis in range(3) ]&lt;br /&gt;
 imageData.SetDimensions(imageSize)&lt;br /&gt;
 imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1)&lt;br /&gt;
 imageData.GetPointData().GetScalars().Fill(0)&lt;br /&gt;
 referenceVolumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
 referenceVolumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
 referenceVolumeNode.SetSpacing(outputVolumeSpacingMm)&lt;br /&gt;
 referenceVolumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
 referenceVolumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
 &lt;br /&gt;
 # Convert model to labelmap&lt;br /&gt;
 seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
 seg.SetReferenceImageGeometryParameterFromVolumeNode(referenceVolumeNode)&lt;br /&gt;
 slicer.modules.segmentations.logic().ImportModelToSegmentationNode(inputModel, seg)&lt;br /&gt;
 seg.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
 outputLabelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
 slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(seg, outputLabelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
 outputLabelmapVolumeArray = (slicer.util.arrayFromVolume(outputLabelmapVolumeNode) * outputVolumeLabelValue).astype('int8')&lt;br /&gt;
 &lt;br /&gt;
 # Write labelmap volume to series of TIFF files&lt;br /&gt;
 pip_install(&amp;quot;imageio&amp;quot;)&lt;br /&gt;
 import imageio&lt;br /&gt;
 for i in range(len(outputLabelmapVolumeArray)):&lt;br /&gt;
     imageio.imwrite(f'{outputDir}/image_{i:03}.tiff', outputLabelmapVolumeArray[i])&lt;br /&gt;
&lt;br /&gt;
==Save the scene into a new directory==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save the scene into a single MRB file==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Save a node to file==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Center the 3D View on the Scene==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Display text in a 3D view or slice view==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide slice view annotations (DataProbe)==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Turning off interpolation==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Customize viewer layout==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;layout type=&amp;quot;vertical&amp;quot; split=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLSliceNode&amp;quot; singletontag=&amp;quot;Red&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;orientation&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewcolor&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/layout&amp;gt;&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Built-in layout IDs are all below 100, so you can choose any large random number&lt;br /&gt;
# for your custom layout ID.&lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
&lt;br /&gt;
# Switch to the new custom layout &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
You can use this code snippet to add a button to the layout selector toolbar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Add button to layout selector toolbar for this custom layout&lt;br /&gt;
viewToolBar = mainWindow().findChild('QToolBar', 'ViewToolBar')&lt;br /&gt;
layoutMenu = viewToolBar.widgetForAction(viewToolBar.actions()[0]).menu()&lt;br /&gt;
layoutSwitchActionParent = layoutMenu  # use `layoutMenu` to add inside layout list, use `viewToolBar` to add next the standard layout list&lt;br /&gt;
layoutSwitchAction = layoutSwitchActionParent.addAction(&amp;quot;My view&amp;quot;) # add inside layout list&lt;br /&gt;
layoutSwitchAction.setData(layoutId)&lt;br /&gt;
layoutSwitchAction.setIcon(qt.QIcon(':Icons/Go.png'))&lt;br /&gt;
layoutSwitchAction.setToolTip('3D and slice view')&lt;br /&gt;
layoutSwitchAction.connect('triggered()', lambda layoutId = customLayoutId: slicer.app.layoutManager().setLayout(layoutId))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Customize keyboard shortcuts==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Disable certain user interactions in slice views==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change default slice view orientation==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set all slice views linked by default==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set crosshair jump mode to centered by default==&lt;br /&gt;
&lt;br /&gt;
You can change default slice jump mode (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
crosshair=slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLCrosshairNode&amp;quot;)&lt;br /&gt;
crosshair.SetCrosshairBehavior(crosshair.CenteredJumpSlice)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set up custom units in slice view ruler==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in range(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a slice view outside the view layout==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;TS&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
viewNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(layoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
viewWidget.sliceViewName = layoutName&lt;br /&gt;
viewWidget.sliceViewLabel = layoutLabel&lt;br /&gt;
c = viewNode.GetLayoutColor()&lt;br /&gt;
viewWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLSliceNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Show a 3D view outside the view layout==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;Test3DView&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;T3&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML node&lt;br /&gt;
viewNode = slicer.vtkMRMLViewNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLThreeDWidget()&lt;br /&gt;
viewWidget.viewLabel = layoutLabel&lt;br /&gt;
viewWidget.viewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLViewNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get displayable manager of a certain type for a certain view==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelDisplayableManager = None&lt;br /&gt;
threeDViewWidget = slicer.app.layoutManager().threeDWidget(0)&lt;br /&gt;
managers = vtk.vtkCollection()&lt;br /&gt;
threeDViewWidget.getDisplayableManagers(managers)&lt;br /&gt;
for i in range(managers.GetNumberOfItems()):&lt;br /&gt;
  obj = managers.GetItemAsObject(i)&lt;br /&gt;
  if obj.IsA('vtkMRMLModelDisplayableManager'):&lt;br /&gt;
    modelDisplayableManager = obj&lt;br /&gt;
    break&lt;br /&gt;
if modelDisplayableManager is None:&lt;br /&gt;
  logging.error('Failed to find the model displayable manager')&lt;br /&gt;
  return&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Running an ITK filter in Python using SimpleITK==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
&lt;br /&gt;
*See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
*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&lt;br /&gt;
&lt;br /&gt;
==Get current mouse coordinates in a slice view==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get DataProbe text==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get reformatted image from a slice viewer as numpy array==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print voxels.shape&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Combine multiple volumes into one==&lt;br /&gt;
&lt;br /&gt;
This example combines two volumes into a new one by subtracting one from the other.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
[input1Volume, input2Volume] = SampleData.SampleDataLogic().downloadDentalSurgery()&lt;br /&gt;
&lt;br /&gt;
import slicer.util&lt;br /&gt;
a = slicer.util.arrayFromVolume(input1Volume)&lt;br /&gt;
b = slicer.util.arrayFromVolume(input2Volume)&lt;br /&gt;
&lt;br /&gt;
# 'a' and 'b' are numpy arrays,&lt;br /&gt;
# they can be combined using any numpy array operations&lt;br /&gt;
# to produce the result array 'c'&lt;br /&gt;
c = b-a&lt;br /&gt;
&lt;br /&gt;
volumeNode = slicer.modules.volumes.logic().CloneVolume(input1Volume, &amp;quot;Difference&amp;quot;)&lt;br /&gt;
slicer.util.updateVolumeFromArray(volumeNode, c)&lt;br /&gt;
setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Thick slab reconstruction and maximum/minimum intensity volume projections==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
==Change default file type for nodes (that have never been saved yet)==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
==Change file type for saving for all volumes (with already existing storage nodes)==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Sequences==&lt;br /&gt;
&lt;br /&gt;
===Concatenate all sequences in the scene into a new sequence===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Segmentations==&lt;br /&gt;
&lt;br /&gt;
===Create a segmentation from a labelmap volume and display in 3D===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
===Export labelmap node from segmentation node===&lt;br /&gt;
&lt;br /&gt;
Export smallest possible labelmap:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export labelmap that matches geometry of a chosen reference volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export by pressing Ctrl+Shift+s key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPath = &amp;quot;c:/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def exportLabelmap():&lt;br /&gt;
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLSegmentationNode&amp;quot;)&lt;br /&gt;
    referenceVolumeNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
    labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
    slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
    filepath = outputPath + &amp;quot;/&amp;quot; + referenceVolumeNode.GetName()+&amp;quot;-label.nrrd&amp;quot;&lt;br /&gt;
    slicer.util.saveNode(labelmapVolumeNode, filepath)&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode.GetDisplayNode().GetColorNode())&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
    slicer.util.delayDisplay(&amp;quot;Segmentation saved to &amp;quot;+filepath)&lt;br /&gt;
&lt;br /&gt;
shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
shortcut.setKey(qt.QKeySequence('Ctrl+Shift+s'))&lt;br /&gt;
shortcut.connect( 'activated()', exportLabelmap)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Export model nodes from segmentation node===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
exportedModelsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelHierarchyNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModelHierarchy(seg, exportedModelsNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Show a segmentation in 3D===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get a representation of a segment===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = segmentationNode.GetBinaryLabelmapRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert all segments using default path and conversion parameters===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert all segments using custom path or conversion parameters===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Re-convert using a modified conversion parameter===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Get centroid of a segment in world (RAS) coordinates===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to run segment editor effects from a script===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
*[https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
*[https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
*[https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
&lt;br /&gt;
*[https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
==Accessing views, renderers, and cameras==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide view controller bars==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Customize widgets in view controller bars==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceController = slicer.app.layoutManager().sliceWidget(&amp;quot;Red&amp;quot;).sliceController()&lt;br /&gt;
&lt;br /&gt;
# hide what is not needed&lt;br /&gt;
sliceController.pinButton().hide()&lt;br /&gt;
#sliceController.viewLabel().hide()&lt;br /&gt;
sliceController.fitToWindowToolButton().hide()&lt;br /&gt;
sliceController.sliceOffsetSlider().hide()&lt;br /&gt;
&lt;br /&gt;
# add custom widgets&lt;br /&gt;
myButton = qt.QPushButton(&amp;quot;My custom button&amp;quot;)&lt;br /&gt;
sliceController.barLayout().addWidget(b)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Change 3D view background color==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderer = renderWindow.GetRenderers().GetFirstRenderer()&lt;br /&gt;
renderer.SetBackground(1,0,0)&lt;br /&gt;
renderer.SetBackground2(1,0,0)&lt;br /&gt;
renderWindow.Render()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Hide Slicer logo from main window (to increase space)==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.findChild(slicer.util.mainWindow(), 'LogoLabel').visible = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subject hierarchy== &lt;br /&gt;
====Get the pseudo-singleton subject hierarchy node====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.mrmlScene.GetSubjectHierarchyNode()&lt;br /&gt;
&lt;br /&gt;
====Create subject hierarchy item====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
====Get subject hierarchy item====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
====Traverse children of a subject hierarchy item====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in range(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
====Manipulate subject hierarchy item====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data node associated to an item&lt;br /&gt;
  shNode.SetItemDisplayVisibility(itemID, 1)&lt;br /&gt;
  # Set visibility of whole branch&lt;br /&gt;
  # Note: Folder-type items (fodler, subject, study, etc.) create their own display nodes when show/hiding from UI.&lt;br /&gt;
  #       The displayable managers use SH information to determine visibility of an item, so no need to show/hide individual leaf nodes any more.&lt;br /&gt;
  #       Once the folder display node is created, it can be shown hidden simply using shNode.SetItemDisplayVisibility&lt;br /&gt;
  # From python, this is how to trigger creating a folder display node&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler().instance()&lt;br /&gt;
  folderPlugin = pluginHandler.pluginByName('Folder')&lt;br /&gt;
  folderPlugin.setDisplayVisibility(folderItemID, 1)&lt;br /&gt;
&lt;br /&gt;
====Filter items in TreeView or ComboBox====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
===Listen to subject hierarchy item events===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
===Use whitelist to customize view menu===&lt;br /&gt;
When right-clicking certain types of nodes in the 2D/3D views, a subject hierarchy menu pops up. If menu actions need to be removed, a whitelist can be used to specify the ones that should show up.&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler.instance()&lt;br /&gt;
  pluginLogic = pluginHandler.pluginLogic()&lt;br /&gt;
  menuActions = pluginLogic.allViewMenuActions()&lt;br /&gt;
  # Returns ('RenamePointAction', 'DeletePointAction', 'ToggleSelectPointAction', 'EditPropertiesAction')&lt;br /&gt;
  newActions = ['RenamePointAction']&lt;br /&gt;
  pluginLogic.setViewMenuActionWhitelist(newActions)&lt;br /&gt;
&lt;br /&gt;
==Plotting==&lt;br /&gt;
&lt;br /&gt;
===Slicer plots displayed in view layout===&lt;br /&gt;
&lt;br /&gt;
Create histogram plot of a volume and show it embedded in the view layout. More information: https://www.slicer.org/wiki/Documentation/Nightly/Developers/Plots&lt;br /&gt;
&lt;br /&gt;
====Using &amp;lt;code&amp;gt;slicer.util.plot&amp;lt;/code&amp;gt; utility function====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
chartNode = slicer.util.plot(histogram, xColumnIndex = 1)&lt;br /&gt;
chartNode.SetYAxisRangeAuto(False)&lt;br /&gt;
chartNode.SetYAxisRange(0, 4e5)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:SlicerPlot.png]]&lt;br /&gt;
&lt;br /&gt;
====Using MRML classes only====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using matplotlib===&lt;br /&gt;
&lt;br /&gt;
Matplotlib may be used from within Slicer, but the default Tk backend locks up and crashes Slicer. However, Matplotlib may still be used through other backends. More details can be found on the [http://matplotlib.sourceforge.net/ MatPlotLib] pages.&lt;br /&gt;
&lt;br /&gt;
====Non-interactive plot====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
&lt;br /&gt;
# Static image view&lt;br /&gt;
pm = qt.QPixmap(&amp;quot;MatplotlibExample.png&amp;quot;)&lt;br /&gt;
imageWidget = qt.QLabel()&lt;br /&gt;
imageWidget.setPixmap(pm)&lt;br /&gt;
imageWidget.setScaledContents(True)&lt;br /&gt;
imageWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:MatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
====Plot in Slicer Jupyter notebook====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
display(filename='MatplotlibExample.png', type=&amp;quot;image/png&amp;quot;, binary=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:JupyterNotebookMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
====Interactive plot using wxWidgets GUI toolkit====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
  import wx&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib wxPython')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Set matplotlib to use WXAgg backend&lt;br /&gt;
import matplotlib&lt;br /&gt;
matplotlib.use('WXAgg')&lt;br /&gt;
&lt;br /&gt;
# Show an interactive plot&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
fig, ax = plt.subplots()&lt;br /&gt;
ax.plot(histogram[1][1:], histogram[0].astype(float))&lt;br /&gt;
ax.grid(True)&lt;br /&gt;
ax.set_ylim((0, 4e5))&lt;br /&gt;
plt.show(block=False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:InteractiveMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==Execute external applications==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
===Run process in default environment===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;br /&gt;
&lt;br /&gt;
==Manage extensions==&lt;br /&gt;
&lt;br /&gt;
===Download and install extension===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensionName = 'SlicerIGT'&lt;br /&gt;
em = slicer.app.extensionsManagerModel()&lt;br /&gt;
if not em.isExtensionInstalled(extensionName):&lt;br /&gt;
    extensionMetaData = em.retrieveExtensionMetadataByName(extensionName)&lt;br /&gt;
    url = em.serverUrl().toString()+'/download/item/'+extensionMetaData['item_id']&lt;br /&gt;
    extensionPackageFilename = slicer.app.temporaryPath+'/'+extensionMetaData['md5']&lt;br /&gt;
    slicer.util.downloadFile(url, extensionPackageFilename)&lt;br /&gt;
    em.installExtension(extensionPackageFilename)&lt;br /&gt;
    slicer.util.restart()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/4.x/Acknowledgments/CommercialPartners&amp;diff=62710</id>
		<title>Documentation/4.x/Acknowledgments/CommercialPartners</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/4.x/Acknowledgments/CommercialPartners&amp;diff=62710"/>
		<updated>2019-12-05T10:07:40Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Commercial Partners */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Commercial Partners ===&lt;br /&gt;
&lt;br /&gt;
* [http://www.isomics.com/ Isomics] uses 3D Slicer in a variety of academic and commercial research partnerships in fields such as planning and guidance for neurosurgery, quantitative imaging for clinical trials, clinical image informatics.&lt;br /&gt;
&lt;br /&gt;
* [http://www.kitware.com/opensource/slicer.html Kitware] Integral to continuing to support the 3D Slicer community, Kitware is also offering consulting services in response to the rapidly growing demand for the development of proprietary applications and commercial products based on 3D Slicer. Kitware has used 3D Slicer to rapidly prototype solutions in nearly every aspect of medical imaging and is also collaborating on the development of commercial pre-clinical and clinical products based on 3D Slicer.&lt;br /&gt;
&lt;br /&gt;
* [http://pixelmedical.ca Pixel Medical] builds on and contributes to 3D Slicer to develop innovative medical software from idea to clinical prototype to finished product, and to support academic research projects. Areas of expertise include radiation therapy, image guided therapy, virtual &amp;amp; augmented reality, hardware &amp;amp; device support, and machine learning &amp;amp; artificial intelligence.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;#669&amp;quot;&amp;gt;&amp;lt;small&amp;gt;Listed in alphabetical order.&amp;lt;/small&amp;gt;&amp;lt;/font&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61482</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61482"/>
		<updated>2019-10-01T14:30:47Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Change 3D view background color */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=&lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the [[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
* [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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
* [https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
* [https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
* [https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
* Capture the full Slicer screen and save it into a file&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
* Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
* Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
* How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
* How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loadedVolumeNode = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Automatically load volumes that are copied into a folder ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to implement a simple background task by using a timer. The background task is to check for any new volume files in folder and if there is any then automatically load it.&lt;br /&gt;
&lt;br /&gt;
There are more efficient methods for file system monitoring or exchanging image data in real-time (for example, using OpenIGTLink), the example below is just for demonstration purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
incomingVolumeFolder = &amp;quot;c:/tmp/incoming&amp;quot;&lt;br /&gt;
incomingVolumesProcessed = []&lt;br /&gt;
&lt;br /&gt;
def checkForNewVolumes():&lt;br /&gt;
  # Check if there is a new file in the &lt;br /&gt;
  from os import listdir&lt;br /&gt;
  from os.path import isfile, join&lt;br /&gt;
  for f in listdir(incomingVolumeFolder):&lt;br /&gt;
    if f in incomingVolumesProcessed:&lt;br /&gt;
      # this is an incoming file, it was already there&lt;br /&gt;
      continue&lt;br /&gt;
    filePath = join(incomingVolumeFolder, f)&lt;br /&gt;
    if not isfile(filePath):&lt;br /&gt;
      # ignore directories&lt;br /&gt;
      continue&lt;br /&gt;
    logging.info(&amp;quot;Loading new file: &amp;quot;+f)&lt;br /&gt;
    incomingVolumesProcessed.append(f)&lt;br /&gt;
    slicer.util.loadVolume(filePath)&lt;br /&gt;
  # Check again in 3000ms&lt;br /&gt;
  qt.QTimer.singleShot(3000, checkForNewVolumes)&lt;br /&gt;
&lt;br /&gt;
# Start monitoring&lt;br /&gt;
checkForNewVolumes()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
=== How to access top level tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # Note, fileValue accesses the database of cached top level tags&lt;br /&gt;
  # (nested tags are not included)&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
=== How to access DICOM tags nested in a sequence ===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # use pydicom to access the full header, which requires&lt;br /&gt;
  # re-reading the dataset instead of using the database cache&lt;br /&gt;
  import pydicom&lt;br /&gt;
  pydicom.dcmread(fileList[0])&lt;br /&gt;
  ds.CTExposureSequence[0].ExposureModulationType&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
=== How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
=== How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm'); slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Export a volume to DICOM file format ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Customize table columns in DICOM browser ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database() # Need to go this way, do not use slicer.dicomDatabase for this&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
* How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
for viewNode in viewNodes:&lt;br /&gt;
  viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
* How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two slice planes==&lt;br /&gt;
&lt;br /&gt;
Measure angle between red and yellow slice nodes. Whenever any of the slice nodes are moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeIds = ['vtkMRMLSliceNodeRed', 'vtkMRMLSliceNodeYellow']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    sliceNormalVector = []&lt;br /&gt;
    for sliceNodeId in sliceNodeIds:&lt;br /&gt;
        sliceToRAS = slicer.mrmlScene.GetNodeByID(sliceNodeId).GetSliceToRAS()&lt;br /&gt;
        sliceNormalVector.append([sliceToRAS.GetElement(0,2), sliceToRAS.GetElement(1,2), sliceToRAS.GetElement(2,2)])&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(sliceNormalVector[0], sliceNormalVector[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between slice planes = {0:0.3f}'.format(angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe slice node changes&lt;br /&gt;
for sliceNodeId in sliceNodeIds:&lt;br /&gt;
    slicer.mrmlScene.GetNodeByID(sliceNodeId).AddObserver(vtk.vtkCommand.ModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from a normal vector and position==&lt;br /&gt;
&lt;br /&gt;
This code snippet shows how to display a slice view defined by a normal vector and position in an anatomically sensible way: rotating slice view so that &amp;quot;up&amp;quot; direction (or &amp;quot;right&amp;quot; direction) is towards an anatomical axis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition, defaultViewUpDirection=None, backupViewRightDirection=None):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Set slice pose from the provided plane normal and position. View up direction is determined automatically,&lt;br /&gt;
    to make view up point towards defaultViewUpDirection.&lt;br /&gt;
    :param defaultViewUpDirection Slice view will be spinned in-plane to match point approximately this up direction. Default: patient superior.&lt;br /&gt;
    :param backupViewRightDirection Slice view will be spinned in-plane to match point approximately this right direction&lt;br /&gt;
        if defaultViewUpDirection is too similar to sliceNormal. Default: patient left.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Fix up input directions&lt;br /&gt;
    if defaultViewUpDirection is None:&lt;br /&gt;
        defaultViewUpDirection = [0,0,1]&lt;br /&gt;
    if backupViewRightDirection is None:&lt;br /&gt;
        backupViewRightDirection = [-1,0,0]&lt;br /&gt;
    if sliceNormal[1]&amp;gt;=0:&lt;br /&gt;
        sliceNormalStandardized = sliceNormal&lt;br /&gt;
    else:&lt;br /&gt;
        sliceNormalStandardized = [-sliceNormal[0], -sliceNormal[1], -sliceNormal[2]]&lt;br /&gt;
    # Compute slice axes&lt;br /&gt;
    sliceNormalViewUpAngle = vtk.vtkMath.AngleBetweenVectors(sliceNormalStandardized, defaultViewUpDirection)&lt;br /&gt;
    angleTooSmallThresholdRad = 0.25 # about 15 degrees&lt;br /&gt;
    if sliceNormalViewUpAngle &amp;gt; angleTooSmallThresholdRad and sliceNormalViewUpAngle &amp;lt; vtk.vtkMath.Pi() - angleTooSmallThresholdRad:&lt;br /&gt;
        viewUpDirection = defaultViewUpDirection&lt;br /&gt;
        sliceAxisY = viewUpDirection&lt;br /&gt;
        sliceAxisX = [0, 0, 0]&lt;br /&gt;
        vtk.vtkMath.Cross(sliceAxisY, sliceNormalStandardized, sliceAxisX)&lt;br /&gt;
    else:&lt;br /&gt;
        sliceAxisX = backupViewRightDirection&lt;br /&gt;
    # Set slice axes&lt;br /&gt;
    sliceNode.SetSliceToRASByNTP(sliceNormalStandardized[0], sliceNormalStandardized[1], sliceNormalStandardized[2],&lt;br /&gt;
        sliceAxisX[0], sliceAxisX[1], sliceAxisX[2],&lt;br /&gt;
        slicePosition[0], slicePosition[1], slicePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Example usage:&lt;br /&gt;
sliceNode = getNode('vtkMRMLSliceNodeRed')&lt;br /&gt;
transformNode = getNode('Transform_3')&lt;br /&gt;
transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
transformNode.GetMatrixTransformToParent(transformMatrix)&lt;br /&gt;
sliceNormal = [transformMatrix.GetElement(0,2), transformMatrix.GetElement(1,2), transformMatrix.GetElement(2,2)]&lt;br /&gt;
slicePosition = [transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)]&lt;br /&gt;
setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Switching to markup fiducial placement mode ==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change markup fiducial display properties ==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a markup point position is modified ==&lt;br /&gt;
&lt;br /&gt;
Event management of Slicer-4.11 version is still subject to change. The example below shows how point manipulation can be observed now.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupChanged(caller,event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    if movingMarkupIndex &amp;gt;= 0:&lt;br /&gt;
        pos = [0,0,0]&lt;br /&gt;
        markupsNode.GetNthFiducialPosition(movingMarkupIndex, pos)&lt;br /&gt;
        isPreview = markupsNode.GetNthControlPointPositionStatus(movingMarkupIndex) == slicer.vtkMRMLMarkupsNode.PositionPreview&lt;br /&gt;
        if isPreview:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} is previewed at {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
        else:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} was moved {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
    else:&lt;br /&gt;
        logging.info(&amp;quot;Points modified: slice view = {0}&amp;quot;.format(sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupStartInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()    &lt;br /&gt;
    logging.info(&amp;quot;Start interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupEndInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    logging.info(&amp;quot;End interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, onMarkupChanged)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointStartInteractionEvent, onMarkupStartInteraction)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointEndInteractionEvent, onMarkupEndInteraction)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a transform is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a context menu when a markup point is clicked in a slice or 3D view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Example actions to perform&lt;br /&gt;
&lt;br /&gt;
def action1():&lt;br /&gt;
  print('Action1 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action2():&lt;br /&gt;
  print('Action2 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action3():&lt;br /&gt;
  print('Action3 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
# Clicked markup index is saved here to let the action&lt;br /&gt;
# know which markup needs to be manipulated.&lt;br /&gt;
slicer.clickedMarkupIndex = -1&lt;br /&gt;
  &lt;br /&gt;
# Create a simple menu&lt;br /&gt;
&lt;br /&gt;
menu = qt.QMenu()&lt;br /&gt;
a1 = qt.QAction(&amp;quot;Test&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a1.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a1)&lt;br /&gt;
a2 = qt.QAction(&amp;quot;Action&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a2.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a2)&lt;br /&gt;
a3 = qt.QAction(&amp;quot;Here&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a3.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a3)&lt;br /&gt;
&lt;br /&gt;
# Add observer to a markup fiducial list&lt;br /&gt;
&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_INT)&lt;br /&gt;
def markupClickedCallback(caller, eventId, callData):&lt;br /&gt;
  slicer.clickedMarkupIndex = callData&lt;br /&gt;
  print('Open menu on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
  menu.move(qt.QCursor.pos())&lt;br /&gt;
  menu.show()&lt;br /&gt;
&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
observerTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointClickedEvent, markupClickedCallback)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write markup positions to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write annotation ROI to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a simple surface mesh as a model node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to display a simple surface mesh (a box, created by a VTK source filter) as a model node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create and set up polydata source&lt;br /&gt;
box = vtk.vtkCubeSource()&lt;br /&gt;
box.SetXLength(30)&lt;br /&gt;
box.SetYLength(20)&lt;br /&gt;
box.SetZLength(15)&lt;br /&gt;
box.SetCenter(10,20,5)&lt;br /&gt;
&lt;br /&gt;
# Create a model node that displays output of the source&lt;br /&gt;
boxNode = slicer.modules.models.logic().AddModel(box.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Adjust display properties&lt;br /&gt;
boxNode.GetDisplayNode().SetColor(1,0,0)&lt;br /&gt;
boxNode.GetDisplayNode().SetOpacity(0.8)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add a texture mapped plane to the scene as a model ==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# use dummy image data here&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
&lt;br /&gt;
scene = slicer.mrmlScene&lt;br /&gt;
&lt;br /&gt;
# Create model node&lt;br /&gt;
model = slicer.vtkMRMLModelNode()&lt;br /&gt;
model.SetScene(scene)&lt;br /&gt;
model.SetName(scene.GenerateUniqueName(&amp;quot;2DImageModel&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
model.SetAndObservePolyData(planeSource.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create display node&lt;br /&gt;
modelDisplay = slicer.vtkMRMLModelDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
modelDisplay.SetScene(scene)&lt;br /&gt;
scene.AddNode(modelDisplay)&lt;br /&gt;
model.SetAndObserveDisplayNodeID(modelDisplay.GetID())&lt;br /&gt;
&lt;br /&gt;
# Add to scene&lt;br /&gt;
modelDisplay.SetAndObserveTextureImageData(e.GetOutput())&lt;br /&gt;
scene.AddNode(model) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
transform = slicer.vtkMRMLLinearTransformNode()&lt;br /&gt;
scene.AddNode(transform) &lt;br /&gt;
model.SetAndObserveTransformNodeID(transform.GetID())&lt;br /&gt;
&lt;br /&gt;
vTransform = vtk.vtkTransform()&lt;br /&gt;
vTransform.Scale(50,50,50)&lt;br /&gt;
vTransform.RotateX(30)&lt;br /&gt;
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get scalar values at surface of a model ==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Select cells of a using markups fiducial points ==&lt;br /&gt;
&lt;br /&gt;
The following script selects cells of a model node that are closest to positions of markups fiducial points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get input nodes&lt;br /&gt;
modelNode = slicer.util.getNode('Segment_1') # select cells in this model&lt;br /&gt;
markupsNode = slicer.util.getNode('F') # points will be selected at positions specified by this markups fiducial node&lt;br /&gt;
&lt;br /&gt;
# Create scalar array that will store selection state&lt;br /&gt;
selectionArray = vtk.vtkIntArray()&lt;br /&gt;
selectionArray.SetName('selection')&lt;br /&gt;
selectionArray.SetNumberOfValues(modelNode.GetMesh().GetNumberOfCells())&lt;br /&gt;
selectionArray.Fill(0)&lt;br /&gt;
&lt;br /&gt;
cellScalars = modelPointValues = modelNode.GetMesh().GetCellData()&lt;br /&gt;
cellScalars.AddArray(selectionArray)&lt;br /&gt;
&lt;br /&gt;
modelNode.GetDisplayNode().SetActiveScalar(&amp;quot;selection&amp;quot;, vtk.vtkAssignAttribute.CELL_DATA)&lt;br /&gt;
modelNode.GetDisplayNode().SetScalarVisibility(True)&lt;br /&gt;
&lt;br /&gt;
cell = vtk.vtkCellLocator()&lt;br /&gt;
cell.SetDataSet(modelNode.GetMesh())&lt;br /&gt;
cell.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onPointsModified(observer=None, eventid=None):&lt;br /&gt;
    global markupsNode, selectionArray&lt;br /&gt;
    selectionArray.Fill(0) # set all cells to non-selected by default&lt;br /&gt;
    markupPoints = slicer.util.arrayFromMarkupsControlPoints(markupsNode)&lt;br /&gt;
    for markupPoint in markupPoints:&lt;br /&gt;
        closestCell = cell.FindCell(markupPoint)&lt;br /&gt;
        if closestCell &amp;gt;=0:&lt;br /&gt;
            selectionArray.SetValue(closestCell, 100) # set selected cell's scalar value to non-zero&lt;br /&gt;
    selectionArray.Modified()&lt;br /&gt;
&lt;br /&gt;
# Initial update&lt;br /&gt;
onPointsModified()&lt;br /&gt;
# Automatic update each time when a markup point is modified&lt;br /&gt;
markupsNodeObserverTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsFiducialNode.PointModifiedEvent, onPointsModified)&lt;br /&gt;
&lt;br /&gt;
# To stop updating selection, run this:&lt;br /&gt;
# markupsNode.RemoveObserver(markupsNodeObserverTag)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export entire scene as VRML ==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export model to Blender, including color by scalar ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export a tract (FiberBundle) to Blender, including color ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Iterate over tract (FiberBundle) streamline points ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a volume ==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a new volume ==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
imageData.GetPointData().GetScalars().Fill(fillVoxelValue)&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify voxels in a volume ==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.SetScalarComponentFromFloat(distortionVectorPosition_Ijk[0], distortionVectorPosition_Ijk[1], distortionVectorPosition_Ijk[2], 0, fillValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get volume voxel coordinates from markup fiducial RAS coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get markup fiducial RAS coordinates from volume voxel coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get the values of all voxels for a label value  ==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Access values in a DTI tensor volume ==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change window/level (brightness/contrast) or colormap of a volume ==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Make mouse left-click and drag on the image adjust window/level ==&lt;br /&gt;
&lt;br /&gt;
In older Slicer versions, by default, left-click and drag in a slice view adjusted window/level of the displayed image. Window/level adjustment is now a new mouse mode that can be activated by clicking on its toolbar button or running this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.applicationLogic().GetInteractionNode().SetCurrentInteractionMode(slicer.vtkMRMLInteractionNode.AdjustWindowLevel)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create custom color table ==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Manipulate a Slice View ==&lt;br /&gt;
&lt;br /&gt;
=== Change slice offset ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Change slice orientation ===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show slice views in 3D window ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reset field of view to show background volume maximized ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rotate slice views to volume plane ===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Iterate over current visible slice views, and set foreground and background images ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     sliceWidget = layoutManager.sliceWidget(sliceViewName)&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Synchronize zoom factor between slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.sliceNodes = [slicer.app.layoutManager().sliceWidget(viewName).mrmlSliceNode()&lt;br /&gt;
    for viewName in slicer.app.layoutManager().sliceViewNames()]&lt;br /&gt;
&lt;br /&gt;
slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
def sliceModified(caller, event):&lt;br /&gt;
    if slicer.updatingSliceNodes:&lt;br /&gt;
        # prevent infinite loop of slice node updates triggering slice node updates&lt;br /&gt;
        return&lt;br /&gt;
    slicer.updatingSliceNodes = True&lt;br /&gt;
    fov = caller.GetFieldOfView()&lt;br /&gt;
    for sliceNode in slicer.sliceNodes:&lt;br /&gt;
        if sliceNode != caller:&lt;br /&gt;
            sliceNode.SetFieldOfView(*fov)&lt;br /&gt;
    slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
for sliceNode in slicer.sliceNodes:&lt;br /&gt;
    sliceNode.AddObserver(vtk.vtkCommand.ModifiedEvent, sliceModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change opacity of foreground volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fit slice plane to markup fiducials ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.array([0,0,0])&lt;br /&gt;
p2 = np.array([0,0,0])&lt;br /&gt;
p3 = np.array([0,0,0])&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0, 0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a series of images from a Slice View ==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a new directory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a single MRB file ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a node to file ==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Center the 3D View on the Scene ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Display text in a 3D view or slice view ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide slice view annotations (DataProbe) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Turning off interpolation ==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Customize viewer layout ==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;layout type=&amp;quot;vertical&amp;quot; split=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLSliceNode&amp;quot; singletontag=&amp;quot;Red&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;orientation&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewcolor&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/layout&amp;gt;&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Built-in layout IDs are all below 100, so you can choose any large random number&lt;br /&gt;
# for your custom layout ID.&lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
&lt;br /&gt;
# Switch to the new custom layout &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
You can use this code snippet to add a button to the layout selector toolbar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Add button to layout selector toolbar for this custom layout&lt;br /&gt;
viewToolBar = mainWindow().findChild('QToolBar', 'ViewToolBar')&lt;br /&gt;
layoutMenu = viewToolBar.widgetForAction(viewToolBar.actions()[0]).menu()&lt;br /&gt;
layoutSwitchActionParent = layoutMenu  # use `layoutMenu` to add inside layout list, use `viewToolBar` to add next the standard layout list&lt;br /&gt;
layoutSwitchAction = layoutSwitchActionParent.addAction(&amp;quot;My view&amp;quot;) # add inside layout list&lt;br /&gt;
layoutSwitchAction.setIcon(qt.QIcon(':Icons/Go.png'))&lt;br /&gt;
layoutSwitchAction.setToolTip('3D and slice view')&lt;br /&gt;
layoutSwitchAction.connect('triggered()', lambda layoutId = customLayoutId: slicer.app.layoutManager().setLayout(layoutId))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Customize keyboard shortcuts ==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Disable certain user interactions in slice views ==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change default slice view orientation ==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Set all slice views linked by default ==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set crosshair jump mode to centered by default ==&lt;br /&gt;
&lt;br /&gt;
You can change default slice jump mode (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
crosshair=slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLCrosshairNode&amp;quot;)&lt;br /&gt;
crosshair.SetCrosshairBehavior(crosshair.CenteredJumpSlice)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set up custom units in slice view ruler ==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in range(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a slice view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;TS&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
viewNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(layoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
viewWidget.sliceViewName = layoutName&lt;br /&gt;
viewWidget.sliceViewLabel = layoutLabel&lt;br /&gt;
c = viewNode.GetLayoutColor()&lt;br /&gt;
viewWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLSliceNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a 3D view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;Test3DView&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;T3&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML node&lt;br /&gt;
viewNode = slicer.vtkMRMLViewNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLThreeDWidget()&lt;br /&gt;
viewWidget.viewLabel = layoutLabel&lt;br /&gt;
viewWidget.viewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLViewNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get displayable manager of a certain type for a certain view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelDisplayableManager = None&lt;br /&gt;
threeDViewWidget = slicer.app.layoutManager().threeDWidget(0)&lt;br /&gt;
managers = vtk.vtkCollection()&lt;br /&gt;
threeDViewWidget.getDisplayableManagers(managers)&lt;br /&gt;
for i in range(managers.GetNumberOfItems()):&lt;br /&gt;
  obj = managers.GetItemAsObject(i)&lt;br /&gt;
  if obj.IsA('vtkMRMLModelDisplayableManager'):&lt;br /&gt;
    modelDisplayableManager = obj&lt;br /&gt;
    break&lt;br /&gt;
if modelDisplayableManager is None:&lt;br /&gt;
  logging.error('Failed to find the model displayable manager')&lt;br /&gt;
  return&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Running an ITK filter in Python using SimpleITK ==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
* See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
* 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&lt;br /&gt;
&lt;br /&gt;
== Get current mouse coordinates in a slice view ==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get DataProbe text ==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get reformatted image from a slice viewer as numpy array ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print voxels.shape&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thick slab reconstruction and maximum/minimum intensity volume projections ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
== Change default file type for nodes (that have never been saved yet) ==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
== Change file type for saving for all volumes (with already existing storage nodes) ==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sequences ==&lt;br /&gt;
&lt;br /&gt;
=== Concatenate all sequences in the scene into a new sequence ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Segmentations ==&lt;br /&gt;
&lt;br /&gt;
=== Create a segmentation from a labelmap volume and display in 3D ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
=== Export labelmap node from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
Export smallest possible labelmap:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export labelmap that matches geometry of a chosen reference volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export by pressing Ctrl+Shift+s key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPath = &amp;quot;c:/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def exportLabelmap():&lt;br /&gt;
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLSegmentationNode&amp;quot;)&lt;br /&gt;
    referenceVolumeNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
    labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
    slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
    filepath = outputPath + &amp;quot;/&amp;quot; + referenceVolumeNode.GetName()+&amp;quot;-label.nrrd&amp;quot;&lt;br /&gt;
    slicer.util.saveNode(labelmapVolumeNode, filepath)&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode.GetDisplayNode().GetColorNode())&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
    slicer.util.delayDisplay(&amp;quot;Segmentation saved to &amp;quot;+filepath)&lt;br /&gt;
&lt;br /&gt;
shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
shortcut.setKey(qt.QKeySequence('Ctrl+Shift+s'))&lt;br /&gt;
shortcut.connect( 'activated()', exportLabelmap)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Export model nodes from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
exportedModelsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelHierarchyNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModelHierarchy(seg, exportedModelsNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show a segmentation in 3D ===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get a representation of a segment ===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = segmentationNode.GetBinaryLabelmapRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using default path and conversion parameters ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using custom path or conversion parameters ===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-convert using a modified conversion parameter ===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get centroid of a segment in world (RAS) coordinates ===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How to run segment editor effects from a script ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
* [https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
* [https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
* [https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
* [https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
== Accessing views, renderers, and cameras ==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide view controller bars ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Customize widgets in view controller bars ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceController = slicer.app.layoutManager().sliceWidget(&amp;quot;Red&amp;quot;).sliceController()&lt;br /&gt;
&lt;br /&gt;
# hide what is not needed&lt;br /&gt;
sliceController.pinButton().hide()&lt;br /&gt;
#sliceController.viewLabel().hide()&lt;br /&gt;
sliceController.fitToWindowToolButton().hide()&lt;br /&gt;
sliceController.sliceOffsetSlider().hide()&lt;br /&gt;
&lt;br /&gt;
# add custom widgets&lt;br /&gt;
myButton = qt.QPushButton(&amp;quot;My custom button&amp;quot;)&lt;br /&gt;
sliceController.barLayout().addWidget(b)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change 3D view background color ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderer = renderWindow.GetRenderers().GetFirstRenderer()&lt;br /&gt;
renderer.SetBackground(1,0,0)&lt;br /&gt;
renderer.SetBackground2(1,0,0)&lt;br /&gt;
renderWindow.Render()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide Slicer logo from main window (to increase space) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.findChild(slicer.util.mainWindow(), 'LogoLabel').visible = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subject hierarchy == &lt;br /&gt;
==== Get the pseudo-singleton subject hierarchy node ====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.mrmlScene.GetSubjectHierarchyNode()&lt;br /&gt;
&lt;br /&gt;
==== Create subject hierarchy item ====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
==== Get subject hierarchy item ====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
==== Traverse children of a subject hierarchy item ====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in range(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
==== Manipulate subject hierarchy item ====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data node associated to an item&lt;br /&gt;
  shNode.SetItemDisplayVisibility(itemID, 1)&lt;br /&gt;
  # Set visibility of whole branch&lt;br /&gt;
  # Note: Folder-type items (fodler, subject, study, etc.) create their own display nodes when show/hiding from UI.&lt;br /&gt;
  #       The displayable managers use SH information to determine visibility of an item, so no need to show/hide individual leaf nodes any more.&lt;br /&gt;
  #       Once the folder display node is created, it can be shown hidden simply using shNode.SetItemDisplayVisibility&lt;br /&gt;
  # From python, this is how to trigger creating a folder display node&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler().instance()&lt;br /&gt;
  folderPlugin = pluginHandler.pluginByName('Folder')&lt;br /&gt;
  folderPlugin.setDisplayVisibility(folderItemID, 1)&lt;br /&gt;
&lt;br /&gt;
==== Filter items in TreeView or ComboBox ====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
=== Listen to subject hierarchy item events ===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
== Plotting ==&lt;br /&gt;
&lt;br /&gt;
=== Slicer plots displayed in view layout ===&lt;br /&gt;
&lt;br /&gt;
Create histogram plot of a volume and show it embedded in the view layout. More information: https://www.slicer.org/wiki/Documentation/Nightly/Developers/Plots&lt;br /&gt;
&lt;br /&gt;
==== Using &amp;lt;code&amp;gt;slicer.util.plot&amp;lt;/code&amp;gt; utility function ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
chartNode = slicer.util.plot(histogram, xColumnIndex = 1)&lt;br /&gt;
chartNode.SetYAxisRangeAuto(False)&lt;br /&gt;
chartNode.SetYAxisRange(0, 4e5)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:SlicerPlot.png]]&lt;br /&gt;
&lt;br /&gt;
==== Using MRML classes only ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using matplotlib ===&lt;br /&gt;
&lt;br /&gt;
Matplotlib may be used from within Slicer, but the default Tk backend locks up and crashes Slicer. However, Matplotlib may still be used through other backends. More details can be found on the [http://matplotlib.sourceforge.net/ MatPlotLib] pages.&lt;br /&gt;
&lt;br /&gt;
==== Non-interactive plot ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
&lt;br /&gt;
# Static image view&lt;br /&gt;
pm = qt.QPixmap(&amp;quot;MatplotlibExample.png&amp;quot;)&lt;br /&gt;
imageWidget = qt.QLabel()&lt;br /&gt;
imageWidget.setPixmap(pm)&lt;br /&gt;
imageWidget.setScaledContents(True)&lt;br /&gt;
imageWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:MatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==== Plot in Slicer Jupyter notebook ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
display(filename='MatplotlibExample.png', type=&amp;quot;image/png&amp;quot;, binary=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:JupyterNotebookMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==== Interactive plot using wxWidgets GUI toolkit ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
  import wx&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib wxPython')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Set matplotlib to use WXAgg backend&lt;br /&gt;
import matplotlib&lt;br /&gt;
matplotlib.use('WXAgg')&lt;br /&gt;
&lt;br /&gt;
# Show an interactive plot&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
fig, ax = plt.subplots()&lt;br /&gt;
ax.plot(histogram[1][1:], histogram[0].astype(float))&lt;br /&gt;
ax.grid(True)&lt;br /&gt;
ax.set_ylim((0, 4e5))&lt;br /&gt;
plt.show(block=False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:InteractiveMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
== Execute external applications ==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
=== Run process in default environment ===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;br /&gt;
&lt;br /&gt;
== Manage extensions ==&lt;br /&gt;
&lt;br /&gt;
=== Download and install extension ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensionName = 'SlicerIGT'&lt;br /&gt;
em = slicer.app.extensionsManagerModel()&lt;br /&gt;
if not em.isExtensionInstalled(extensionName):&lt;br /&gt;
    extensionMetaData = em.retrieveExtensionMetadataByName(extensionName)&lt;br /&gt;
    url = em.serverUrl().toString()+'/download/item/'+extensionMetaData['item_id']&lt;br /&gt;
    extensionPackageFilename = slicer.app.temporaryPath+'/'+extensionMetaData['md5']&lt;br /&gt;
    slicer.util.downloadFile(url, extensionPackageFilename)&lt;br /&gt;
    em.installExtension(extensionPackageFilename)&lt;br /&gt;
    slicer.util.restart()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61481</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61481"/>
		<updated>2019-10-01T14:11:19Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Manipulate subject hierarchy item */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=&lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the [[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
* [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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
* [https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
* [https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
* [https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
* Capture the full Slicer screen and save it into a file&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
* Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
* Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
* How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
* How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loadedVolumeNode = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Automatically load volumes that are copied into a folder ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to implement a simple background task by using a timer. The background task is to check for any new volume files in folder and if there is any then automatically load it.&lt;br /&gt;
&lt;br /&gt;
There are more efficient methods for file system monitoring or exchanging image data in real-time (for example, using OpenIGTLink), the example below is just for demonstration purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
incomingVolumeFolder = &amp;quot;c:/tmp/incoming&amp;quot;&lt;br /&gt;
incomingVolumesProcessed = []&lt;br /&gt;
&lt;br /&gt;
def checkForNewVolumes():&lt;br /&gt;
  # Check if there is a new file in the &lt;br /&gt;
  from os import listdir&lt;br /&gt;
  from os.path import isfile, join&lt;br /&gt;
  for f in listdir(incomingVolumeFolder):&lt;br /&gt;
    if f in incomingVolumesProcessed:&lt;br /&gt;
      # this is an incoming file, it was already there&lt;br /&gt;
      continue&lt;br /&gt;
    filePath = join(incomingVolumeFolder, f)&lt;br /&gt;
    if not isfile(filePath):&lt;br /&gt;
      # ignore directories&lt;br /&gt;
      continue&lt;br /&gt;
    logging.info(&amp;quot;Loading new file: &amp;quot;+f)&lt;br /&gt;
    incomingVolumesProcessed.append(f)&lt;br /&gt;
    slicer.util.loadVolume(filePath)&lt;br /&gt;
  # Check again in 3000ms&lt;br /&gt;
  qt.QTimer.singleShot(3000, checkForNewVolumes)&lt;br /&gt;
&lt;br /&gt;
# Start monitoring&lt;br /&gt;
checkForNewVolumes()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
=== How to access top level tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # Note, fileValue accesses the database of cached top level tags&lt;br /&gt;
  # (nested tags are not included)&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
=== How to access DICOM tags nested in a sequence ===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # use pydicom to access the full header, which requires&lt;br /&gt;
  # re-reading the dataset instead of using the database cache&lt;br /&gt;
  import pydicom&lt;br /&gt;
  pydicom.dcmread(fileList[0])&lt;br /&gt;
  ds.CTExposureSequence[0].ExposureModulationType&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
=== How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
=== How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm'); slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Export a volume to DICOM file format ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Customize table columns in DICOM browser ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database() # Need to go this way, do not use slicer.dicomDatabase for this&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
* How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
for viewNode in viewNodes:&lt;br /&gt;
  viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
* How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two slice planes==&lt;br /&gt;
&lt;br /&gt;
Measure angle between red and yellow slice nodes. Whenever any of the slice nodes are moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeIds = ['vtkMRMLSliceNodeRed', 'vtkMRMLSliceNodeYellow']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    sliceNormalVector = []&lt;br /&gt;
    for sliceNodeId in sliceNodeIds:&lt;br /&gt;
        sliceToRAS = slicer.mrmlScene.GetNodeByID(sliceNodeId).GetSliceToRAS()&lt;br /&gt;
        sliceNormalVector.append([sliceToRAS.GetElement(0,2), sliceToRAS.GetElement(1,2), sliceToRAS.GetElement(2,2)])&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(sliceNormalVector[0], sliceNormalVector[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between slice planes = {0:0.3f}'.format(angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe slice node changes&lt;br /&gt;
for sliceNodeId in sliceNodeIds:&lt;br /&gt;
    slicer.mrmlScene.GetNodeByID(sliceNodeId).AddObserver(vtk.vtkCommand.ModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from a normal vector and position==&lt;br /&gt;
&lt;br /&gt;
This code snippet shows how to display a slice view defined by a normal vector and position in an anatomically sensible way: rotating slice view so that &amp;quot;up&amp;quot; direction (or &amp;quot;right&amp;quot; direction) is towards an anatomical axis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition, defaultViewUpDirection=None, backupViewRightDirection=None):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Set slice pose from the provided plane normal and position. View up direction is determined automatically,&lt;br /&gt;
    to make view up point towards defaultViewUpDirection.&lt;br /&gt;
    :param defaultViewUpDirection Slice view will be spinned in-plane to match point approximately this up direction. Default: patient superior.&lt;br /&gt;
    :param backupViewRightDirection Slice view will be spinned in-plane to match point approximately this right direction&lt;br /&gt;
        if defaultViewUpDirection is too similar to sliceNormal. Default: patient left.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Fix up input directions&lt;br /&gt;
    if defaultViewUpDirection is None:&lt;br /&gt;
        defaultViewUpDirection = [0,0,1]&lt;br /&gt;
    if backupViewRightDirection is None:&lt;br /&gt;
        backupViewRightDirection = [-1,0,0]&lt;br /&gt;
    if sliceNormal[1]&amp;gt;=0:&lt;br /&gt;
        sliceNormalStandardized = sliceNormal&lt;br /&gt;
    else:&lt;br /&gt;
        sliceNormalStandardized = [-sliceNormal[0], -sliceNormal[1], -sliceNormal[2]]&lt;br /&gt;
    # Compute slice axes&lt;br /&gt;
    sliceNormalViewUpAngle = vtk.vtkMath.AngleBetweenVectors(sliceNormalStandardized, defaultViewUpDirection)&lt;br /&gt;
    angleTooSmallThresholdRad = 0.25 # about 15 degrees&lt;br /&gt;
    if sliceNormalViewUpAngle &amp;gt; angleTooSmallThresholdRad and sliceNormalViewUpAngle &amp;lt; vtk.vtkMath.Pi() - angleTooSmallThresholdRad:&lt;br /&gt;
        viewUpDirection = defaultViewUpDirection&lt;br /&gt;
        sliceAxisY = viewUpDirection&lt;br /&gt;
        sliceAxisX = [0, 0, 0]&lt;br /&gt;
        vtk.vtkMath.Cross(sliceAxisY, sliceNormalStandardized, sliceAxisX)&lt;br /&gt;
    else:&lt;br /&gt;
        sliceAxisX = backupViewRightDirection&lt;br /&gt;
    # Set slice axes&lt;br /&gt;
    sliceNode.SetSliceToRASByNTP(sliceNormalStandardized[0], sliceNormalStandardized[1], sliceNormalStandardized[2],&lt;br /&gt;
        sliceAxisX[0], sliceAxisX[1], sliceAxisX[2],&lt;br /&gt;
        slicePosition[0], slicePosition[1], slicePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Example usage:&lt;br /&gt;
sliceNode = getNode('vtkMRMLSliceNodeRed')&lt;br /&gt;
transformNode = getNode('Transform_3')&lt;br /&gt;
transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
transformNode.GetMatrixTransformToParent(transformMatrix)&lt;br /&gt;
sliceNormal = [transformMatrix.GetElement(0,2), transformMatrix.GetElement(1,2), transformMatrix.GetElement(2,2)]&lt;br /&gt;
slicePosition = [transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)]&lt;br /&gt;
setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Switching to markup fiducial placement mode ==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change markup fiducial display properties ==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a markup point position is modified ==&lt;br /&gt;
&lt;br /&gt;
Event management of Slicer-4.11 version is still subject to change. The example below shows how point manipulation can be observed now.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupChanged(caller,event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    if movingMarkupIndex &amp;gt;= 0:&lt;br /&gt;
        pos = [0,0,0]&lt;br /&gt;
        markupsNode.GetNthFiducialPosition(movingMarkupIndex, pos)&lt;br /&gt;
        isPreview = markupsNode.GetNthControlPointPositionStatus(movingMarkupIndex) == slicer.vtkMRMLMarkupsNode.PositionPreview&lt;br /&gt;
        if isPreview:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} is previewed at {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
        else:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} was moved {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
    else:&lt;br /&gt;
        logging.info(&amp;quot;Points modified: slice view = {0}&amp;quot;.format(sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupStartInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()    &lt;br /&gt;
    logging.info(&amp;quot;Start interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupEndInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    logging.info(&amp;quot;End interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, onMarkupChanged)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointStartInteractionEvent, onMarkupStartInteraction)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointEndInteractionEvent, onMarkupEndInteraction)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a transform is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a context menu when a markup point is clicked in a slice or 3D view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Example actions to perform&lt;br /&gt;
&lt;br /&gt;
def action1():&lt;br /&gt;
  print('Action1 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action2():&lt;br /&gt;
  print('Action2 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action3():&lt;br /&gt;
  print('Action3 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
# Clicked markup index is saved here to let the action&lt;br /&gt;
# know which markup needs to be manipulated.&lt;br /&gt;
slicer.clickedMarkupIndex = -1&lt;br /&gt;
  &lt;br /&gt;
# Create a simple menu&lt;br /&gt;
&lt;br /&gt;
menu = qt.QMenu()&lt;br /&gt;
a1 = qt.QAction(&amp;quot;Test&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a1.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a1)&lt;br /&gt;
a2 = qt.QAction(&amp;quot;Action&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a2.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a2)&lt;br /&gt;
a3 = qt.QAction(&amp;quot;Here&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a3.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a3)&lt;br /&gt;
&lt;br /&gt;
# Add observer to a markup fiducial list&lt;br /&gt;
&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_INT)&lt;br /&gt;
def markupClickedCallback(caller, eventId, callData):&lt;br /&gt;
  slicer.clickedMarkupIndex = callData&lt;br /&gt;
  print('Open menu on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
  menu.move(qt.QCursor.pos())&lt;br /&gt;
  menu.show()&lt;br /&gt;
&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
observerTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointClickedEvent, markupClickedCallback)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write markup positions to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write annotation ROI to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a simple surface mesh as a model node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to display a simple surface mesh (a box, created by a VTK source filter) as a model node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create and set up polydata source&lt;br /&gt;
box = vtk.vtkCubeSource()&lt;br /&gt;
box.SetXLength(30)&lt;br /&gt;
box.SetYLength(20)&lt;br /&gt;
box.SetZLength(15)&lt;br /&gt;
box.SetCenter(10,20,5)&lt;br /&gt;
&lt;br /&gt;
# Create a model node that displays output of the source&lt;br /&gt;
boxNode = slicer.modules.models.logic().AddModel(box.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Adjust display properties&lt;br /&gt;
boxNode.GetDisplayNode().SetColor(1,0,0)&lt;br /&gt;
boxNode.GetDisplayNode().SetOpacity(0.8)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add a texture mapped plane to the scene as a model ==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# use dummy image data here&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
&lt;br /&gt;
scene = slicer.mrmlScene&lt;br /&gt;
&lt;br /&gt;
# Create model node&lt;br /&gt;
model = slicer.vtkMRMLModelNode()&lt;br /&gt;
model.SetScene(scene)&lt;br /&gt;
model.SetName(scene.GenerateUniqueName(&amp;quot;2DImageModel&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
model.SetAndObservePolyData(planeSource.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create display node&lt;br /&gt;
modelDisplay = slicer.vtkMRMLModelDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
modelDisplay.SetScene(scene)&lt;br /&gt;
scene.AddNode(modelDisplay)&lt;br /&gt;
model.SetAndObserveDisplayNodeID(modelDisplay.GetID())&lt;br /&gt;
&lt;br /&gt;
# Add to scene&lt;br /&gt;
modelDisplay.SetAndObserveTextureImageData(e.GetOutput())&lt;br /&gt;
scene.AddNode(model) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
transform = slicer.vtkMRMLLinearTransformNode()&lt;br /&gt;
scene.AddNode(transform) &lt;br /&gt;
model.SetAndObserveTransformNodeID(transform.GetID())&lt;br /&gt;
&lt;br /&gt;
vTransform = vtk.vtkTransform()&lt;br /&gt;
vTransform.Scale(50,50,50)&lt;br /&gt;
vTransform.RotateX(30)&lt;br /&gt;
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get scalar values at surface of a model ==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Select cells of a using markups fiducial points ==&lt;br /&gt;
&lt;br /&gt;
The following script selects cells of a model node that are closest to positions of markups fiducial points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get input nodes&lt;br /&gt;
modelNode = slicer.util.getNode('Segment_1') # select cells in this model&lt;br /&gt;
markupsNode = slicer.util.getNode('F') # points will be selected at positions specified by this markups fiducial node&lt;br /&gt;
&lt;br /&gt;
# Create scalar array that will store selection state&lt;br /&gt;
selectionArray = vtk.vtkIntArray()&lt;br /&gt;
selectionArray.SetName('selection')&lt;br /&gt;
selectionArray.SetNumberOfValues(modelNode.GetMesh().GetNumberOfCells())&lt;br /&gt;
selectionArray.Fill(0)&lt;br /&gt;
&lt;br /&gt;
cellScalars = modelPointValues = modelNode.GetMesh().GetCellData()&lt;br /&gt;
cellScalars.AddArray(selectionArray)&lt;br /&gt;
&lt;br /&gt;
modelNode.GetDisplayNode().SetActiveScalar(&amp;quot;selection&amp;quot;, vtk.vtkAssignAttribute.CELL_DATA)&lt;br /&gt;
modelNode.GetDisplayNode().SetScalarVisibility(True)&lt;br /&gt;
&lt;br /&gt;
cell = vtk.vtkCellLocator()&lt;br /&gt;
cell.SetDataSet(modelNode.GetMesh())&lt;br /&gt;
cell.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onPointsModified(observer=None, eventid=None):&lt;br /&gt;
    global markupsNode, selectionArray&lt;br /&gt;
    selectionArray.Fill(0) # set all cells to non-selected by default&lt;br /&gt;
    markupPoints = slicer.util.arrayFromMarkupsControlPoints(markupsNode)&lt;br /&gt;
    for markupPoint in markupPoints:&lt;br /&gt;
        closestCell = cell.FindCell(markupPoint)&lt;br /&gt;
        if closestCell &amp;gt;=0:&lt;br /&gt;
            selectionArray.SetValue(closestCell, 100) # set selected cell's scalar value to non-zero&lt;br /&gt;
    selectionArray.Modified()&lt;br /&gt;
&lt;br /&gt;
# Initial update&lt;br /&gt;
onPointsModified()&lt;br /&gt;
# Automatic update each time when a markup point is modified&lt;br /&gt;
markupsNodeObserverTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsFiducialNode.PointModifiedEvent, onPointsModified)&lt;br /&gt;
&lt;br /&gt;
# To stop updating selection, run this:&lt;br /&gt;
# markupsNode.RemoveObserver(markupsNodeObserverTag)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export entire scene as VRML ==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export model to Blender, including color by scalar ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export a tract (FiberBundle) to Blender, including color ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Iterate over tract (FiberBundle) streamline points ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a volume ==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a new volume ==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
imageData.GetPointData().GetScalars().Fill(fillVoxelValue)&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify voxels in a volume ==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.SetScalarComponentFromFloat(distortionVectorPosition_Ijk[0], distortionVectorPosition_Ijk[1], distortionVectorPosition_Ijk[2], 0, fillValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get volume voxel coordinates from markup fiducial RAS coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get markup fiducial RAS coordinates from volume voxel coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get the values of all voxels for a label value  ==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Access values in a DTI tensor volume ==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change window/level (brightness/contrast) or colormap of a volume ==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Make mouse left-click and drag on the image adjust window/level ==&lt;br /&gt;
&lt;br /&gt;
In older Slicer versions, by default, left-click and drag in a slice view adjusted window/level of the displayed image. Window/level adjustment is now a new mouse mode that can be activated by clicking on its toolbar button or running this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.applicationLogic().GetInteractionNode().SetCurrentInteractionMode(slicer.vtkMRMLInteractionNode.AdjustWindowLevel)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create custom color table ==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Manipulate a Slice View ==&lt;br /&gt;
&lt;br /&gt;
=== Change slice offset ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Change slice orientation ===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show slice views in 3D window ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reset field of view to show background volume maximized ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rotate slice views to volume plane ===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Iterate over current visible slice views, and set foreground and background images ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     sliceWidget = layoutManager.sliceWidget(sliceViewName)&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Synchronize zoom factor between slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.sliceNodes = [slicer.app.layoutManager().sliceWidget(viewName).mrmlSliceNode()&lt;br /&gt;
    for viewName in slicer.app.layoutManager().sliceViewNames()]&lt;br /&gt;
&lt;br /&gt;
slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
def sliceModified(caller, event):&lt;br /&gt;
    if slicer.updatingSliceNodes:&lt;br /&gt;
        # prevent infinite loop of slice node updates triggering slice node updates&lt;br /&gt;
        return&lt;br /&gt;
    slicer.updatingSliceNodes = True&lt;br /&gt;
    fov = caller.GetFieldOfView()&lt;br /&gt;
    for sliceNode in slicer.sliceNodes:&lt;br /&gt;
        if sliceNode != caller:&lt;br /&gt;
            sliceNode.SetFieldOfView(*fov)&lt;br /&gt;
    slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
for sliceNode in slicer.sliceNodes:&lt;br /&gt;
    sliceNode.AddObserver(vtk.vtkCommand.ModifiedEvent, sliceModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change opacity of foreground volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fit slice plane to markup fiducials ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.array([0,0,0])&lt;br /&gt;
p2 = np.array([0,0,0])&lt;br /&gt;
p3 = np.array([0,0,0])&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0, 0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a series of images from a Slice View ==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a new directory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a single MRB file ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a node to file ==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Center the 3D View on the Scene ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Display text in a 3D view or slice view ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide slice view annotations (DataProbe) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Turning off interpolation ==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Customize viewer layout ==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;layout type=&amp;quot;vertical&amp;quot; split=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLSliceNode&amp;quot; singletontag=&amp;quot;Red&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;orientation&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewcolor&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/layout&amp;gt;&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Built-in layout IDs are all below 100, so you can choose any large random number&lt;br /&gt;
# for your custom layout ID.&lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
&lt;br /&gt;
# Switch to the new custom layout &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
You can use this code snippet to add a button to the layout selector toolbar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Add button to layout selector toolbar for this custom layout&lt;br /&gt;
viewToolBar = mainWindow().findChild('QToolBar', 'ViewToolBar')&lt;br /&gt;
layoutMenu = viewToolBar.widgetForAction(viewToolBar.actions()[0]).menu()&lt;br /&gt;
layoutSwitchActionParent = layoutMenu  # use `layoutMenu` to add inside layout list, use `viewToolBar` to add next the standard layout list&lt;br /&gt;
layoutSwitchAction = layoutSwitchActionParent.addAction(&amp;quot;My view&amp;quot;) # add inside layout list&lt;br /&gt;
layoutSwitchAction.setIcon(qt.QIcon(':Icons/Go.png'))&lt;br /&gt;
layoutSwitchAction.setToolTip('3D and slice view')&lt;br /&gt;
layoutSwitchAction.connect('triggered()', lambda layoutId = customLayoutId: slicer.app.layoutManager().setLayout(layoutId))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Customize keyboard shortcuts ==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Disable certain user interactions in slice views ==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change default slice view orientation ==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Set all slice views linked by default ==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set crosshair jump mode to centered by default ==&lt;br /&gt;
&lt;br /&gt;
You can change default slice jump mode (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
crosshair=slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLCrosshairNode&amp;quot;)&lt;br /&gt;
crosshair.SetCrosshairBehavior(crosshair.CenteredJumpSlice)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set up custom units in slice view ruler ==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in range(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a slice view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;TS&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
viewNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(layoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
viewWidget.sliceViewName = layoutName&lt;br /&gt;
viewWidget.sliceViewLabel = layoutLabel&lt;br /&gt;
c = viewNode.GetLayoutColor()&lt;br /&gt;
viewWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLSliceNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a 3D view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;Test3DView&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;T3&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML node&lt;br /&gt;
viewNode = slicer.vtkMRMLViewNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLThreeDWidget()&lt;br /&gt;
viewWidget.viewLabel = layoutLabel&lt;br /&gt;
viewWidget.viewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLViewNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get displayable manager of a certain type for a certain view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelDisplayableManager = None&lt;br /&gt;
threeDViewWidget = slicer.app.layoutManager().threeDWidget(0)&lt;br /&gt;
managers = vtk.vtkCollection()&lt;br /&gt;
threeDViewWidget.getDisplayableManagers(managers)&lt;br /&gt;
for i in range(managers.GetNumberOfItems()):&lt;br /&gt;
  obj = managers.GetItemAsObject(i)&lt;br /&gt;
  if obj.IsA('vtkMRMLModelDisplayableManager'):&lt;br /&gt;
    modelDisplayableManager = obj&lt;br /&gt;
    break&lt;br /&gt;
if modelDisplayableManager is None:&lt;br /&gt;
  logging.error('Failed to find the model displayable manager')&lt;br /&gt;
  return&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Running an ITK filter in Python using SimpleITK ==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
* See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
* 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&lt;br /&gt;
&lt;br /&gt;
== Get current mouse coordinates in a slice view ==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get DataProbe text ==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get reformatted image from a slice viewer as numpy array ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print voxels.shape&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thick slab reconstruction and maximum/minimum intensity volume projections ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
== Change default file type for nodes (that have never been saved yet) ==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
== Change file type for saving for all volumes (with already existing storage nodes) ==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sequences ==&lt;br /&gt;
&lt;br /&gt;
=== Concatenate all sequences in the scene into a new sequence ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Segmentations ==&lt;br /&gt;
&lt;br /&gt;
=== Create a segmentation from a labelmap volume and display in 3D ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
=== Export labelmap node from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
Export smallest possible labelmap:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export labelmap that matches geometry of a chosen reference volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export by pressing Ctrl+Shift+s key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPath = &amp;quot;c:/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def exportLabelmap():&lt;br /&gt;
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLSegmentationNode&amp;quot;)&lt;br /&gt;
    referenceVolumeNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
    labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
    slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
    filepath = outputPath + &amp;quot;/&amp;quot; + referenceVolumeNode.GetName()+&amp;quot;-label.nrrd&amp;quot;&lt;br /&gt;
    slicer.util.saveNode(labelmapVolumeNode, filepath)&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode.GetDisplayNode().GetColorNode())&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
    slicer.util.delayDisplay(&amp;quot;Segmentation saved to &amp;quot;+filepath)&lt;br /&gt;
&lt;br /&gt;
shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
shortcut.setKey(qt.QKeySequence('Ctrl+Shift+s'))&lt;br /&gt;
shortcut.connect( 'activated()', exportLabelmap)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Export model nodes from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
exportedModelsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelHierarchyNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModelHierarchy(seg, exportedModelsNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show a segmentation in 3D ===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get a representation of a segment ===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = segmentationNode.GetBinaryLabelmapRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using default path and conversion parameters ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using custom path or conversion parameters ===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-convert using a modified conversion parameter ===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get centroid of a segment in world (RAS) coordinates ===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How to run segment editor effects from a script ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
* [https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
* [https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
* [https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
* [https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
== Accessing views, renderers, and cameras ==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide view controller bars ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Customize widgets in view controller bars ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceController = slicer.app.layoutManager().sliceWidget(&amp;quot;Red&amp;quot;).sliceController()&lt;br /&gt;
&lt;br /&gt;
# hide what is not needed&lt;br /&gt;
sliceController.pinButton().hide()&lt;br /&gt;
#sliceController.viewLabel().hide()&lt;br /&gt;
sliceController.fitToWindowToolButton().hide()&lt;br /&gt;
sliceController.sliceOffsetSlider().hide()&lt;br /&gt;
&lt;br /&gt;
# add custom widgets&lt;br /&gt;
myButton = qt.QPushButton(&amp;quot;My custom button&amp;quot;)&lt;br /&gt;
sliceController.barLayout().addWidget(b)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change 3D view background color ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderer = renderWindow.GetRenderers().GetFirstRenderer()&lt;br /&gt;
renderer.SetBackground(1,0,0)&lt;br /&gt;
renderer.SetBackground2(1,0,0)&lt;br /&gt;
renderWindow.Render()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subject hierarchy == &lt;br /&gt;
==== Get the pseudo-singleton subject hierarchy node ====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.mrmlScene.GetSubjectHierarchyNode()&lt;br /&gt;
&lt;br /&gt;
==== Create subject hierarchy item ====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
==== Get subject hierarchy item ====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
==== Traverse children of a subject hierarchy item ====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in range(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
==== Manipulate subject hierarchy item ====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data node associated to an item&lt;br /&gt;
  shNode.SetItemDisplayVisibility(itemID, 1)&lt;br /&gt;
  # Set visibility of whole branch&lt;br /&gt;
  # Note: Folder-type items (fodler, subject, study, etc.) create their own display nodes when show/hiding from UI.&lt;br /&gt;
  #       The displayable managers use SH information to determine visibility of an item, so no need to show/hide individual leaf nodes any more.&lt;br /&gt;
  #       Once the folder display node is created, it can be shown hidden simply using shNode.SetItemDisplayVisibility&lt;br /&gt;
  # From python, this is how to trigger creating a folder display node&lt;br /&gt;
  pluginHandler = slicer.qSlicerSubjectHierarchyPluginHandler().instance()&lt;br /&gt;
  folderPlugin = pluginHandler.pluginByName('Folder')&lt;br /&gt;
  folderPlugin.setDisplayVisibility(folderItemID, 1)&lt;br /&gt;
&lt;br /&gt;
==== Filter items in TreeView or ComboBox ====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
=== Listen to subject hierarchy item events ===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
== Plotting ==&lt;br /&gt;
&lt;br /&gt;
=== Slicer plots displayed in view layout ===&lt;br /&gt;
&lt;br /&gt;
Create histogram plot of a volume and show it embedded in the view layout. More information: https://www.slicer.org/wiki/Documentation/Nightly/Developers/Plots&lt;br /&gt;
&lt;br /&gt;
==== Using &amp;lt;code&amp;gt;slicer.util.plot&amp;lt;/code&amp;gt; utility function ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
chartNode = slicer.util.plot(histogram, xColumnIndex = 1)&lt;br /&gt;
chartNode.SetYAxisRangeAuto(False)&lt;br /&gt;
chartNode.SetYAxisRange(0, 4e5)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:SlicerPlot.png]]&lt;br /&gt;
&lt;br /&gt;
==== Using MRML classes only ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using matplotlib ===&lt;br /&gt;
&lt;br /&gt;
Matplotlib may be used from within Slicer, but the default Tk backend locks up and crashes Slicer. However, Matplotlib may still be used through other backends. More details can be found on the [http://matplotlib.sourceforge.net/ MatPlotLib] pages.&lt;br /&gt;
&lt;br /&gt;
==== Non-interactive plot ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
&lt;br /&gt;
# Static image view&lt;br /&gt;
pm = qt.QPixmap(&amp;quot;MatplotlibExample.png&amp;quot;)&lt;br /&gt;
imageWidget = qt.QLabel()&lt;br /&gt;
imageWidget.setPixmap(pm)&lt;br /&gt;
imageWidget.setScaledContents(True)&lt;br /&gt;
imageWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:MatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==== Plot in Slicer Jupyter notebook ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
display(filename='MatplotlibExample.png', type=&amp;quot;image/png&amp;quot;, binary=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:JupyterNotebookMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==== Interactive plot using wxWidgets GUI toolkit ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
  import wx&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib wxPython')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Set matplotlib to use WXAgg backend&lt;br /&gt;
import matplotlib&lt;br /&gt;
matplotlib.use('WXAgg')&lt;br /&gt;
&lt;br /&gt;
# Show an interactive plot&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
fig, ax = plt.subplots()&lt;br /&gt;
ax.plot(histogram[1][1:], histogram[0].astype(float))&lt;br /&gt;
ax.grid(True)&lt;br /&gt;
ax.set_ylim((0, 4e5))&lt;br /&gt;
plt.show(block=False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:InteractiveMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
== Execute external applications ==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
=== Run process in default environment ===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;br /&gt;
&lt;br /&gt;
== Manage extensions ==&lt;br /&gt;
&lt;br /&gt;
=== Download and install extension ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensionName = 'SlicerIGT'&lt;br /&gt;
em = slicer.app.extensionsManagerModel()&lt;br /&gt;
if not em.isExtensionInstalled(extensionName):&lt;br /&gt;
    extensionMetaData = em.retrieveExtensionMetadataByName(extensionName)&lt;br /&gt;
    url = em.serverUrl().toString()+'/download/item/'+extensionMetaData['item_id']&lt;br /&gt;
    extensionPackageFilename = slicer.app.temporaryPath+'/'+extensionMetaData['md5']&lt;br /&gt;
    slicer.util.downloadFile(url, extensionPackageFilename)&lt;br /&gt;
    em.installExtension(extensionPackageFilename)&lt;br /&gt;
    slicer.util.restart()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61480</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61480"/>
		<updated>2019-10-01T14:04:57Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Get the pseudo-singleton subject hierarchy node */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=&lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the [[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
* [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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
* [https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
* [https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
* [https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
* Capture the full Slicer screen and save it into a file&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
* Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
* Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
* How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
* How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loadedVolumeNode = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Automatically load volumes that are copied into a folder ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to implement a simple background task by using a timer. The background task is to check for any new volume files in folder and if there is any then automatically load it.&lt;br /&gt;
&lt;br /&gt;
There are more efficient methods for file system monitoring or exchanging image data in real-time (for example, using OpenIGTLink), the example below is just for demonstration purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
incomingVolumeFolder = &amp;quot;c:/tmp/incoming&amp;quot;&lt;br /&gt;
incomingVolumesProcessed = []&lt;br /&gt;
&lt;br /&gt;
def checkForNewVolumes():&lt;br /&gt;
  # Check if there is a new file in the &lt;br /&gt;
  from os import listdir&lt;br /&gt;
  from os.path import isfile, join&lt;br /&gt;
  for f in listdir(incomingVolumeFolder):&lt;br /&gt;
    if f in incomingVolumesProcessed:&lt;br /&gt;
      # this is an incoming file, it was already there&lt;br /&gt;
      continue&lt;br /&gt;
    filePath = join(incomingVolumeFolder, f)&lt;br /&gt;
    if not isfile(filePath):&lt;br /&gt;
      # ignore directories&lt;br /&gt;
      continue&lt;br /&gt;
    logging.info(&amp;quot;Loading new file: &amp;quot;+f)&lt;br /&gt;
    incomingVolumesProcessed.append(f)&lt;br /&gt;
    slicer.util.loadVolume(filePath)&lt;br /&gt;
  # Check again in 3000ms&lt;br /&gt;
  qt.QTimer.singleShot(3000, checkForNewVolumes)&lt;br /&gt;
&lt;br /&gt;
# Start monitoring&lt;br /&gt;
checkForNewVolumes()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
=== How to access top level tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # Note, fileValue accesses the database of cached top level tags&lt;br /&gt;
  # (nested tags are not included)&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
=== How to access DICOM tags nested in a sequence ===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # use pydicom to access the full header, which requires&lt;br /&gt;
  # re-reading the dataset instead of using the database cache&lt;br /&gt;
  import pydicom&lt;br /&gt;
  pydicom.dcmread(fileList[0])&lt;br /&gt;
  ds.CTExposureSequence[0].ExposureModulationType&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
=== How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
=== How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm'); slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Export a volume to DICOM file format ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Customize table columns in DICOM browser ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database() # Need to go this way, do not use slicer.dicomDatabase for this&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
* How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
for viewNode in viewNodes:&lt;br /&gt;
  viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
* How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Measure angle between two slice planes==&lt;br /&gt;
&lt;br /&gt;
Measure angle between red and yellow slice nodes. Whenever any of the slice nodes are moved, the updated angle is printed on the console.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeIds = ['vtkMRMLSliceNodeRed', 'vtkMRMLSliceNodeYellow']&lt;br /&gt;
&lt;br /&gt;
# Print angles between slice nodes&lt;br /&gt;
def ShowAngle(unused1=None, unused2=None):&lt;br /&gt;
    sliceNormalVector = []&lt;br /&gt;
    for sliceNodeId in sliceNodeIds:&lt;br /&gt;
        sliceToRAS = slicer.mrmlScene.GetNodeByID(sliceNodeId).GetSliceToRAS()&lt;br /&gt;
        sliceNormalVector.append([sliceToRAS.GetElement(0,2), sliceToRAS.GetElement(1,2), sliceToRAS.GetElement(2,2)])&lt;br /&gt;
    angleRad = vtk.vtkMath.AngleBetweenVectors(sliceNormalVector[0], sliceNormalVector[1])&lt;br /&gt;
    angleDeg = vtk.vtkMath.DegreesFromRadians(angleRad)&lt;br /&gt;
    print('Angle between slice planes = {0:0.3f}'.format(angleDeg))&lt;br /&gt;
&lt;br /&gt;
# Observe slice node changes&lt;br /&gt;
for sliceNodeId in sliceNodeIds:&lt;br /&gt;
    slicer.mrmlScene.GetNodeByID(sliceNodeId).AddObserver(vtk.vtkCommand.ModifiedEvent, ShowAngle)&lt;br /&gt;
&lt;br /&gt;
# Print current angle&lt;br /&gt;
ShowAngle()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from a normal vector and position==&lt;br /&gt;
&lt;br /&gt;
This code snippet shows how to display a slice view defined by a normal vector and position in an anatomically sensible way: rotating slice view so that &amp;quot;up&amp;quot; direction (or &amp;quot;right&amp;quot; direction) is towards an anatomical axis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition, defaultViewUpDirection=None, backupViewRightDirection=None):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Set slice pose from the provided plane normal and position. View up direction is determined automatically,&lt;br /&gt;
    to make view up point towards defaultViewUpDirection.&lt;br /&gt;
    :param defaultViewUpDirection Slice view will be spinned in-plane to match point approximately this up direction. Default: patient superior.&lt;br /&gt;
    :param backupViewRightDirection Slice view will be spinned in-plane to match point approximately this right direction&lt;br /&gt;
        if defaultViewUpDirection is too similar to sliceNormal. Default: patient left.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Fix up input directions&lt;br /&gt;
    if defaultViewUpDirection is None:&lt;br /&gt;
        defaultViewUpDirection = [0,0,1]&lt;br /&gt;
    if backupViewRightDirection is None:&lt;br /&gt;
        backupViewRightDirection = [-1,0,0]&lt;br /&gt;
    if sliceNormal[1]&amp;gt;=0:&lt;br /&gt;
        sliceNormalStandardized = sliceNormal&lt;br /&gt;
    else:&lt;br /&gt;
        sliceNormalStandardized = [-sliceNormal[0], -sliceNormal[1], -sliceNormal[2]]&lt;br /&gt;
    # Compute slice axes&lt;br /&gt;
    sliceNormalViewUpAngle = vtk.vtkMath.AngleBetweenVectors(sliceNormalStandardized, defaultViewUpDirection)&lt;br /&gt;
    angleTooSmallThresholdRad = 0.25 # about 15 degrees&lt;br /&gt;
    if sliceNormalViewUpAngle &amp;gt; angleTooSmallThresholdRad and sliceNormalViewUpAngle &amp;lt; vtk.vtkMath.Pi() - angleTooSmallThresholdRad:&lt;br /&gt;
        viewUpDirection = defaultViewUpDirection&lt;br /&gt;
        sliceAxisY = viewUpDirection&lt;br /&gt;
        sliceAxisX = [0, 0, 0]&lt;br /&gt;
        vtk.vtkMath.Cross(sliceAxisY, sliceNormalStandardized, sliceAxisX)&lt;br /&gt;
    else:&lt;br /&gt;
        sliceAxisX = backupViewRightDirection&lt;br /&gt;
    # Set slice axes&lt;br /&gt;
    sliceNode.SetSliceToRASByNTP(sliceNormalStandardized[0], sliceNormalStandardized[1], sliceNormalStandardized[2],&lt;br /&gt;
        sliceAxisX[0], sliceAxisX[1], sliceAxisX[2],&lt;br /&gt;
        slicePosition[0], slicePosition[1], slicePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Example usage:&lt;br /&gt;
sliceNode = getNode('vtkMRMLSliceNodeRed')&lt;br /&gt;
transformNode = getNode('Transform_3')&lt;br /&gt;
transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
transformNode.GetMatrixTransformToParent(transformMatrix)&lt;br /&gt;
sliceNormal = [transformMatrix.GetElement(0,2), transformMatrix.GetElement(1,2), transformMatrix.GetElement(2,2)]&lt;br /&gt;
slicePosition = [transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)]&lt;br /&gt;
setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Switching to markup fiducial placement mode ==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change markup fiducial display properties ==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a markup point position is modified ==&lt;br /&gt;
&lt;br /&gt;
Event management of Slicer-4.11 version is still subject to change. The example below shows how point manipulation can be observed now.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupChanged(caller,event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    if movingMarkupIndex &amp;gt;= 0:&lt;br /&gt;
        pos = [0,0,0]&lt;br /&gt;
        markupsNode.GetNthFiducialPosition(movingMarkupIndex, pos)&lt;br /&gt;
        isPreview = markupsNode.GetNthControlPointPositionStatus(movingMarkupIndex) == slicer.vtkMRMLMarkupsNode.PositionPreview&lt;br /&gt;
        if isPreview:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} is previewed at {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
        else:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} was moved {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
    else:&lt;br /&gt;
        logging.info(&amp;quot;Points modified: slice view = {0}&amp;quot;.format(sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupStartInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()    &lt;br /&gt;
    logging.info(&amp;quot;Start interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupEndInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    logging.info(&amp;quot;End interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, onMarkupChanged)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointStartInteractionEvent, onMarkupStartInteraction)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointEndInteractionEvent, onMarkupEndInteraction)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a transform is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a context menu when a markup point is clicked in a slice or 3D view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Example actions to perform&lt;br /&gt;
&lt;br /&gt;
def action1():&lt;br /&gt;
  print('Action1 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action2():&lt;br /&gt;
  print('Action2 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action3():&lt;br /&gt;
  print('Action3 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
# Clicked markup index is saved here to let the action&lt;br /&gt;
# know which markup needs to be manipulated.&lt;br /&gt;
slicer.clickedMarkupIndex = -1&lt;br /&gt;
  &lt;br /&gt;
# Create a simple menu&lt;br /&gt;
&lt;br /&gt;
menu = qt.QMenu()&lt;br /&gt;
a1 = qt.QAction(&amp;quot;Test&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a1.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a1)&lt;br /&gt;
a2 = qt.QAction(&amp;quot;Action&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a2.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a2)&lt;br /&gt;
a3 = qt.QAction(&amp;quot;Here&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a3.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a3)&lt;br /&gt;
&lt;br /&gt;
# Add observer to a markup fiducial list&lt;br /&gt;
&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_INT)&lt;br /&gt;
def markupClickedCallback(caller, eventId, callData):&lt;br /&gt;
  slicer.clickedMarkupIndex = callData&lt;br /&gt;
  print('Open menu on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
  menu.move(qt.QCursor.pos())&lt;br /&gt;
  menu.show()&lt;br /&gt;
&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
observerTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointClickedEvent, markupClickedCallback)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write markup positions to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write annotation ROI to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a simple surface mesh as a model node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to display a simple surface mesh (a box, created by a VTK source filter) as a model node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create and set up polydata source&lt;br /&gt;
box = vtk.vtkCubeSource()&lt;br /&gt;
box.SetXLength(30)&lt;br /&gt;
box.SetYLength(20)&lt;br /&gt;
box.SetZLength(15)&lt;br /&gt;
box.SetCenter(10,20,5)&lt;br /&gt;
&lt;br /&gt;
# Create a model node that displays output of the source&lt;br /&gt;
boxNode = slicer.modules.models.logic().AddModel(box.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Adjust display properties&lt;br /&gt;
boxNode.GetDisplayNode().SetColor(1,0,0)&lt;br /&gt;
boxNode.GetDisplayNode().SetOpacity(0.8)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add a texture mapped plane to the scene as a model ==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# use dummy image data here&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
&lt;br /&gt;
scene = slicer.mrmlScene&lt;br /&gt;
&lt;br /&gt;
# Create model node&lt;br /&gt;
model = slicer.vtkMRMLModelNode()&lt;br /&gt;
model.SetScene(scene)&lt;br /&gt;
model.SetName(scene.GenerateUniqueName(&amp;quot;2DImageModel&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
model.SetAndObservePolyData(planeSource.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create display node&lt;br /&gt;
modelDisplay = slicer.vtkMRMLModelDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
modelDisplay.SetScene(scene)&lt;br /&gt;
scene.AddNode(modelDisplay)&lt;br /&gt;
model.SetAndObserveDisplayNodeID(modelDisplay.GetID())&lt;br /&gt;
&lt;br /&gt;
# Add to scene&lt;br /&gt;
modelDisplay.SetAndObserveTextureImageData(e.GetOutput())&lt;br /&gt;
scene.AddNode(model) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
transform = slicer.vtkMRMLLinearTransformNode()&lt;br /&gt;
scene.AddNode(transform) &lt;br /&gt;
model.SetAndObserveTransformNodeID(transform.GetID())&lt;br /&gt;
&lt;br /&gt;
vTransform = vtk.vtkTransform()&lt;br /&gt;
vTransform.Scale(50,50,50)&lt;br /&gt;
vTransform.RotateX(30)&lt;br /&gt;
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get scalar values at surface of a model ==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Select cells of a using markups fiducial points ==&lt;br /&gt;
&lt;br /&gt;
The following script selects cells of a model node that are closest to positions of markups fiducial points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get input nodes&lt;br /&gt;
modelNode = slicer.util.getNode('Segment_1') # select cells in this model&lt;br /&gt;
markupsNode = slicer.util.getNode('F') # points will be selected at positions specified by this markups fiducial node&lt;br /&gt;
&lt;br /&gt;
# Create scalar array that will store selection state&lt;br /&gt;
selectionArray = vtk.vtkIntArray()&lt;br /&gt;
selectionArray.SetName('selection')&lt;br /&gt;
selectionArray.SetNumberOfValues(modelNode.GetMesh().GetNumberOfCells())&lt;br /&gt;
selectionArray.Fill(0)&lt;br /&gt;
&lt;br /&gt;
cellScalars = modelPointValues = modelNode.GetMesh().GetCellData()&lt;br /&gt;
cellScalars.AddArray(selectionArray)&lt;br /&gt;
&lt;br /&gt;
modelNode.GetDisplayNode().SetActiveScalar(&amp;quot;selection&amp;quot;, vtk.vtkAssignAttribute.CELL_DATA)&lt;br /&gt;
modelNode.GetDisplayNode().SetScalarVisibility(True)&lt;br /&gt;
&lt;br /&gt;
cell = vtk.vtkCellLocator()&lt;br /&gt;
cell.SetDataSet(modelNode.GetMesh())&lt;br /&gt;
cell.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onPointsModified(observer=None, eventid=None):&lt;br /&gt;
    global markupsNode, selectionArray&lt;br /&gt;
    selectionArray.Fill(0) # set all cells to non-selected by default&lt;br /&gt;
    markupPoints = slicer.util.arrayFromMarkupsControlPoints(markupsNode)&lt;br /&gt;
    for markupPoint in markupPoints:&lt;br /&gt;
        closestCell = cell.FindCell(markupPoint)&lt;br /&gt;
        if closestCell &amp;gt;=0:&lt;br /&gt;
            selectionArray.SetValue(closestCell, 100) # set selected cell's scalar value to non-zero&lt;br /&gt;
    selectionArray.Modified()&lt;br /&gt;
&lt;br /&gt;
# Initial update&lt;br /&gt;
onPointsModified()&lt;br /&gt;
# Automatic update each time when a markup point is modified&lt;br /&gt;
markupsNodeObserverTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsFiducialNode.PointModifiedEvent, onPointsModified)&lt;br /&gt;
&lt;br /&gt;
# To stop updating selection, run this:&lt;br /&gt;
# markupsNode.RemoveObserver(markupsNodeObserverTag)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export entire scene as VRML ==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export model to Blender, including color by scalar ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export a tract (FiberBundle) to Blender, including color ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Iterate over tract (FiberBundle) streamline points ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a volume ==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a new volume ==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
imageData.GetPointData().GetScalars().Fill(fillVoxelValue)&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(imageData)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify voxels in a volume ==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.SetScalarComponentFromFloat(distortionVectorPosition_Ijk[0], distortionVectorPosition_Ijk[1], distortionVectorPosition_Ijk[2], 0, fillValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get volume voxel coordinates from markup fiducial RAS coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get markup fiducial RAS coordinates from volume voxel coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get the values of all voxels for a label value  ==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Access values in a DTI tensor volume ==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change window/level (brightness/contrast) or colormap of a volume ==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Make mouse left-click and drag on the image adjust window/level ==&lt;br /&gt;
&lt;br /&gt;
In older Slicer versions, by default, left-click and drag in a slice view adjusted window/level of the displayed image. Window/level adjustment is now a new mouse mode that can be activated by clicking on its toolbar button or running this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.applicationLogic().GetInteractionNode().SetCurrentInteractionMode(slicer.vtkMRMLInteractionNode.AdjustWindowLevel)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create custom color table ==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Manipulate a Slice View ==&lt;br /&gt;
&lt;br /&gt;
=== Change slice offset ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Change slice orientation ===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show slice views in 3D window ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reset field of view to show background volume maximized ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rotate slice views to volume plane ===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Iterate over current visible slice views, and set foreground and background images ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     sliceWidget = layoutManager.sliceWidget(sliceViewName)&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Synchronize zoom factor between slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.sliceNodes = [slicer.app.layoutManager().sliceWidget(viewName).mrmlSliceNode()&lt;br /&gt;
    for viewName in slicer.app.layoutManager().sliceViewNames()]&lt;br /&gt;
&lt;br /&gt;
slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
def sliceModified(caller, event):&lt;br /&gt;
    if slicer.updatingSliceNodes:&lt;br /&gt;
        # prevent infinite loop of slice node updates triggering slice node updates&lt;br /&gt;
        return&lt;br /&gt;
    slicer.updatingSliceNodes = True&lt;br /&gt;
    fov = caller.GetFieldOfView()&lt;br /&gt;
    for sliceNode in slicer.sliceNodes:&lt;br /&gt;
        if sliceNode != caller:&lt;br /&gt;
            sliceNode.SetFieldOfView(*fov)&lt;br /&gt;
    slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
for sliceNode in slicer.sliceNodes:&lt;br /&gt;
    sliceNode.AddObserver(vtk.vtkCommand.ModifiedEvent, sliceModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change opacity of foreground volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fit slice plane to markup fiducials ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.array([0,0,0])&lt;br /&gt;
p2 = np.array([0,0,0])&lt;br /&gt;
p3 = np.array([0,0,0])&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0, 0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a series of images from a Slice View ==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a new directory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a single MRB file ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a node to file ==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Center the 3D View on the Scene ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Display text in a 3D view or slice view ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide slice view annotations (DataProbe) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Turning off interpolation ==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Customize viewer layout ==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;layout type=&amp;quot;vertical&amp;quot; split=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLSliceNode&amp;quot; singletontag=&amp;quot;Red&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;orientation&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewcolor&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/layout&amp;gt;&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Built-in layout IDs are all below 100, so you can choose any large random number&lt;br /&gt;
# for your custom layout ID.&lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
&lt;br /&gt;
# Switch to the new custom layout &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
You can use this code snippet to add a button to the layout selector toolbar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Add button to layout selector toolbar for this custom layout&lt;br /&gt;
viewToolBar = mainWindow().findChild('QToolBar', 'ViewToolBar')&lt;br /&gt;
layoutMenu = viewToolBar.widgetForAction(viewToolBar.actions()[0]).menu()&lt;br /&gt;
layoutSwitchActionParent = layoutMenu  # use `layoutMenu` to add inside layout list, use `viewToolBar` to add next the standard layout list&lt;br /&gt;
layoutSwitchAction = layoutSwitchActionParent.addAction(&amp;quot;My view&amp;quot;) # add inside layout list&lt;br /&gt;
layoutSwitchAction.setIcon(qt.QIcon(':Icons/Go.png'))&lt;br /&gt;
layoutSwitchAction.setToolTip('3D and slice view')&lt;br /&gt;
layoutSwitchAction.connect('triggered()', lambda layoutId = customLayoutId: slicer.app.layoutManager().setLayout(layoutId))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Customize keyboard shortcuts ==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Disable certain user interactions in slice views ==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change default slice view orientation ==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Set all slice views linked by default ==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set crosshair jump mode to centered by default ==&lt;br /&gt;
&lt;br /&gt;
You can change default slice jump mode (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
crosshair=slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLCrosshairNode&amp;quot;)&lt;br /&gt;
crosshair.SetCrosshairBehavior(crosshair.CenteredJumpSlice)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set up custom units in slice view ruler ==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in range(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a slice view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;TS&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
viewNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(layoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
viewWidget.sliceViewName = layoutName&lt;br /&gt;
viewWidget.sliceViewLabel = layoutLabel&lt;br /&gt;
c = viewNode.GetLayoutColor()&lt;br /&gt;
viewWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLSliceNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a 3D view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;Test3DView&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;T3&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML node&lt;br /&gt;
viewNode = slicer.vtkMRMLViewNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLThreeDWidget()&lt;br /&gt;
viewWidget.viewLabel = layoutLabel&lt;br /&gt;
viewWidget.viewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLViewNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get displayable manager of a certain type for a certain view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelDisplayableManager = None&lt;br /&gt;
threeDViewWidget = slicer.app.layoutManager().threeDWidget(0)&lt;br /&gt;
managers = vtk.vtkCollection()&lt;br /&gt;
threeDViewWidget.getDisplayableManagers(managers)&lt;br /&gt;
for i in range(managers.GetNumberOfItems()):&lt;br /&gt;
  obj = managers.GetItemAsObject(i)&lt;br /&gt;
  if obj.IsA('vtkMRMLModelDisplayableManager'):&lt;br /&gt;
    modelDisplayableManager = obj&lt;br /&gt;
    break&lt;br /&gt;
if modelDisplayableManager is None:&lt;br /&gt;
  logging.error('Failed to find the model displayable manager')&lt;br /&gt;
  return&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Running an ITK filter in Python using SimpleITK ==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
* See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
* 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&lt;br /&gt;
&lt;br /&gt;
== Get current mouse coordinates in a slice view ==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get DataProbe text ==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get reformatted image from a slice viewer as numpy array ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print voxels.shape&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thick slab reconstruction and maximum/minimum intensity volume projections ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
== Change default file type for nodes (that have never been saved yet) ==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
== Change file type for saving for all volumes (with already existing storage nodes) ==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sequences ==&lt;br /&gt;
&lt;br /&gt;
=== Concatenate all sequences in the scene into a new sequence ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Segmentations ==&lt;br /&gt;
&lt;br /&gt;
=== Create a segmentation from a labelmap volume and display in 3D ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
=== Export labelmap node from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
Export smallest possible labelmap:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export labelmap that matches geometry of a chosen reference volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export by pressing Ctrl+Shift+s key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPath = &amp;quot;c:/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def exportLabelmap():&lt;br /&gt;
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLSegmentationNode&amp;quot;)&lt;br /&gt;
    referenceVolumeNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
    labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
    slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
    filepath = outputPath + &amp;quot;/&amp;quot; + referenceVolumeNode.GetName()+&amp;quot;-label.nrrd&amp;quot;&lt;br /&gt;
    slicer.util.saveNode(labelmapVolumeNode, filepath)&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode.GetDisplayNode().GetColorNode())&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
    slicer.util.delayDisplay(&amp;quot;Segmentation saved to &amp;quot;+filepath)&lt;br /&gt;
&lt;br /&gt;
shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
shortcut.setKey(qt.QKeySequence('Ctrl+Shift+s'))&lt;br /&gt;
shortcut.connect( 'activated()', exportLabelmap)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Export model nodes from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
exportedModelsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelHierarchyNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModelHierarchy(seg, exportedModelsNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show a segmentation in 3D ===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get a representation of a segment ===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = segmentationNode.GetBinaryLabelmapRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using default path and conversion parameters ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using custom path or conversion parameters ===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-convert using a modified conversion parameter ===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get centroid of a segment in world (RAS) coordinates ===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How to run segment editor effects from a script ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
* [https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
* [https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
* [https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
* [https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
== Accessing views, renderers, and cameras ==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide view controller bars ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Customize widgets in view controller bars ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceController = slicer.app.layoutManager().sliceWidget(&amp;quot;Red&amp;quot;).sliceController()&lt;br /&gt;
&lt;br /&gt;
# hide what is not needed&lt;br /&gt;
sliceController.pinButton().hide()&lt;br /&gt;
#sliceController.viewLabel().hide()&lt;br /&gt;
sliceController.fitToWindowToolButton().hide()&lt;br /&gt;
sliceController.sliceOffsetSlider().hide()&lt;br /&gt;
&lt;br /&gt;
# add custom widgets&lt;br /&gt;
myButton = qt.QPushButton(&amp;quot;My custom button&amp;quot;)&lt;br /&gt;
sliceController.barLayout().addWidget(b)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change 3D view background color ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderer = renderWindow.GetRenderers().GetFirstRenderer()&lt;br /&gt;
renderer.SetBackground(1,0,0)&lt;br /&gt;
renderer.SetBackground2(1,0,0)&lt;br /&gt;
renderWindow.Render()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subject hierarchy == &lt;br /&gt;
==== Get the pseudo-singleton subject hierarchy node ====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.mrmlScene.GetSubjectHierarchyNode()&lt;br /&gt;
&lt;br /&gt;
==== Create subject hierarchy item ====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
==== Get subject hierarchy item ====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
==== Traverse children of a subject hierarchy item ====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in range(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
==== Manipulate subject hierarchy item ====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data nodes associated to items in a branch (or a leaf item)&lt;br /&gt;
  shNode.SetDisplayVisibilityForBranch(itemID, 1)&lt;br /&gt;
&lt;br /&gt;
==== Filter items in TreeView or ComboBox ====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
=== Listen to subject hierarchy item events ===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
== Plotting ==&lt;br /&gt;
&lt;br /&gt;
=== Slicer plots displayed in view layout ===&lt;br /&gt;
&lt;br /&gt;
Create histogram plot of a volume and show it embedded in the view layout. More information: https://www.slicer.org/wiki/Documentation/Nightly/Developers/Plots&lt;br /&gt;
&lt;br /&gt;
==== Using &amp;lt;code&amp;gt;slicer.util.plot&amp;lt;/code&amp;gt; utility function ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
chartNode = slicer.util.plot(histogram, xColumnIndex = 1)&lt;br /&gt;
chartNode.SetYAxisRangeAuto(False)&lt;br /&gt;
chartNode.SetYAxisRange(0, 4e5)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:SlicerPlot.png]]&lt;br /&gt;
&lt;br /&gt;
==== Using MRML classes only ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using matplotlib ===&lt;br /&gt;
&lt;br /&gt;
Matplotlib may be used from within Slicer, but the default Tk backend locks up and crashes Slicer. However, Matplotlib may still be used through other backends. More details can be found on the [http://matplotlib.sourceforge.net/ MatPlotLib] pages.&lt;br /&gt;
&lt;br /&gt;
==== Non-interactive plot ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
&lt;br /&gt;
# Static image view&lt;br /&gt;
pm = qt.QPixmap(&amp;quot;MatplotlibExample.png&amp;quot;)&lt;br /&gt;
imageWidget = qt.QLabel()&lt;br /&gt;
imageWidget.setPixmap(pm)&lt;br /&gt;
imageWidget.setScaledContents(True)&lt;br /&gt;
imageWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:MatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==== Plot in Slicer Jupyter notebook ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
display(filename='MatplotlibExample.png', type=&amp;quot;image/png&amp;quot;, binary=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:JupyterNotebookMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==== Interactive plot using wxWidgets GUI toolkit ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
  import wx&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib wxPython')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Set matplotlib to use WXAgg backend&lt;br /&gt;
import matplotlib&lt;br /&gt;
matplotlib.use('WXAgg')&lt;br /&gt;
&lt;br /&gt;
# Show an interactive plot&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
fig, ax = plt.subplots()&lt;br /&gt;
ax.plot(histogram[1][1:], histogram[0].astype(float))&lt;br /&gt;
ax.grid(True)&lt;br /&gt;
ax.set_ylim((0, 4e5))&lt;br /&gt;
plt.show(block=False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:InteractiveMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
== Execute external applications ==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
=== Run process in default environment ===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;br /&gt;
&lt;br /&gt;
== Manage extensions ==&lt;br /&gt;
&lt;br /&gt;
=== Download and install extension ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensionName = 'SlicerIGT'&lt;br /&gt;
em = slicer.app.extensionsManagerModel()&lt;br /&gt;
if not em.isExtensionInstalled(extensionName):&lt;br /&gt;
    extensionMetaData = em.retrieveExtensionMetadataByName(extensionName)&lt;br /&gt;
    url = em.serverUrl().toString()+'/download/item/'+extensionMetaData['item_id']&lt;br /&gt;
    extensionPackageFilename = slicer.app.temporaryPath+'/'+extensionMetaData['md5']&lt;br /&gt;
    slicer.util.downloadFile(url, extensionPackageFilename)&lt;br /&gt;
    em.installExtension(extensionPackageFilename)&lt;br /&gt;
    slicer.util.restart()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Training&amp;diff=61474</id>
		<title>Documentation/Nightly/Training</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Training&amp;diff=61474"/>
		<updated>2019-09-24T12:41:54Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Slicer4 Neurosurgical Planning Tutorial */ Copying over from 4.10 page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
=Introduction: Slicer {{documentation/version}} Tutorials=&lt;br /&gt;
&lt;br /&gt;
*This page contains &amp;quot;How to&amp;quot; tutorials with matched sample data sets. They demonstrate how to use the 3D Slicer environment (version {{documentation/version}} release) to accomplish certain tasks. &lt;br /&gt;
*For tutorials for other versions of Slicer, please visit the [[Training| Slicer training portal]].&lt;br /&gt;
*For &amp;quot;reference manual&amp;quot; style documentation, please visit the [[Documentation/{{documentation/version}}|Slicer {{documentation/version}} documentation page]]&lt;br /&gt;
*For questions related to the Slicer4 Training Compendium, please send an e-mail to '''[http://www.na-mic.org/Wiki/index.php/User:SPujol Sonia Pujol, Ph.D., Director of Training of 3D Slicer.]'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Some of these tutorials are based on older releases of 3D Slicer and are being upgraded to Slicer4.10. The concepts are still useful but some interface elements and features may be different in updated versions.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Quick Start Guide =&lt;br /&gt;
&lt;br /&gt;
==Downloading and Installing Slicer==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/gtir3x6e007snkx/QuickStartGuide_3DSlicer_SoniaPujol.pdf?dl=0| Quick Start Guide] shows how to install and start 3D Slicer&lt;br /&gt;
*Author: Sonia Pujol, Ph.D.&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[image:QuickStart_image.png|250px|SlicerWelcome tutorial]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=General Introduction=&lt;br /&gt;
&lt;br /&gt;
==Slicer Welcome Tutorial==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/vn8sqlof2kag2kk/SlicerWelcome-tutorial_Slicer4.8_SoniaPujol.pdf?dl=0] is an introduction to Slicer.&lt;br /&gt;
*Author: Sonia Pujol, Ph.D.&lt;br /&gt;
*Audience: First-time users who want a general introduction to the software&lt;br /&gt;
*Modules: Welcome to Slicer, Sample Data&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[image:SlicerWelcome-image.png|250px|SlicerWelcome tutorial]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Slicer4Minute Tutorial==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/9jfsyhhgude5hf1/Slicer4.8minute_SoniaPujol.pdf?dl=0| Slicer4 Minute Tutorial]  is a brief introduction to the advanced 3D visualization capabilities of Slicer 4.8.&lt;br /&gt;
*Author: Sonia Pujol, Ph.D.&lt;br /&gt;
*Audience: First-time users who want to discover Slicer in 4 minutes&lt;br /&gt;
*Modules: Welcome to Slicer, Models&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
*The [[media:Slicer4minute.zip|Slicer4Minute dataset]] contains an MR scan of the brain and 3D reconstructions of the anatomy&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[image:Slicer4minute-image.png|250px|right|Slicer4Minute tutorial]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=3D Visualization=&lt;br /&gt;
==Slicer4 Data Loading and 3D Visualization ==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
* Slicer 4.10&lt;br /&gt;
** The [http://slicer.kitware.com/midas3/download/item/356408/20180430_DataLoadingAndVisualizationTutorial.pdf Data loading and visualization] ([http://slicer.kitware.com/midas3/download/item/356409/20180430_DataLoadingAndVisualizationTutorial.pptx pptx]) course guides through the basics of loading and viewing volumes and 3D models in Slicer 4.10. &lt;br /&gt;
** Author: Csaba Pinter&lt;br /&gt;
** Modules: Welcome to Slicer, Data, Volume Rendering, Models.&lt;br /&gt;
** Audience: End-users&lt;br /&gt;
** Based on: 3D Slicer version 4.10&lt;br /&gt;
** The [http://slicer.kitware.com/midas3/download/?items=330421,1 3DVisualization dataset] contain an MR scan and a series of 3D models of the brain.&lt;br /&gt;
&lt;br /&gt;
* Slicer 4.5&lt;br /&gt;
** The [[Media:3DDataLoadingandVisualization_Slicer4.5_SoniaPujol.pdf | Data loading and 3D visualization]] course guides through the basics of loading and viewing volumes and 3D models in Slicer 4.5. &lt;br /&gt;
** Author: Sonia Pujol, Ph.D.&lt;br /&gt;
** Modules: Welcome to Slicer, Sample Data, Models.&lt;br /&gt;
** Audience: End-users&lt;br /&gt;
** Based on: 3D Slicer version 4.5&lt;br /&gt;
** The [http://slicer.kitware.com/midas3/download/?items=330421,1 3DVisualization dataset] contain an MR scan and a series of 3D models of the brain.&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[Image:20180426_DataLoadingAndVisualizationTutorial.png|right|250px|]]&lt;br /&gt;
[[Image:Slicer4DataLoading_tutorial.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Slicer4 3D Visualization of DICOM images for Radiology Applications==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/9jcjpl33qfh5pi6/3DVisualizationDICOM_Slicer4.8_SoniaPujol.pdf?dl=0 3D Visualization of DICOM images]  course guides through 3D data loading and visualization of DICOM images for Radiology Applications in Slicer4. &lt;br /&gt;
*Author: Sonia Pujol, Ph.D., Kitt Shaffer, M.D., Ph.D., Ron Kikinis, M.D.&lt;br /&gt;
*Audience: Radiologists and users of Slicer who need a more comprehensive overview over Slicer4 visualization capabilities.&lt;br /&gt;
*Modules: DICOM, Volumes, Volume Rendering, Models.&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
*The [[Media:3DVisualization_DICOM_images_part1.zip‎  | 3DVisualizationDICOM_part1]] and [[Media:3DVisualization_DICOM_images_part2.zip | 3DVisualizationDICOM_part2]] datasets contain a series of MR and CT scans, and 3D models of the brain, lung and liver.&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[Image:Slicer4RSNA_2.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Tutorials for software developers=&lt;br /&gt;
&lt;br /&gt;
== Slicer4 Programming Tutorial ==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/wrhrvvmplosiis1/Slicer4_ProgrammingTutorial_SPujol-SPieper_Nightly.pdf?dl=0# Slicer Programming tutorial] guides through the integration of a python module in Slicer4. &lt;br /&gt;
*Author: Sonia Pujol, Ph.D., Steve Pieper, Ph.D.&lt;br /&gt;
*Audience: Developers&lt;br /&gt;
*Based on: 3D Slicer version 4.7&lt;br /&gt;
*The [https://www.dropbox.com/s/6yxu8qepmvywk0n/HelloPython_Nightly.zip?dl=0 HelloPython dataset] contains sample data set (MR scan of the brain) and complete Python module examples.&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[Image:HelloPythonTutorial.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== PerkLab's Slicer bootcamp training materials ==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [http://perk.cs.queensu.ca/ Laboratory for Percutaneous Surgery at Queen's University] has made available training material of its internal yearly bootcamp, covering topics, such as 3D Slicer overview, basic visualization, segmentation, registration, scripting and module development, surgical navigation, DICOM, reproducible medical image computing research methodology, version control, and research project management.&lt;br /&gt;
** [https://github.com/PerkLab/PerkLabBootcamp/blob/master/Doc/day3_2_SlicerProgramming.pptx?raw=true Scripting and module development tutorial]&lt;br /&gt;
** [https://github.com/PerkLab/PerkLabBootcamp/tree/master/Doc All other tutorials]&lt;br /&gt;
*Author: Andras Lasso, Csaba Pinter, Tamas Ungi, Csaba Pinter, Matthew Holden, Kyle Sunderland&lt;br /&gt;
*Audience: Developers, Users&lt;br /&gt;
*Based on: 3D Slicer version 4.10&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[Image:PerkLabSlicerProgrammingTutorial.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Slicer script repository ==&lt;br /&gt;
&lt;br /&gt;
For additional Python scripts examples, please visit the [[Documentation/{{documentation/version}}/ScriptRepository|Script Repository page]]&lt;br /&gt;
&lt;br /&gt;
==Developing and contributing extensions for 3D Slicer==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [http://goo.gl/IP4cdg Developing and contributing extensions for 3D Slicer tutorial ] is an introduction to the internals of 3D Slicer and the process of contributing a 3D Slicer extension.&lt;br /&gt;
*Authors: Andrey Fedorov, Jean-Christophe Fillion-Robin, Steve Pieper&lt;br /&gt;
*Audience: Developers&lt;br /&gt;
*Based on: 3D Slicer version 4.4&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[Image:Contributing3DSlicerExtension.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Segmentation=&lt;br /&gt;
== Slicer4 Image Segmentation ==&lt;br /&gt;
&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
* Segmentation for 3D printing: shows how to use the Segment Editor module for combining CAD designed parts with patient-specific models.&lt;br /&gt;
** '''[https://discourse.slicer.org/t/new-video-tutorial-for-segment-editor-lumbar-spine-segmentation-for-3d-printing/700 Video tutorial]'''. Author: Hillary Lia.&lt;br /&gt;
** '''[[Documentation/{{documentation/version}}/Training#Segmentation_for_3D_printing|Segmentation for 3D printing Step-by-step tutorial]]'''. Author: Csaba Pinter, MSc&lt;br /&gt;
** Audience: Users and developers interested in segmentation and 3D printing&lt;br /&gt;
** Dataset: [[:File:BasePiece.zip|Phantom base STL model]] Source: [http://perk-software.cs.queensu.ca/plus/doc/nightly/modelcatalog/ PerkLab].&lt;br /&gt;
** Based on: 3D Slicer version 4.7&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|[[Image:20170717_3DPrintingTutorialYoutube.PNG|280px]]&lt;br /&gt;
|---&lt;br /&gt;
|&lt;br /&gt;
* '''[https://youtu.be/BJoIexIvtGo Video tutorial: Whole heart segmentation from cardiac CT]''' shows how to use the Segment Editor module for segmenting heart ventricles, atria, and great vessels from cardiac CT volumes.&lt;br /&gt;
** Author: Andras Lasso, PhD&lt;br /&gt;
** Audience: Users who need to segment heart structures, for example for visualization, quantification, or simulation.&lt;br /&gt;
** Sample data set: http://slicer.kitware.com/midas3/download/bitstream/738905/CTA-cardio2.nrrd&lt;br /&gt;
** Based on: 3D Slicer version 4.8&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|[[Image:WholeHeartSegYoutube.png|280px]]&lt;br /&gt;
|---&lt;br /&gt;
|&lt;br /&gt;
* '''[https://youtu.be/0at15gjk-Ns Video tutorial: Femur and pelvis segmentation from CT]''' shows how to use the Segment Editor module for segmenting pelvis and femur from CT volumes.&lt;br /&gt;
** Author: Andras Lasso, PhD&lt;br /&gt;
** Audience: Users who need to segment bones in CT images for visualization, quantification, or simulation.&lt;br /&gt;
** Sample data set: https://wiki.cancerimagingarchive.net/display/Public/TCGA-PRAD (Subject TCGA-VP-A878)&lt;br /&gt;
** Based on: 3D Slicer version 4.8&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|[[Image:FemurSegmentationYoutube.png|280px]]&lt;br /&gt;
|---&lt;br /&gt;
|&lt;br /&gt;
* [https://lassoan.github.io/SlicerSegmentationRecipes/ Slicer Segmentation Recipes]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Registration=&lt;br /&gt;
&lt;br /&gt;
== Slicer4 Image Registration ==&lt;br /&gt;
&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.dropbox.com/s/chrugp2j2as5gop/ImageRegistration_Slicer4.8_SoniaPujol.pdf?dl=0 Registration tutorial] shows how to perform intra- and inter-subject registration within Slicer.&lt;br /&gt;
* Authors: Sonia Pujol, Ph.D., Dominik Meier, Ph.D., Ron Kikinis, M.D.&lt;br /&gt;
* Audience: Users and developers interested in image registration&lt;br /&gt;
* Dataset: [[Media:RegistrationData.zip| 3D Slicer Registration Data]]&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|[[File:registration_Slicer4.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Slicer Registration Case Library==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The ''[[Documentation/{{documentation/version}}/Registration/RegistrationLibrary|Slicer Registration Case Library]]'' provides real-life example cases of using the Slicer registration tools. They include pre-computed dataset and step-by-step instructions for users to follow. &lt;br /&gt;
:Author: Dominik Meier, Ph.D.&lt;br /&gt;
:Audience:  users interested learning/applying Slicer image registration technology&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|[[Image:RegLib_table.png|250px|link=http://wiki.slicer.org/slicerWiki/index.php/Documentation/{{documentation/version}}/Registration/RegistrationLibrary]]&lt;br /&gt;
|}&lt;br /&gt;
=Slicer Extensions=&lt;br /&gt;
==Slicer4 Diffusion Tensor Imaging Tutorial ==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*Please visit [http://dmri.slicer.org/docs/ dmri.slicer.org/docs] for the latest documentation of SlicerDMRI.&lt;br /&gt;
*The [https://www.dropbox.com/s/m7rzeblbdzr49bc/DiffusionMRIAnalysis_Slicer4.8_SoniaPujol.pdf?dl=0| Diffusion Tensor Imaging]  course is an introduction to the basics of loading Diffusion Weighted images in Slicer, estimating tensors and generating fiber tracts. &lt;br /&gt;
*Author: Sonia Pujol, Ph.D.&lt;br /&gt;
*Audience: End-users and developers&lt;br /&gt;
*Modules: Data, Volumes, DWI to DTI Estimation, Diffusion Tensor Scalar Measurements, Editor, Markups,Tractography Label Map Seeding, Tractography Interactive Seeding&lt;br /&gt;
*Based on: 3D Slicer version 4.8&lt;br /&gt;
*The [[media:Dti tutorial data.zip|DTI dataset]] contains an MR Diffusion Weighted Imaging scan of the brain.&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[Image:Slicer4DTI Tutorial.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Slicer4 Neurosurgical Planning Tutorial==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://spujol.github.io/NeurosurgicalPlanningTutorial/ Neurosurgical Planning tutorial] course guides end-users through the generation of fiber tracts in the vicinity of a tumor.&lt;br /&gt;
*Author: Sonia Pujol, Ph.D., Ron Kikinis, M.D.&lt;br /&gt;
*Audience: Clinicians and Clinical Researchers&lt;br /&gt;
*Modules: Segment Editor, Tractography &lt;br /&gt;
*Based on 3D Slicer version 4.10&lt;br /&gt;
*The [[Media:WhiteMatterExplorationData.zip| White Matter Exploration dataset]] contains a Diffusion Weighted Imaging scan of a brain tumor patient.&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[Image:NeurosurgicalPlanningTutorial.png|right|250px|link=http://vimeo.com/67336069]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Slicer4 Quantitative Imaging tutorial==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [[media:QuantitativeImaging_Slicer4.5.pdf‎ | Slicer4 Quantitative Imaging tutorial]]  guides through the use for Slicer for quantifying small volumetric changes in slow-growing tumors, and for calculating Standardized Uptake Value (SUV) from PET/CT data.&lt;br /&gt;
*Authors: Sonia Pujol, Ph.D., Katarzyna Macura, M.D., Ron Kikinis, M.D.&lt;br /&gt;
*Audience: Radiologists and users of Slicer who need a more comprehensive overview over Slicer4 quantitative imaging capabilities.&lt;br /&gt;
*Modules: Data, Volumes, Models, Change Tracker, PET Standard Uptake Value Computation&lt;br /&gt;
*Based on: 3D Slicer version 4.5&lt;br /&gt;
*The [[media:QuantitativeImaging.zip‎| Quantitative Imaging dataset]]  contains a series of MR and PET/CT data.&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[Image:Slicer4_QuantitativeImaging.png|right|250px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Slicer4 IGT ==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*[http://www.slicerigt.org/wp/user-tutorial/ Slicer IGT tutorials]&lt;br /&gt;
*Authors: Tamas Ungi, M.D, Ph.D., Junichi Tokuda, Ph.D.&lt;br /&gt;
*Audience: End-users interested in using Slicer for real-time navigated procedures. E.g. navigated needle insertions or other minimally invasive medical procedures.&lt;br /&gt;
*Modules: SlicerIGT Extension&lt;br /&gt;
*Based on: Slicer4.3.1-2014.09.14&lt;br /&gt;
*Data: [https://onedrive.live.com/redir?resid=7230D4DEC6058018!2937&amp;amp;authkey=!AGQkSCZOwjVYXw8&amp;amp;ithint=folder%2cpptx  Slicer-IGT datasets]&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[Image:SlicetIGT.png|right|150px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Slicer4 Radiation Therapy Tutorial ==&lt;br /&gt;
&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
* The [https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SlicerRT_WorldCongress_TutorialIGRT.pdf SlicerRT tutorial] is an introduction to the Radiation Therapy functionalities of Slicer.&lt;br /&gt;
* Author: Csaba Pinter, Andras Lasso, An Wang, Gregory C. Sharp, David Jaffray, Gabor Fichtinger. &lt;br /&gt;
* Dataset: [http://slicer.kitware.com/midas3/download/item/205404/SlicerRT_WorldCongress_TutorialIGRT_Dataset.zip download] from MIDAS server&lt;br /&gt;
* Based on Slicer 4.7&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
&amp;lt;!-- [[Image:TUTORIAL-IMAGE-HERE.png|right|150px|]] --&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Slicer Pathology==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [[Documentation/{{documentation/version}}/Extensions/SlicerPathology|Slicer Pathology Tutorial]] describes how to use the corresponding tools for automatic and semi-automatic pathology image segmentation.&lt;br /&gt;
*Author: Erich Bremer (Stonybrook), Andriy Fedorov (Brigham and Women’s Hospital)&lt;br /&gt;
*Dataset:  Available directly with the Slicer Pathology Slicer extension.&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[File:SlicerPathologyScreenShot8.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==SPHARM-PDM==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.nitrc.org/docman/view.php/308/1982/SPHARM-PDM_Tutorial_July2015.pdf SPHARM-PDM Tutorial] describes how to use SPHARM-PDM and ShapePopulationViewer Slicer extensions to respectively compute point-based models using a parametric boundary description for the computing of Shape Analysis and perform the quality control between the different models.&lt;br /&gt;
*Author: Jonathan Perdomo (UNC), Beatriz Paniagua (Kitware Inc.)&lt;br /&gt;
*Dataset:  [https://www.nitrc.org/docman/view.php/308/1981/SPHARM_Tutorial_Data_July2015.zip Tutorial Data]&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-SPHARM-PDM.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Fiber Bundle Volume Measurement==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [http://www.na-mic.org/Wiki/images/5/57/Fiber_Bundle_Volume_Measurement.pptx Fiber Bundle Volume Measurement Tutorial] aim is to calculate the volume of the fiber bundle that passes through the Corpus Callosum(CC). Following this tutorial, you’ll be able to (1) convert fiber bundles to label map and (2) calculate volume measurements from the fiber bundles.&lt;br /&gt;
*Author: Shun Gong (Shanghai Changzheng Hospital, China)&lt;br /&gt;
*Dataset:  [http://www.na-mic.org/Wiki/images/4/4c/FiberVolume_data.zip Tutorial data]: The following data are provided: Baseline image, Down sampled whole brain tractography (conducted as in the [[Documentation/{{documentation/version}}/Training#Slicer4_Diffusion_Tensor_Imaging_Tutorial|DWI tutorial]] and down-sampled to about 10000 fibers using Tractography Display module), Corpus callosum label map (drawn as in the [[Documentation/{{documentation/version}}/Training#Slicer4_Diffusion_Tensor_Imaging_Tutorial|DWI tutorial]]).&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-FiberBundleVolumeMeasurements.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= 3D Slicer version 4.7 Tutorial Contest=&lt;br /&gt;
&lt;br /&gt;
For previous editions of the contest, please visit the [https://na-mic.org/wiki/Tutorial_Contests 3D Slicer Tutorial Contests page]&lt;br /&gt;
&lt;br /&gt;
===Segmentation for 3D printing===&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SegmentationFor3DPrinting_TutorialContestWinter2017.pdf Segmentation for 3D printing Tutorial] ([https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SegmentationFor3DPrinting_TutorialContestWinter2017.pptx pptx]) is an introduction to the new [[Documentation/{{documentation/version}}/Modules/SegmentEditor|Segment Editor]] module, demonstrated through the popular topic of 3D printing. &lt;br /&gt;
*Author: Csaba Pinter (Queen's University, Canada)&lt;br /&gt;
* [https://www.youtube.com/watch?v=Uht6Fwtr9hE Narrated video version on YouTube].&lt;br /&gt;
*Dataset: [[:File:BasePiece.zip|Phantom base STL model]] Source: [http://perk-software.cs.queensu.ca/plus/doc/nightly/modelcatalog/ PerkLab].&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-Segmentation-for-3d-printing.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Slicer Pathology===&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [[Documentation/{{documentation/version}}/Extensions/SlicerPathology|Slicer Pathology Tutorial]] describes how to use the corresponding tools for automatic and semi-automatic pathology image segmentation.&lt;br /&gt;
*Author: Erich Bremer (Stonybrook), Andriy Fedorov (Brigham and Women’s Hospital)&lt;br /&gt;
*Dataset:  Available directly with the Slicer Pathology Slicer extension.&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[File:SlicerPathologyScreenShot8.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Simple Python Tool for Quality Control of DWI data===&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [http://www.na-mic.org/Wiki/images/3/3a/SimpleDiffusionGradientInformationExtractorTutorial_Chauvin_Jan2017.pptx Simple Multi-shell Diffusion Gradients Information Extractor Tutorial] describes how to use a simple Python script for parsing multi-shell sensitizing gradients information from nifti file format (separated bvecs, bvals files).&lt;br /&gt;
*Author: Laurent Chauvin (ETS Montreal)&lt;br /&gt;
*Dataset:  Not available.&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-SimpleDiffusionGradientInformationExtractorTutorial.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===SPHARM-PDM===&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.nitrc.org/docman/view.php/308/1982/SPHARM-PDM_Tutorial_July2015.pdf SPHARM-PDM Tutorial] describes how to use SPHARM-PDM and ShapePopulationViewer Slicer extensions to respectively compute point-based models using a parametric boundary description for the computing of Shape Analysis and perform the quality control between the different models.&lt;br /&gt;
*Author: Jonathan Perdomo (UNC), Beatriz Paniagua (Kitware Inc.)&lt;br /&gt;
*Dataset:  [https://www.nitrc.org/docman/view.php/308/1981/SPHARM_Tutorial_Data_July2015.zip Tutorial Data]&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-SPHARM-PDM.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Integration of Robot Operating System (ROS) and 3D Slicer using OpenIGTLink===&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [https://www.na-mic.org/Wiki/images/a/ab/ROSIGTLTutorial_Tokuda_Jan2017.pptx Integration of Robot Operating System (ROS) and 3D Slicer using OpenIGTLink Tutorial] describes the software architecture of surgical robot systems and allows to acquire hands-on experience of software-hardware integration for medical robotics.&lt;br /&gt;
*Author: Junichi Tokuda (Brigham and Women’s Hospital)&lt;br /&gt;
*Dataset:  Not available.&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-Integration-ROS-3DSlicer-OpenIGTLink.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Fiber Bundle Volume Measurement===&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*The [http://www.na-mic.org/Wiki/images/5/57/Fiber_Bundle_Volume_Measurement.pptx Fiber Bundle Volume Measurement Tutorial] aim is to calculate the volume of the fiber bundle that passes through the Corpus Callosum(CC). Following this tutorial, you’ll be able to (1) convert fiber bundles to label map and (2) calculate volume measurements from the fiber bundles.&lt;br /&gt;
*Author: Shun Gong (Shanghai Changzheng Hospital, China)&lt;br /&gt;
*Dataset:  [http://www.na-mic.org/Wiki/images/4/4c/FiberVolume_data.zip Tutorial data]: The following data are provided: Baseline image, Down sampled whole brain tractography (conducted as in the [[Documentation/{{documentation/version}}/Training#Slicer4_Diffusion_Tensor_Imaging_Tutorial|DWI tutorial]] and down-sampled to about 10000 fibers using Tractography Display module), Corpus callosum label map (drawn as in the [[Documentation/{{documentation/version}}/Training#Slicer4_Diffusion_Tensor_Imaging_Tutorial|DWI tutorial]]).&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[File:SlicerWinterProjectWeek2017-FiberBundleVolumeMeasurements.png | 200px]]. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=YouTube videos=&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;5&amp;quot; width=&amp;quot;1200px&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; | [[Image:Verterbra.png|right|250px|]] [https://www.youtube.com/watch?v=Uht6Fwtr9hE How to segment multiple vertebrae in spine CT for 3D printing - Author: Hillary Lia]&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; | [[Image:Femurmodel.png|right|250px|]] [https://www.youtube.com/watch?v=0at15gjk-Ns Creating a femur model from CT volume using 3D Slicer - Author: Nabgha Farhat ]&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; | [[Image:3DPrinting.png|right|250px|]] [https://www.youtube.com/watch?v=MKLWzD0PiIc Preparing data for 3D printing - Author: PerkLab ]&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; | [[Image:Verterbra.png|right|250px|]] [https://www.youtube.com/watch?v=Uht6Fwtr9hE How to segment multiple vertebrae in spine CT for 3D printing - Author: Hillary Lia]&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; | [[Image:DICOM2.png|right|250px|]] [https://www.youtube.com/watch?v=nzWf4xHy1BM&amp;amp; How to export CT and segmentation data to DICOM- Author: Andras Lasso, Csaba Pinter]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additional [http://www.youtube.com/results?search_query=3d+slicer&amp;amp;sm=3 non-curated videos-based demonstrations using 3D Slicer are accessible on YouTube].&lt;br /&gt;
&lt;br /&gt;
=Teams Contributions  =&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
* This ''Slicer 4.1 [http://vimeo.com/41096643 webinar]'' presents the new features and improvements of the release, and a brief overview of work for the next release.&lt;br /&gt;
* Authors: Steve Pieper Ph.D.&lt;br /&gt;
* Audience: First time users and developers interested in Slicer 4.1 new features.&lt;br /&gt;
* Length: 0h20m&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|[[Image:Webinar-Slicer-4.1.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
*This ''Intro to Slicer 4.0 [http://vimeo.com/37671358 webinar]'' provides an introduction to 3DSlicer, and demonstrates core functionalities such as loading, visualizing and saving data. Basic processing tools, including manual registration, manual segmentation and tractography tools are also highlighted. This webinar is a general overview. For in depth information see the modules above and the documentation pages.&lt;br /&gt;
*Authors: Julien Finet, M.S., Steve Pieper, Ph.D., Jean-Christophe Fillion-Robin, M.S. &lt;br /&gt;
*Audience: First time users interested in a broad overview of Slicer’s features and tools.&lt;br /&gt;
*Length: 1h20m&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|[[Image:Webinar.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== International resources==&lt;br /&gt;
&lt;br /&gt;
==Resources in Chinese ==&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
A 3D Slicer community on WeChat in China offers many tutorials and clinical examples in Chinese.  Note that the images are of interest to non-Chinese speakers and Google Translate does a reasonable job of translating some of the text.&lt;br /&gt;
&lt;br /&gt;
* [https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247486116&amp;amp;idx=1&amp;amp;sn=772e9d431ac32cbb73d08cf0e6bc219a&amp;amp;chksm=eacc0096ddbb89805d93ac4be181d1a35058031bac673d7a91b3b44dccee2bfd1d8461397635#rd Getting started 大脑前动脉远端动脉瘤手术夹闭治疗]&lt;br /&gt;
&lt;br /&gt;
* [https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247484787&amp;amp;idx=1&amp;amp;sn=1f6279bdccab168fc79b7275e9fe91ca&amp;amp;chksm=eacc0f41ddbb8657be92f617661133d87bb55a4ecf12f786e97a8b7d5249a05d11e0cd620c3f#rd distal anterior cerebral artery aneurysm 3D Slicer：漂亮得不像实力派]&lt;br /&gt;
&lt;br /&gt;
* [https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247486360&amp;amp;idx=1&amp;amp;sn=f833b13a26f543aa9175419a03df7f52&amp;amp;chksm=eacc01aaddbb88bcb004773a4db8a9b3c7633d21cda3956f84b96515252eb861c5eb1e75a60b&amp;amp;mpshare=1&amp;amp;scene=24&amp;amp;srcid=0212LIfOkBRm9CvA7ImHCpRt#rd meningioma skull resection 脑膜瘤患者颅骨切除一期修补的3DSlicer方案]&lt;br /&gt;
&lt;br /&gt;
* [https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247486079&amp;amp;idx=1&amp;amp;sn=9b926dc398a408e3441082b9e0ffde61&amp;amp;chksm=eacc004dddbb895bf9b60f5f1bc443513196e4cb90a6caf6f348a4da7b7fc22eb658661aeb49&amp;amp;mpshare=1&amp;amp;scene=24&amp;amp;srcid=0212AFtT2Wq7K7bvkMGTdyih#rd Cerebral hemorrhage by forehead positioning method 脑出血经额手术定位法（五 ]&lt;br /&gt;
&lt;br /&gt;
* [https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247485356&amp;amp;idx=1&amp;amp;sn=044f5899b651b35994db00c32ab688ee&amp;amp;chksm=eacc0d9eddbb8488f16ff82bb1dda8456a4011790fed024781972d578783e67781443cf4a319&amp;amp;mpshare=1&amp;amp;scene=24&amp;amp;srcid=0212G45TadrPnX8tp9eaNXUs#rd Hematoma modeling 血肿建模的第11种方法]&lt;br /&gt;
&lt;br /&gt;
* [https://mp.weixin.qq.com/s?__biz=MzI3MDY4ODA5Mw==&amp;amp;mid=2247486025&amp;amp;idx=1&amp;amp;sn=b281324893be4ab116d20826f1b426c3&amp;amp;chksm=eacc007bddbb896d9deb096f209278f40c0b52c6410a8a9ff3ce8c3697c99304f18eb678f11e&amp;amp;mpshare=1&amp;amp;scene=24&amp;amp;srcid=02125v1kxvIGmfkxx7mUZcCM#rd Mobile phone positioning and AR application 手机定位及AR应用的初步探索]&lt;br /&gt;
&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|&lt;br /&gt;
[[image:Wechat-hemorage-2018-02-12.png|250px|Example WeChat tutorial slides]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Resources in German ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.youtube.com/watch?v=sl-00kGpuPk&amp;amp;list=PLJWCUXz3GeAfmYLiFcKus_c0jcsMnVsgb A series of four YouTube videos on python programming in Slicer] (German narration with English subtitles)&lt;br /&gt;
&lt;br /&gt;
== Murat Maga's blog posts about using 3D Slicer for biology ==&lt;br /&gt;
&lt;br /&gt;
* [https://blogs.uw.edu/maga/2017/04/11/getting-started-with-3d-slicer-as-a-biologist/ Slicer for Biologists]&lt;br /&gt;
* [https://blogs.uw.edu/maga/2017/04/11/a-worked-example-getting-and-visualizing-data-from-digimorph/ Loading data from DigiMorph]&lt;br /&gt;
* [https://blogs.uw.edu/maga/2017/04/11/morphosource-data-and-dealing-with-dicom-series-in-slicer/ Fixing problem DICOM]&lt;br /&gt;
* [https://blogs.uw.edu/maga/2017/04/12/scissors-tool-is-awesome/ Scissors tool is awesom]&lt;br /&gt;
 &lt;br /&gt;
== Using the (legacy) Editor ==&lt;br /&gt;
&lt;br /&gt;
=== Fast GrowCut ===&lt;br /&gt;
&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
* The [[media:FastGrowCutTutorial.pdf |Fast GrowCut tutorial]]  shows how to perform a segmentation using the Fast GrowCut effect in Slicer.&lt;br /&gt;
* Authors: Hillary Lia&lt;br /&gt;
* Audience: Users interested in segmentation&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|[[File:FastGrowCutLogo.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Use case: Slicer in paleontology ===&lt;br /&gt;
&lt;br /&gt;
This set of tutorials about the use of slicer in paleontology is very well written and provides step-by-step instructions.  Even though it covers slicer version 3.4, many of the concepts and techniques have applicability to the new version and to any 3D imaging field:&lt;br /&gt;
&lt;br /&gt;
* [http://openpaleo.blogspot.com/2008/12/3d-slicer-tutorial.html Open Source Paleontologist: 3D Slicer: The Tutorial]&lt;br /&gt;
* [http://openpaleo.blogspot.com/2008/12/3d-slicer-tutorial-part-ii.html Open Source Paleontologist: 3D Slicer: The Tutorial Part II]&lt;br /&gt;
* [http://openpaleo.blogspot.com/2008/12/3d-slicer-tutorial-part-iii.html Open Source Paleontologist: 3D Slicer: The Tutorial Part III]&lt;br /&gt;
* [http://openpaleo.blogspot.com/2008/12/3d-slicer-tutorial-part-iv.html Open Source Paleontologist: 3D Slicer: The Tutorial Part IV]&lt;br /&gt;
* [http://openpaleo.blogspot.com/2009/03/3d-slicer-tutorial-part-v.html Open Source Paleontologist: 3D Slicer: The Tutorial Part V]&lt;br /&gt;
* [http://openpaleo.blogspot.com/2009/03/3d-slicer-tutorial-part-vi.html Open Source Paleontologist: 3D Slicer: The Tutorial Part VI]&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61451</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61451"/>
		<updated>2019-09-16T16:24:00Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=&lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the [[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
* [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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
* [https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
* [https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
* [https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
* Capture the full Slicer screen and save it into a file&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
* Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
* Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
* How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
* How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loadedVolumeNode = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Automatically load volumes that are copied into a folder ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to implement a simple background task by using a timer. The background task is to check for any new volume files in folder and if there is any then automatically load it.&lt;br /&gt;
&lt;br /&gt;
There are more efficient methods for file system monitoring or exchanging image data in real-time (for example, using OpenIGTLink), the example below is just for demonstration purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
incomingVolumeFolder = &amp;quot;c:/tmp/incoming&amp;quot;&lt;br /&gt;
incomingVolumesProcessed = []&lt;br /&gt;
&lt;br /&gt;
def checkForNewVolumes():&lt;br /&gt;
  # Check if there is a new file in the &lt;br /&gt;
  from os import listdir&lt;br /&gt;
  from os.path import isfile, join&lt;br /&gt;
  for f in listdir(incomingVolumeFolder):&lt;br /&gt;
    if f in incomingVolumesProcessed:&lt;br /&gt;
      # this is an incoming file, it was already there&lt;br /&gt;
      continue&lt;br /&gt;
    filePath = join(incomingVolumeFolder, f)&lt;br /&gt;
    if not isfile(filePath):&lt;br /&gt;
      # ignore directories&lt;br /&gt;
      continue&lt;br /&gt;
    logging.info(&amp;quot;Loading new file: &amp;quot;+f)&lt;br /&gt;
    incomingVolumesProcessed.append(f)&lt;br /&gt;
    slicer.util.loadVolume(filePath)&lt;br /&gt;
  # Check again in 3000ms&lt;br /&gt;
  qt.QTimer.singleShot(3000, checkForNewVolumes)&lt;br /&gt;
&lt;br /&gt;
# Start monitoring&lt;br /&gt;
checkForNewVolumes()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
=== How to access top level tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # Note, fileValue accesses the database of cached top level tags&lt;br /&gt;
  # (nested tags are not included)&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
=== How to access DICOM tags nested in a sequence ===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  # use pydicom to access the full header, which requires&lt;br /&gt;
  # re-reading the dataset instead of using the database cache&lt;br /&gt;
  import pydicom&lt;br /&gt;
  pydicom.dcmread(fileList[0])&lt;br /&gt;
  ds.CTExposureSequence[0].ExposureModulationType&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
=== How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
=== How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm'); slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Export a volume to DICOM file format ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Customize table columns in DICOM browser ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database() # Need to go this way, do not use slicer.dicomDatabase for this&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
* How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
for viewNode in viewNodes:&lt;br /&gt;
  viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
* How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from a normal vector and position==&lt;br /&gt;
&lt;br /&gt;
This code snippet shows how to display a slice view defined by a normal vector and position in an anatomically sensible way: rotating slice view so that &amp;quot;up&amp;quot; direction (or &amp;quot;right&amp;quot; direction) is towards an anatomical axis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition, defaultViewUpDirection=None, backupViewRightDirection=None):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Set slice pose from the provided plane normal and position. View up direction is determined automatically,&lt;br /&gt;
    to make view up point towards defaultViewUpDirection.&lt;br /&gt;
    :param defaultViewUpDirection Slice view will be spinned in-plane to match point approximately this up direction. Default: patient superior.&lt;br /&gt;
    :param backupViewRightDirection Slice view will be spinned in-plane to match point approximately this right direction&lt;br /&gt;
        if defaultViewUpDirection is too similar to sliceNormal. Default: patient left.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Fix up input directions&lt;br /&gt;
    if defaultViewUpDirection is None:&lt;br /&gt;
        defaultViewUpDirection = [0,0,1]&lt;br /&gt;
    if backupViewRightDirection is None:&lt;br /&gt;
        backupViewRightDirection = [-1,0,0]&lt;br /&gt;
    if sliceNormal[1]&amp;gt;=0:&lt;br /&gt;
        sliceNormalStandardized = sliceNormal&lt;br /&gt;
    else:&lt;br /&gt;
        sliceNormalStandardized = [-sliceNormal[0], -sliceNormal[1], -sliceNormal[2]]&lt;br /&gt;
    # Compute slice axes&lt;br /&gt;
    sliceNormalViewUpAngle = vtk.vtkMath.AngleBetweenVectors(sliceNormalStandardized, defaultViewUpDirection)&lt;br /&gt;
    angleTooSmallThresholdRad = 0.25 # about 15 degrees&lt;br /&gt;
    if sliceNormalViewUpAngle &amp;gt; angleTooSmallThresholdRad and sliceNormalViewUpAngle &amp;lt; vtk.vtkMath.Pi() - angleTooSmallThresholdRad:&lt;br /&gt;
        viewUpDirection = defaultViewUpDirection&lt;br /&gt;
        sliceAxisY = viewUpDirection&lt;br /&gt;
        sliceAxisX = [0, 0, 0]&lt;br /&gt;
        vtk.vtkMath.Cross(sliceAxisY, sliceNormalStandardized, sliceAxisX)&lt;br /&gt;
    else:&lt;br /&gt;
        sliceAxisX = backupViewRightDirection&lt;br /&gt;
    # Set slice axes&lt;br /&gt;
    sliceNode.SetSliceToRASByNTP(sliceNormalStandardized[0], sliceNormalStandardized[1], sliceNormalStandardized[2],&lt;br /&gt;
        sliceAxisX[0], sliceAxisX[1], sliceAxisX[2],&lt;br /&gt;
        slicePosition[0], slicePosition[1], slicePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Example usage:&lt;br /&gt;
sliceNode = getNode('vtkMRMLSliceNodeRed')&lt;br /&gt;
transformNode = getNode('Transform_3')&lt;br /&gt;
transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
transformNode.GetMatrixTransformToParent(transformMatrix)&lt;br /&gt;
sliceNormal = [transformMatrix.GetElement(0,2), transformMatrix.GetElement(1,2), transformMatrix.GetElement(2,2)]&lt;br /&gt;
slicePosition = [transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)]&lt;br /&gt;
setSlicePoseFromSliceNormalAndPosition(sliceNode, sliceNormal, slicePosition)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Switching to markup fiducial placement mode ==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change markup fiducial display properties ==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a markup point position is modified ==&lt;br /&gt;
&lt;br /&gt;
Event management of Slicer-4.11 version is still subject to change. The example below shows how point manipulation can be observed now.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupChanged(caller,event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    if movingMarkupIndex &amp;gt;= 0:&lt;br /&gt;
        pos = [0,0,0]&lt;br /&gt;
        markupsNode.GetNthFiducialPosition(movingMarkupIndex, pos)&lt;br /&gt;
        isPreview = markupsNode.GetNthControlPointPositionStatus(movingMarkupIndex) == slicer.vtkMRMLMarkupsNode.PositionPreview&lt;br /&gt;
        if isPreview:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} is previewed at {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
        else:&lt;br /&gt;
            logging.info(&amp;quot;Point {0} was moved {1} in slice view {2}&amp;quot;.format(movingMarkupIndex, pos, sliceView))&lt;br /&gt;
    else:&lt;br /&gt;
        logging.info(&amp;quot;Points modified: slice view = {0}&amp;quot;.format(sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupStartInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()    &lt;br /&gt;
    logging.info(&amp;quot;Start interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
def onMarkupEndInteraction(caller, event):&lt;br /&gt;
    markupsNode = caller&lt;br /&gt;
    sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
    movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()&lt;br /&gt;
    logging.info(&amp;quot;End interaction: point ID = {0}, slice view = {1}&amp;quot;.format(movingMarkupIndex, sliceView))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, onMarkupChanged)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointStartInteractionEvent, onMarkupStartInteraction)&lt;br /&gt;
markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointEndInteractionEvent, onMarkupEndInteraction)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a transform is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a context menu when a markup point is clicked in a slice or 3D view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Example actions to perform&lt;br /&gt;
&lt;br /&gt;
def action1():&lt;br /&gt;
  print('Action1 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action2():&lt;br /&gt;
  print('Action2 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action3():&lt;br /&gt;
  print('Action3 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
# Clicked markup index is saved here to let the action&lt;br /&gt;
# know which markup needs to be manipulated.&lt;br /&gt;
slicer.clickedMarkupIndex = -1&lt;br /&gt;
  &lt;br /&gt;
# Create a simple menu&lt;br /&gt;
&lt;br /&gt;
menu = qt.QMenu()&lt;br /&gt;
a1 = qt.QAction(&amp;quot;Test&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a1.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a1)&lt;br /&gt;
a2 = qt.QAction(&amp;quot;Action&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a2.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a2)&lt;br /&gt;
a3 = qt.QAction(&amp;quot;Here&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a3.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a3)&lt;br /&gt;
&lt;br /&gt;
# Add observer to a markup fiducial list&lt;br /&gt;
&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_INT)&lt;br /&gt;
def markupClickedCallback(caller, eventId, callData):&lt;br /&gt;
  slicer.clickedMarkupIndex = callData&lt;br /&gt;
  print('Open menu on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
  menu.move(qt.QCursor.pos())&lt;br /&gt;
  menu.show()&lt;br /&gt;
&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
observerTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointClickedEvent, markupClickedCallback)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write markup positions to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write annotation ROI to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a simple surface mesh as a model node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to display a simple surface mesh (a box, created by a VTK source filter) as a model node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create and set up polydata source&lt;br /&gt;
box = vtk.vtkCubeSource()&lt;br /&gt;
box.SetXLength(30)&lt;br /&gt;
box.SetYLength(20)&lt;br /&gt;
box.SetZLength(15)&lt;br /&gt;
box.SetCenter(10,20,5)&lt;br /&gt;
&lt;br /&gt;
# Create a model node that displays output of the source&lt;br /&gt;
boxNode = slicer.modules.models.logic().AddModel(box.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Adjust display properties&lt;br /&gt;
boxNode.GetDisplayNode().SetColor(1,0,0)&lt;br /&gt;
boxNode.GetDisplayNode().SetOpacity(0.8)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add a texture mapped plane to the scene as a model ==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# use dummy image data here&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
&lt;br /&gt;
scene = slicer.mrmlScene&lt;br /&gt;
&lt;br /&gt;
# Create model node&lt;br /&gt;
model = slicer.vtkMRMLModelNode()&lt;br /&gt;
model.SetScene(scene)&lt;br /&gt;
model.SetName(scene.GenerateUniqueName(&amp;quot;2DImageModel&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
model.SetAndObservePolyData(planeSource.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create display node&lt;br /&gt;
modelDisplay = slicer.vtkMRMLModelDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
modelDisplay.SetScene(scene)&lt;br /&gt;
scene.AddNode(modelDisplay)&lt;br /&gt;
model.SetAndObserveDisplayNodeID(modelDisplay.GetID())&lt;br /&gt;
&lt;br /&gt;
# Add to scene&lt;br /&gt;
modelDisplay.SetAndObserveTextureImageData(e.GetOutput())&lt;br /&gt;
scene.AddNode(model) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
transform = slicer.vtkMRMLLinearTransformNode()&lt;br /&gt;
scene.AddNode(transform) &lt;br /&gt;
model.SetAndObserveTransformNodeID(transform.GetID())&lt;br /&gt;
&lt;br /&gt;
vTransform = vtk.vtkTransform()&lt;br /&gt;
vTransform.Scale(50,50,50)&lt;br /&gt;
vTransform.RotateX(30)&lt;br /&gt;
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get scalar values at surface of a model ==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Select cells of a using markups fiducial points ==&lt;br /&gt;
&lt;br /&gt;
The following script selects cells of a model node that are closest to positions of markups fiducial points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get input nodes&lt;br /&gt;
modelNode = slicer.util.getNode('Segment_1') # select cells in this model&lt;br /&gt;
markupsNode = slicer.util.getNode('F') # points will be selected at positions specified by this markups fiducial node&lt;br /&gt;
&lt;br /&gt;
# Create scalar array that will store selection state&lt;br /&gt;
selectionArray = vtk.vtkIntArray()&lt;br /&gt;
selectionArray.SetName('selection')&lt;br /&gt;
selectionArray.SetNumberOfValues(modelNode.GetMesh().GetNumberOfCells())&lt;br /&gt;
selectionArray.Fill(0)&lt;br /&gt;
&lt;br /&gt;
cellScalars = modelPointValues = modelNode.GetMesh().GetCellData()&lt;br /&gt;
cellScalars.AddArray(selectionArray)&lt;br /&gt;
&lt;br /&gt;
modelNode.GetDisplayNode().SetActiveScalar(&amp;quot;selection&amp;quot;, vtk.vtkAssignAttribute.CELL_DATA)&lt;br /&gt;
modelNode.GetDisplayNode().SetScalarVisibility(True)&lt;br /&gt;
&lt;br /&gt;
cell = vtk.vtkCellLocator()&lt;br /&gt;
cell.SetDataSet(modelNode.GetMesh())&lt;br /&gt;
cell.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onPointsModified(observer=None, eventid=None):&lt;br /&gt;
    global markupsNode, selectionArray&lt;br /&gt;
    selectionArray.Fill(0) # set all cells to non-selected by default&lt;br /&gt;
    markupPoints = slicer.util.arrayFromMarkupsControlPoints(markupsNode)&lt;br /&gt;
    for markupPoint in markupPoints:&lt;br /&gt;
        closestCell = cell.FindCell(markupPoint)&lt;br /&gt;
        if closestCell &amp;gt;=0:&lt;br /&gt;
            selectionArray.SetValue(closestCell, 100) # set selected cell's scalar value to non-zero&lt;br /&gt;
    selectionArray.Modified()&lt;br /&gt;
&lt;br /&gt;
# Initial update&lt;br /&gt;
onPointsModified()&lt;br /&gt;
# Automatic update each time when a markup point is modified&lt;br /&gt;
markupsNodeObserverTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsFiducialNode.PointModifiedEvent, onPointsModified)&lt;br /&gt;
&lt;br /&gt;
# To stop updating selection, run this:&lt;br /&gt;
# markupsNode.RemoveObserver(markupsNodeObserverTag)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export entire scene as VRML ==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export model to Blender, including color by scalar ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export a tract (FiberBundle) to Blender, including color ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Iterate over tract (FiberBundle) streamline points ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a volume ==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a new volume ==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
thresholder = vtk.vtkImageThreshold()&lt;br /&gt;
thresholder.SetInputData(imageData)&lt;br /&gt;
thresholder.SetInValue(fillVoxelValue)&lt;br /&gt;
thresholder.SetOutValue(fillVoxelValue)&lt;br /&gt;
thresholder.Update()&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(thresholder.GetOutput())&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify voxels in a volume ==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.SetScalarComponentFromFloat(distortionVectorPosition_Ijk[0], distortionVectorPosition_Ijk[1], distortionVectorPosition_Ijk[2], 0, fillValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get volume voxel coordinates from markup fiducial RAS coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get markup fiducial RAS coordinates from volume voxel coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get the values of all voxels for a label value  ==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Access values in a DTI tensor volume ==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change window/level (brightness/contrast) or colormap of a volume ==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Make mouse left-click and drag on the image adjust window/level ==&lt;br /&gt;
&lt;br /&gt;
In older Slicer versions, by default, left-click and drag in a slice view adjusted window/level of the displayed image. Window/level adjustment is now a new mouse mode that can be activated by clicking on its toolbar button or running this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.applicationLogic().GetInteractionNode().SetCurrentInteractionMode(slicer.vtkMRMLInteractionNode.AdjustWindowLevel)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create custom color table ==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Manipulate a Slice View ==&lt;br /&gt;
&lt;br /&gt;
=== Change slice offset ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Change slice orientation ===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show slice views in 3D window ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reset field of view to show background volume maximized ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rotate slice views to volume plane ===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Iterate over current visible slice views, and set foreground and background images ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     sliceWidget = layoutManager.sliceWidget(sliceViewName)&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Synchronize zoom factor between slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.sliceNodes = [slicer.app.layoutManager().sliceWidget(viewName).mrmlSliceNode()&lt;br /&gt;
    for viewName in slicer.app.layoutManager().sliceViewNames()]&lt;br /&gt;
&lt;br /&gt;
slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
def sliceModified(caller, event):&lt;br /&gt;
    if slicer.updatingSliceNodes:&lt;br /&gt;
        # prevent infinite loop of slice node updates triggering slice node updates&lt;br /&gt;
        return&lt;br /&gt;
    slicer.updatingSliceNodes = True&lt;br /&gt;
    fov = caller.GetFieldOfView()&lt;br /&gt;
    for sliceNode in slicer.sliceNodes:&lt;br /&gt;
        if sliceNode != caller:&lt;br /&gt;
            sliceNode.SetFieldOfView(*fov)&lt;br /&gt;
    slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
for sliceNode in slicer.sliceNodes:&lt;br /&gt;
    sliceNode.AddObserver(vtk.vtkCommand.ModifiedEvent, sliceModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change opacity of foreground volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fit slice plane to markup fiducials ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.array([0,0,0])&lt;br /&gt;
p2 = np.array([0,0,0])&lt;br /&gt;
p3 = np.array([0,0,0])&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0, 0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a series of images from a Slice View ==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a new directory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a single MRB file ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a node to file ==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Center the 3D View on the Scene ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Display text in a 3D view or slice view ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide slice view annotations (DataProbe) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Turning off interpolation ==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Customize viewer layout ==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;layout type=&amp;quot;vertical&amp;quot; split=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLSliceNode&amp;quot; singletontag=&amp;quot;Red&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;orientation&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewcolor&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/layout&amp;gt;&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Built-in layout IDs are all below 100, so you can choose any large random number&lt;br /&gt;
# for your custom layout ID.&lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
&lt;br /&gt;
# Switch to the new custom layout &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
You can use this code snippet to add a button to the layout selector toolbar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Add button to layout selector toolbar for this custom layout&lt;br /&gt;
viewToolBar = mainWindow().findChild('QToolBar', 'ViewToolBar')&lt;br /&gt;
layoutMenu = viewToolBar.widgetForAction(viewToolBar.actions()[0]).menu()&lt;br /&gt;
layoutSwitchActionParent = layoutMenu  # use `layoutMenu` to add inside layout list, use `viewToolBar` to add next the standard layout list&lt;br /&gt;
layoutSwitchAction = layoutSwitchActionParent.addAction(&amp;quot;My view&amp;quot;) # add inside layout list&lt;br /&gt;
layoutSwitchAction.setIcon(qt.QIcon(':Icons/Go.png'))&lt;br /&gt;
layoutSwitchAction.setToolTip('3D and slice view')&lt;br /&gt;
layoutSwitchAction.connect('triggered()', lambda layoutId = customLayoutId: slicer.app.layoutManager().setLayout(layoutId))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Customize keyboard shortcuts ==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Disable certain user interactions in slice views ==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change default slice view orientation ==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Set all slice views linked by default ==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set crosshair jump mode to centered by default ==&lt;br /&gt;
&lt;br /&gt;
You can change default slice jump mode (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
crosshair=slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLCrosshairNode&amp;quot;)&lt;br /&gt;
crosshair.SetCrosshairBehavior(crosshair.CenteredJumpSlice)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set up custom units in slice view ruler ==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in range(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a slice view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;TS&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
viewNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(layoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
viewWidget.sliceViewName = layoutName&lt;br /&gt;
viewWidget.sliceViewLabel = layoutLabel&lt;br /&gt;
c = viewNode.GetLayoutColor()&lt;br /&gt;
viewWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLSliceNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a 3D view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = &amp;quot;Test3DView&amp;quot;&lt;br /&gt;
layoutLabel = &amp;quot;T3&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML node&lt;br /&gt;
viewNode = slicer.vtkMRMLViewNode()&lt;br /&gt;
viewNode.SetName(layoutName)&lt;br /&gt;
viewNode.SetLayoutName(layoutName)&lt;br /&gt;
viewNode.SetLayoutLabel(layoutLabel)&lt;br /&gt;
viewNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
viewNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
viewNode = slicer.mrmlScene.AddNode(viewNode)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
viewWidget = slicer.qMRMLThreeDWidget()&lt;br /&gt;
viewWidget.viewLabel = layoutLabel&lt;br /&gt;
viewWidget.viewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
viewWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
viewWidget.setMRMLViewNode(viewNode)&lt;br /&gt;
viewWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get displayable manager of a certain type for a certain view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelDisplayableManager = None&lt;br /&gt;
threeDViewWidget = slicer.app.layoutManager().threeDWidget(0)&lt;br /&gt;
managers = vtk.vtkCollection()&lt;br /&gt;
threeDViewWidget.getDisplayableManagers(managers)&lt;br /&gt;
for i in range(managers.GetNumberOfItems()):&lt;br /&gt;
  obj = managers.GetItemAsObject(i)&lt;br /&gt;
  if obj.IsA('vtkMRMLModelDisplayableManager'):&lt;br /&gt;
    modelDisplayableManager = obj&lt;br /&gt;
    break&lt;br /&gt;
if modelDisplayableManager is None:&lt;br /&gt;
  logging.error('Failed to find the model displayable manager')&lt;br /&gt;
  return&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Running an ITK filter in Python using SimpleITK ==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
* See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
* 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&lt;br /&gt;
&lt;br /&gt;
== Get current mouse coordinates in a slice view ==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get DataProbe text ==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get reformatted image from a slice viewer as numpy array ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print voxels.shape&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thick slab reconstruction and maximum/minimum intensity volume projections ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
== Change default file type for nodes (that have never been saved yet) ==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
== Change file type for saving for all volumes (with already existing storage nodes) ==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sequences ==&lt;br /&gt;
&lt;br /&gt;
=== Concatenate all sequences in the scene into a new sequence ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Segmentations ==&lt;br /&gt;
&lt;br /&gt;
=== Create a segmentation from a labelmap volume and display in 3D ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
=== Export labelmap node from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
Export smallest possible labelmap:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export labelmap that matches geometry of a chosen reference volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export by pressing Ctrl+Shift+s key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPath = &amp;quot;c:/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def exportLabelmap():&lt;br /&gt;
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLSegmentationNode&amp;quot;)&lt;br /&gt;
    referenceVolumeNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
    labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
    slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
    filepath = outputPath + &amp;quot;/&amp;quot; + referenceVolumeNode.GetName()+&amp;quot;-label.nrrd&amp;quot;&lt;br /&gt;
    slicer.util.saveNode(labelmapVolumeNode, filepath)&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode.GetDisplayNode().GetColorNode())&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
    slicer.util.delayDisplay(&amp;quot;Segmentation saved to &amp;quot;+filepath)&lt;br /&gt;
&lt;br /&gt;
shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
shortcut.setKey(qt.QKeySequence('Ctrl+Shift+s'))&lt;br /&gt;
shortcut.connect( 'activated()', exportLabelmap)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Export model nodes from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
exportedModelsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelHierarchyNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModelHierarchy(seg, exportedModelsNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show a segmentation in 3D ===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get a representation of a segment ===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = segmentationNode.GetBinaryLabelmapRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using default path and conversion parameters ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using custom path or conversion parameters ===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-convert using a modified conversion parameter ===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get centroid of a segment in world (RAS) coordinates ===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How to run segment editor effects from a script ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
* [https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
* [https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
* [https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
* [https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
== Accessing views, renderers, and cameras ==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide view controller bars ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Customize widgets in view controller bars ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceController = slicer.app.layoutManager().sliceWidget(&amp;quot;Red&amp;quot;).sliceController()&lt;br /&gt;
&lt;br /&gt;
# hide what is not needed&lt;br /&gt;
sliceController.pinButton().hide()&lt;br /&gt;
#sliceController.viewLabel().hide()&lt;br /&gt;
sliceController.fitToWindowToolButton().hide()&lt;br /&gt;
sliceController.sliceOffsetSlider().hide()&lt;br /&gt;
&lt;br /&gt;
# add custom widgets&lt;br /&gt;
myButton = qt.QPushButton(&amp;quot;My custom button&amp;quot;)&lt;br /&gt;
sliceController.barLayout().addWidget(b)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change 3D view background color ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderer = renderWindow.GetRenderers().GetFirstRenderer()&lt;br /&gt;
renderer.SetBackground(1,0,0)&lt;br /&gt;
renderer.SetBackground2(1,0,0)&lt;br /&gt;
renderWindow.Render()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subject hierarchy == &lt;br /&gt;
==== Get the pseudo-singleton subject hierarchy node ====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
&lt;br /&gt;
==== Create subject hierarchy item ====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
==== Get subject hierarchy item ====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
==== Traverse children of a subject hierarchy item ====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in range(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
==== Manipulate subject hierarchy item ====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data nodes associated to items in a branch (or a leaf item)&lt;br /&gt;
  shNode.SetDisplayVisibilityForBranch(itemID, 1)&lt;br /&gt;
&lt;br /&gt;
==== Filter items in TreeView or ComboBox ====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
=== Listen to subject hierarchy item events ===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
== Plotting ==&lt;br /&gt;
&lt;br /&gt;
=== Slicer plots displayed in view layout ===&lt;br /&gt;
&lt;br /&gt;
Create histogram plot of a volume and show it embedded in the view layout. More information: https://www.slicer.org/wiki/Documentation/Nightly/Developers/Plots&lt;br /&gt;
&lt;br /&gt;
==== Using &amp;lt;code&amp;gt;slicer.util.plot&amp;lt;/code&amp;gt; utility function ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
chartNode = slicer.util.plot(histogram, xColumnIndex = 1)&lt;br /&gt;
chartNode.SetYAxisRangeAuto(False)&lt;br /&gt;
chartNode.SetYAxisRange(0, 4e5)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:SlicerPlot.png]]&lt;br /&gt;
&lt;br /&gt;
==== Using MRML classes only ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using matplotlib ===&lt;br /&gt;
&lt;br /&gt;
Matplotlib may be used from within Slicer, but the default Tk backend locks up and crashes Slicer. However, Matplotlib may still be used through other backends. More details can be found on the [http://matplotlib.sourceforge.net/ MatPlotLib] pages.&lt;br /&gt;
&lt;br /&gt;
==== Non-interactive plot ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
&lt;br /&gt;
# Static image view&lt;br /&gt;
pm = qt.QPixmap(&amp;quot;MatplotlibExample.png&amp;quot;)&lt;br /&gt;
imageWidget = qt.QLabel()&lt;br /&gt;
imageWidget.setPixmap(pm)&lt;br /&gt;
imageWidget.setScaledContents(True)&lt;br /&gt;
imageWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:MatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==== Plot in Slicer Jupyter notebook ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
matplotlib.use('Agg')&lt;br /&gt;
from pylab import *&lt;br /&gt;
&lt;br /&gt;
t1 = arange(0.0, 5.0, 0.1)&lt;br /&gt;
t2 = arange(0.0, 5.0, 0.02)&lt;br /&gt;
t3 = arange(0.0, 2.0, 0.01) &lt;br /&gt;
&lt;br /&gt;
subplot(211)&lt;br /&gt;
plot(t1, cos(2*pi*t1)*exp(-t1), 'bo', t2, cos(2*pi*t2)*exp(-t2), 'k')&lt;br /&gt;
grid(True)&lt;br /&gt;
title('A tale of 2 subplots')&lt;br /&gt;
ylabel('Damped')&lt;br /&gt;
&lt;br /&gt;
subplot(212)&lt;br /&gt;
plot(t3, cos(2*pi*t3), 'r--')&lt;br /&gt;
grid(True)&lt;br /&gt;
xlabel('time (s)')&lt;br /&gt;
ylabel('Undamped')&lt;br /&gt;
savefig('MatplotlibExample.png')&lt;br /&gt;
display(filename='MatplotlibExample.png', type=&amp;quot;image/png&amp;quot;, binary=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:JupyterNotebookMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
==== Interactive plot using wxWidgets GUI toolkit ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
  import matplotlib&lt;br /&gt;
  import wx&lt;br /&gt;
except ModuleNotFoundError:&lt;br /&gt;
  pip_install('matplotlib wxPython')&lt;br /&gt;
  import matplotlib&lt;br /&gt;
&lt;br /&gt;
# Get a volume from SampleData and compute its histogram&lt;br /&gt;
import SampleData&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Set matplotlib to use WXAgg backend&lt;br /&gt;
import matplotlib&lt;br /&gt;
matplotlib.use('WXAgg')&lt;br /&gt;
&lt;br /&gt;
# Show an interactive plot&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
fig, ax = plt.subplots()&lt;br /&gt;
ax.plot(histogram[1][1:], histogram[0].astype(float))&lt;br /&gt;
ax.grid(True)&lt;br /&gt;
ax.set_ylim((0, 4e5))&lt;br /&gt;
plt.show(block=False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:InteractiveMatplotlibExample.png]]&lt;br /&gt;
&lt;br /&gt;
== Execute external applications ==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
=== Run process in default environment ===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/Segmentations&amp;diff=61393</id>
		<title>Documentation/Nightly/Modules/Segmentations</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/Segmentations&amp;diff=61393"/>
		<updated>2019-09-05T20:14:12Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
This work is part of the SparKit project, funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health and Long-Term Care and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&amp;lt;br&amp;gt;&lt;br /&gt;
Author: Csaba Pinter (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contact: Csaba Pinter, &amp;lt;email&amp;gt;pinter.csaba@gmail.com&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
|{{collaborator|logo|sparkit}}|{{collaborator|longname|sparkit}}&lt;br /&gt;
|{{collaborator|logo|ocairo}}|{{collaborator|longname|ocairo}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
The {{documentation/modulename}} module manages segmentations. Each segmentation can contain multiple segments, which correspond to one structure or ROI. Each segment can contain multiple data representations for the same structure, and the module supports automatic conversion between these representations (the default ones are: planar contour, binary labelmap, closed surface model), as well as advanced display settings and import/export features.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Motivation, features, and details of the infrastructure are explained in [https://www.slicer.org/w/images/6/64/20160526_Segmentations.pptx these slides] ([https://www.slicer.org/w/images/a/ae/20160526_Segmentations.pdf PDF]).'''&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Note: It is important to remember that segmentations are not labelmaps, i.e. they are not one 3D volume containing color indices in a color table. There is a legacy labelmap support that temporarilymerges the segments into an old-school labelmap, but that feature will be removed, and under the hood the segmentation node is structured as explained above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
* 3D printing: Convert labelmaps to surface models and export them to STL&lt;br /&gt;
* Contour analysis: Convert RT planar contours to labelmap for per-voxel analysis&lt;br /&gt;
* Nice and flexible visualization: Show any structure as 3D surface, and line intersections in 2D views; Show surface and labelmap simultaneously&lt;br /&gt;
* Organize segmented structures: Each segmentation contains multiple &amp;quot;segments&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20160526_SegmentationObject.PNG|thumb|371px| Segmentation node containing and managing multiple structures (called segments - the columns in the figure) in multiple representations (rows)]]&lt;br /&gt;
|[[File:20150710_SegmentationsModuleUI.png|thumb|480px| Segmentations module UI]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Training#Slicer4_Image_Segmentation|Segmentation tutorials]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|How to}}&lt;br /&gt;
&lt;br /&gt;
; Edit segmentation&lt;br /&gt;
: Segment structures in the '''[{{documentation/{{documentation/version}}/slicer-manual-base-url}}/user_guide/module_segmenteditor.html Segment Editor]''' module&lt;br /&gt;
&lt;br /&gt;
; ''Import labelmap'' volume or ''model'' into segmentation&lt;br /&gt;
# In Segmentations module&lt;br /&gt;
#* Expand Export/import models and labelmaps section at the bottom of the Segmentations module (it is collapsed by default)&lt;br /&gt;
#* Select Import, import type, then choose imported node: labelmap, model, or folder containing models&lt;br /&gt;
#* Click Import&lt;br /&gt;
# In Data module (Subject hierarchy tab)&lt;br /&gt;
#* Right-click model or model hierarchy node&lt;br /&gt;
#* Select 'Convert model to segmentation node'&lt;br /&gt;
&lt;br /&gt;
; ''Export labelmap'' or surface ''model'' from segmentation (for saving to STL, editing, etc).&lt;br /&gt;
# Expand the Export/import segments section at the bottom of the Segmentations module (it is collapsed by default). Select output type, then click Export. If exporting to an existing node is needed, it can be selected as Output node. If only a subset of the segments are needed, then open the Advanced section, where this selection can be changed, along with the reference volume.&lt;br /&gt;
# Switch to the Data module and make sure the Subject hierarchy tree is selected. Right-click the segmentation node, then select one of the Export functions&lt;br /&gt;
: To save exported result to file, use the Save data dialog (left side of top toolbar). To save to STL, change the File Format selector to STL in the rows of the models to be saved.&lt;br /&gt;
&lt;br /&gt;
; Create new representation in segmentation (conversion)&lt;br /&gt;
: The supported representations are listed as rows in the Representations section. The already existing representations have a green tick, the master representation (that is the source of all conversions and the representation that can be edited) a gold star&lt;br /&gt;
: To create a representation that is missing, click on the Create button in its row. If custom conversion path or parameters are to be used (reference grid for labelmaps, smoothing for surfaces, etc.), long-press the button and choose &amp;quot;Advanced create...&amp;quot;. In the appearing window the available conversion paths are listed in a list, ordered by estimated time cost. After selecting the desired path, the involved parameters are listed in the bottom section of the window&lt;br /&gt;
: To re-convert an existing representation (to use different conversion path or parameters), click the Update buitton in their row&lt;br /&gt;
&lt;br /&gt;
; Change display mode of segments&lt;br /&gt;
# By long-pressing the eye icon in the segments table the display options are shown and the different display modes can be turned on or off&lt;br /&gt;
# In Data module's Subject hierarchy, right-clicking the visibility eye icon next to the segmentation node or its segments also offers advanced display options&lt;br /&gt;
&lt;br /&gt;
; Managing segmentations in python&lt;br /&gt;
: See [https://www.slicer.org/slicerWiki/index.php?title=Documentation/Nightly/ScriptRepository#Segmentations Segmentations section] in the script in repository&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
* Segments table&lt;br /&gt;
** Add/remove segments&lt;br /&gt;
** Edit selected: takes user to [[Documentation/{{documentation/version}}/Modules/SegmentEditor|Segment Editor]] module&lt;br /&gt;
** Set visibility and per-segment display settings, opacity, color, segment name&lt;br /&gt;
* Display&lt;br /&gt;
** Segmentations-wide display settings (not per-segment!): visibility, opacity (will be multiplied with per-segment opacity for display)&lt;br /&gt;
** Views: Individual views to show the active segmentation in&lt;br /&gt;
** Slice intersection thickness&lt;br /&gt;
** Representation in 3D/2D views: The representation to be shown in the 3D and 2D views. Useful if there are multiple representations available, for example if we want to show the closed surface in the 3D view but the labelmap in the slice views&lt;br /&gt;
* Representations&lt;br /&gt;
** List of supported representations and related operations &lt;br /&gt;
** The already existing representations have a green tick, the master representation (that is the source of all conversions and the representation that can be edited) a gold star&lt;br /&gt;
** The buttons in each row can be used to create, remove, update a representation&lt;br /&gt;
*** Advanced conversion is possible (to use the non-default path or conversion parameters) by long-pressing the Create or Update button&lt;br /&gt;
*** Existing representations can be made master by clicking Make master. The master representation is used as source for conversions, it is the one that can be edited, and saved to disk&lt;br /&gt;
* Copy/move (import/export)&lt;br /&gt;
** Left panel lists the segments in the active segmentation&lt;br /&gt;
** Right panel shows the external data container&lt;br /&gt;
** The arrow buttons van be used to copy (with plus sign) or move (no plus sign) segments between the segmentation and the external node&lt;br /&gt;
** New labelmap or model can be created by clicking the appropriate button on the top of the right panel&lt;br /&gt;
** Multiple segments can be exported into a labelmap. In case of overlapping segments, the subsequent segments will overwrite the previous ones!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
''' Subject hierarchy support'''&lt;br /&gt;
* Segmentations are shown in subject hierarchy as any other node, with the exception that the contained segments are in a &amp;quot;virtual branch&amp;quot;.&lt;br /&gt;
** The segments can be moved between segmentations, but drag&amp;amp;drop to anywhere other than under another segmentation is not allowed&lt;br /&gt;
* Special subject hierarchy features for segmentations&lt;br /&gt;
** Create representation: Create the chosen representation using the default path&lt;br /&gt;
* Special subject hierarchy features for segments&lt;br /&gt;
** Show only this segment: Useful if only one segment needs to be shown and there are many, so clicking the eye buttons woud take a long time&lt;br /&gt;
** Show all segments&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
''' DICOM export '''&lt;br /&gt;
* The master representation is used when exporting into DICOM&lt;br /&gt;
* RT structure set export is available if SlicerRT is installed&lt;br /&gt;
* DICOM SegObj export - coming soon!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{documentation/{{documentation/version}}/module-parametersdescription}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
* [http://slicer.readthedocs.io/en/latest/user_guide/module_segmenteditor.html Segment Editor] module is used to edit Segmentation nodes&lt;br /&gt;
* This module and infrastructure is a successor of the [[Documentation/4.4/Modules/Contours|Contours]] module and mechanism, which was the first implementation for this task, but its design was overgrown by the new features and needs, and became inconvenient and unstable. Further information about the Segmentation effort on the related [https://github.com/SlicerRt/SlicerRT/wiki/Segmentation design wiki page], the [https://www.slicer.org/wiki/Documentation/Labs/Segmentations labs wiki page], and the links pointing from these pages.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
* Past references&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
** Issue for Segmentations (complete Contours overhaul, delivery June 2015) [https://www.assembla.com/spaces/slicerrt/tickets/626 here]&lt;br /&gt;
** Issue for original Contours effort on SlicerRT Assembla ticketing system [https://www.assembla.com/spaces/slicerrt/tickets/137 here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
** Development notes [https://github.com/SlicerRt/SlicerRT/wiki/Segmentation wiki page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
* [https://github.com/Slicer/Slicer/tree/master/Libs/vtkSegmentationCore vtkSegmentationCore on GitHub] (within Slicer)&lt;br /&gt;
* [https://github.com/Slicer/Slicer/tree/master/Modules/Loadable/Segmentations Segmentations Slicer module on GitHub]&lt;br /&gt;
* [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/Segmentations Labs page]&lt;br /&gt;
* Numerous scripting examples are listed in the [https://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/ScriptRepository Script repository] page&lt;br /&gt;
* How to create new representation or converter - TODO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
=FAQ=&lt;br /&gt;
; The closed surface generated from the RT Structure Set contour points is flawed&lt;br /&gt;
: Please [[Documentation/SlicerRT/HowToReportAnError|report]] the issue first so that we can fix the conversion.&lt;br /&gt;
: Use advanced conversion and choose a path through Ribbon model representation. SlicerRT extension needs to be installed for this.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61350</id>
		<title>Documentation/Nightly/Extensions/SlicerRT</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61350"/>
		<updated>2019-08-09T19:10:54Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Comprehensive tutorials */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
[[{{collaborator|logo|cco}}]] &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|canarie}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|ocairo}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|sparkit}}]]&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
Authors: &amp;lt;b&amp;gt;Csaba Pinter&amp;lt;/b&amp;gt; (PerkLab, Queen's University), &amp;lt;b&amp;gt;Andras Lasso&amp;lt;/b&amp;gt; (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contributors: &amp;lt;b&amp;gt;Greg Sharp&amp;lt;/b&amp;gt; (Massachusetts General Hospital), Kevin Wang (Princess Margaret Hospital, UHN Toronto), Steve Pieper (Isomics)&amp;lt;br&amp;gt;&lt;br /&gt;
Contacts:&lt;br /&gt;
* Csaba Pinter, &amp;lt;email&amp;gt;pinter.csaba@gmail.com&amp;lt;/email&amp;gt;&lt;br /&gt;
* Andras Lasso, &amp;lt;email&amp;gt;lasso@cs.queensu.ca&amp;lt;/email&amp;gt;&lt;br /&gt;
* [https://discourse.slicer.org Slicer Forum]&lt;br /&gt;
* [[Documentation/SlicerRT/HowToReportAnError|How to report an error]]&lt;br /&gt;
Website: [http://slicerrt.github.io slicerrt.org]&amp;lt;br&amp;gt;&lt;br /&gt;
License: [http://www.slicer.org/pages/LicenseText Slicer license]&amp;lt;br&amp;gt;&lt;br /&gt;
'''Download/install:''' install 3D Slicer, start 3D Slicer, open the Extension Manager, install the SlicerRT extension (see more details [http://slicerrt.github.io/Download.html on the download page])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; margin-left:12px;&amp;quot;&amp;gt;&lt;br /&gt;
importScript('http://www.ohloh.net/p/641228/widgets/project_basic_stats.js');&lt;br /&gt;
&amp;lt;wiki:gadget url=&amp;quot;http://www.ohloh.net/p/641228/widgets/project_search_code.xml&amp;quot; height=&amp;quot;195&amp;quot; border=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Extension Description}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
[[Image:SlicerRT_Logo_3.0_128x128.png]]&lt;br /&gt;
|&lt;br /&gt;
* SlicerRT is a radiation therapy toolkit for 3D Slicer, containing generic RT features for import/export, analysis, visualization, aiming to make 3D Slicer a powerful radiotherapy research platform. SlicerRT development is currently funded by CANARIE.&amp;lt;br&amp;gt;SlicerRT was originally created via funding by Cancer Care Ontario and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&lt;br /&gt;
&lt;br /&gt;
* The SlicerRT extension incorporates [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]] modules and algorithms.&lt;br /&gt;
&lt;br /&gt;
* Additional information for users can be found on the [[Documentation/SlicerRT/UsersGuide|User's Guide]] page &amp;lt;br&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Modules}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
*[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External Beam Planning]] (Treatment planning)&lt;br /&gt;
* Dose analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseVolumeHistogram|Dose volume histogram]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseAccumulation|Dose accumulation]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseComparison|Dose comparison]] (Gamma dose similarity index)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Isodose|Isodose line and surface display]]&lt;br /&gt;
* Contour analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentComparison|Segment comparison]] (Dice Similarity Coefficient, Hausdorff distances)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentMorphology|Segment morphology]] (Add/remove margin, Unify, Intersect, etc.)&lt;br /&gt;
* I/O&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DicomRtImport|DICOM-RT import]], [https://www.slicer.org/wiki/Documentation/Nightly/Modules/DICOM#DICOM_export export] (handles datasets of types RT Structure Set, RT Dose, RT Plan, RT Image)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DicomSroImport|DICOM-SRO import/export]] (handles DICOM Spatial Registration object, both rigid and deformable)&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing Batch processing scripts] (currently only one is available for command-line conversion of RTSS to volume nodes)&lt;br /&gt;
&lt;br /&gt;
* Modules from [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmBSplineDeformableRegistration|Plastimatch Automatic deformable image registration]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmLANDWARP|Plastimatch LANDWARP Landmark]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmSyntheticImageGeneration|Plastimatch Synthetic Image Generation]] (Greg Sharp)[[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Former SlicerRT modules integrated to Slicer core&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Data|Subject hierarchy]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Transforms|Transform visualizer]]&lt;br /&gt;
**DICOM-RT export, as [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/DICOMExport improved DICOM export function]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Segmentations|Segmentations]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentEditor|Segment Editor]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Experimental modules&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External beam planning]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
| [[File:SlicerRt_Montage.jpg|512px|SlicerRT highlights]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Use Cases}}&lt;br /&gt;
* Comparison of dose maps and dose volume histograms from various treatment planning systems&lt;br /&gt;
* Evaluation of the effect of different adaptive techniques (IGRT, image-based non-rigid patient motion compensation, etc.)&lt;br /&gt;
** Calculate couch shift parameters for patient setup correction in IGRT&lt;br /&gt;
* Dose accumulation with motion compensation&lt;br /&gt;
* Testing of treatment planning algorithms&lt;br /&gt;
* Calculation of PTV margin&lt;br /&gt;
* Proton dose calculation&lt;br /&gt;
* Gel dosimetry analysis&lt;br /&gt;
* Tumor volume tracking&lt;br /&gt;
* Treatment plan similarity measurement in the cloud&lt;br /&gt;
* Batch structure set conversion&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Tutorials}}&lt;br /&gt;
&lt;br /&gt;
=== Comprehensive tutorials ===&lt;br /&gt;
&lt;br /&gt;
* '''Image-guided radiation therapy tutorial 2019''' ''(recommended)''&lt;br /&gt;
** [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_IGRT_4.11.pptx Slides including dataset]&lt;br /&gt;
* '''World Congress 2015 tutorial'''&lt;br /&gt;
** Tutorial presentation: [https://www.dropbox.com/s/b7qx3n10s52o5f8/SlicerRT_WorldCongress_TutorialIGRT.pptx?dl=0 pptx] [https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SlicerRT_WorldCongress_TutorialIGRT.pdf pdf]&lt;br /&gt;
** Dataset: [http://slicer.kitware.com/midas3/download/item/205391/WC2015_Gel_Slicelet_Dataset.zip download] from MIDAS&lt;br /&gt;
* '''Summer NA-MIC week 2013 tutorial'''&lt;br /&gt;
** Tutorial presentation: [http://wiki.na-mic.org/Wiki/images/b/b0/SlicerRT_TutorialContestSummer2013.pdf download] from Slicer wiki&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/download/folder/1345/SlicerRtTutorial_Namic2013June.zip download] from MIDAS&lt;br /&gt;
* '''ECR 2013 - Medical University Vienna workshop'''&lt;br /&gt;
** Workshop material: [http://www.na-mic.org/Wiki/index.php/File:Pinter_MedUni2013_Workshop.pdf download] from NA-MIC.org&lt;br /&gt;
* '''RSNA 2012 tutorial'''&lt;br /&gt;
** Tutorial description: [http://www.donotlink.com/bEo SlicerRT wiki: Slicer tutorials at RSNA 2012]&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/folder/859 download] SlicerRT ART dose verification data from Midas server&lt;br /&gt;
&lt;br /&gt;
=== Module tutorials ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_OrthovoltageDoseEngine.pptx External beam planning tutorial for orthovoltage RT] (uses EGSnrc)&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_DoseSurfaceHistogram.pptx Dose surface histogram tutorial]&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_Isodose.pptx Isodose tutorial]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Similar Extensions}}&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]: SlicerRT and Plastimatch are complementary software libraries. Plastimatch focuses on delivering new computational methods radiotherapy, while SlicerRT aims for providing an easy-to-use interface for a wide range of stable, well-tested radiotherapy related features. SlicerRT uses Plastimatch internally for certain operations.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/GelDosimetry|Gel Dosimetry]]: Slicelet facilitating a streamlined workflow to perform true 3D gel dosimetry analysis for commissioning linacs and evaluating new dose calculation procedures&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/FilmDosimetry|Film Dosimetry]]: Slicelet supporting workflow to perform 2D film dosimetry analysis for commissioning new radiation techniques and to validate the accuracy of radiation treatment by enabling visual comparison of the planned dose to the delivered dose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|References}}&lt;br /&gt;
==How to cite==&lt;br /&gt;
Please cite the following paper when referring to SlicerRt in your publication:&amp;lt;br&amp;gt;&lt;br /&gt;
C. Pinter, A. Lasso, A. Wang, D. Jaffray and G. Fichtinger, [http://perk.cs.queensu.ca/sites/perk.cs.queensu.ca/files/Pinter2012_0.pdf &amp;quot;SlicerRT – Radiation therapy research toolkit for 3D Slicer&amp;quot;], Med. Phys., 39(10) pp. 6332-6338, 2012&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@ARTICLE{Pinter2012,&lt;br /&gt;
  author = {Pinter, C. and Lasso, A. and Wang, A. and Jaffray, D. and Fichtinger, G.},&lt;br /&gt;
  title = {SlicerRT – Radiation therapy research toolkit for 3D Slicer},&lt;br /&gt;
  journal = {Med. Phys.},&lt;br /&gt;
  year = {2012},&lt;br /&gt;
  volume = {39},&lt;br /&gt;
  number = {10},&lt;br /&gt;
  pages = {6332-6338},&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Information for Developers}}&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/wiki/SlicerRt-developers-page SlicerRT developers wiki page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/FilmDosimetry&amp;diff=61347</id>
		<title>Documentation/Nightly/Modules/FilmDosimetry</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/FilmDosimetry&amp;diff=61347"/>
		<updated>2019-08-08T18:52:17Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Film dosimetry analysis workflow: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
[[File:LogoCco.png|Cancer Care Ontario]]&lt;br /&gt;
[[File:Logo-SparKit.png|SparKit]]&lt;br /&gt;
[[File:LogoOCAIRO.jpg|SparKit]]&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
Authors: &amp;lt;b&amp;gt;Csaba Pinter&amp;lt;/b&amp;gt; (PerkLab, Queen's University), Kevin Alexander (KGH, Queen's University), Alec Robinson (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contributors: John Schreiner (Kingston General Hospital)&amp;lt;br&amp;gt;&lt;br /&gt;
Contacts:&lt;br /&gt;
* Csaba Pinter, &amp;lt;email&amp;gt;csaba.pinter@queensu.ca&amp;lt;/email&amp;gt;&lt;br /&gt;
* Kevin Alexander, &amp;lt;email&amp;gt;Kevin.Alexander@krcc.on.ca&amp;lt;/email&amp;gt;&lt;br /&gt;
* [[Documentation/SlicerRT/HowToReportAnError|How to report an error]]&lt;br /&gt;
License: [http://www.slicer.org/pages/LicenseText Slicer license]&amp;lt;br&amp;gt;&lt;br /&gt;
'''Download/install:''' install 3D Slicer, start 3D Slicer, open the Extension Manager, install SlicerRT extension, restart, install the FilmDosimetry extension&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Extension Description}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|[[Image:FilmDosimetry_Logo_128x128.png]]&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
* Film dosimetry analysis is a 2D dosimetry tool used in commissioning new radiation techniques and to validate the accuracy of radiation treatment by enabling visual comparison of the planned dose to the delivered dose.&lt;br /&gt;
* The extension depends on the SlicerRT general radiation therapy extension&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Use Cases}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
== Film dosimetry analysis workflow: ==&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:FilmDosimetryFlowchart.png|thumb|960px|Film dosimetry data flow diagram]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Screenshots ====&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:FilmDosimetry_1.0_Gamma.png|thumb|920px|Film dosimetry screenshot (gamma step)]]&lt;br /&gt;
&lt;br /&gt;
|[[File:FilmDosimetry_1.0_CalibrationFunction.png|thumb|400px|Pdd aligment curve screenshot]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:FilmDosimetry_1.0_Registration.png|thumb|400px|Calibration curve screenshot]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Tutorials}}&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_FilmDosimetryAnalysis.pptx Film dosimetry tutorial 2019]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Similar Extensions}}&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/GelDosimetry]]: GelDosimetry supports a real 3D dosimetry workflow&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/SlicerRT|SlicerRT]]: FilmDosimetry uses several modules from the SlicerRT extension&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|References}}&lt;br /&gt;
* Alexander, K. M., Robinson, A., Pinter, C., Fichtinger, G., Schreiner, L. J. (2016). Development of 3D Slicer based film dosimetry analysis. Journal of Physics: Conference Series, 847, 012061&lt;br /&gt;
** Please cite this when you refer to Film Dosimetry in your publication&lt;br /&gt;
* Pinter, C., et al. &amp;quot;Performing radiation therapy research using the open-source SlicerRT toolkit.&amp;quot; World Congress for Medical Physics and Biomedical Engineering, 2015&lt;br /&gt;
* C. Pinter, A. Lasso, A. Wang, D. Jaffray and G. Fichtinger, [http://perk.cs.queensu.ca/sites/perk.cs.queensu.ca/files/Pinter2012_0.pdf &amp;quot;SlicerRT – Radiation therapy research toolkit for 3D Slicer&amp;quot;], Med. Phys., 39(10) pp. 6332-6338, 2012&lt;br /&gt;
** Please cite the following paper when referring to SlicerRT in your publication&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@ARTICLE{Pinter2012,&lt;br /&gt;
  author = {Pinter, C. and Lasso, A. and Wang, A. and Jaffray, D. and Fichtinger, G.},&lt;br /&gt;
  title = {SlicerRT – Radiation therapy research toolkit for 3D Slicer},&lt;br /&gt;
  journal = {Med. Phys.},&lt;br /&gt;
  year = {2012},&lt;br /&gt;
  volume = {39},&lt;br /&gt;
  number = {10},&lt;br /&gt;
  pages = {6332-6338},&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Information for Developers}}&lt;br /&gt;
* Source code available on GitHub: https://github.com/SlicerRt/FilmDosimetryAnalysis&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61315</id>
		<title>Documentation/Nightly/Extensions/SlicerRT</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61315"/>
		<updated>2019-07-26T12:35:08Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
[[{{collaborator|logo|cco}}]] &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|canarie}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|ocairo}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|sparkit}}]]&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
Authors: &amp;lt;b&amp;gt;Csaba Pinter&amp;lt;/b&amp;gt; (PerkLab, Queen's University), &amp;lt;b&amp;gt;Andras Lasso&amp;lt;/b&amp;gt; (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contributors: &amp;lt;b&amp;gt;Greg Sharp&amp;lt;/b&amp;gt; (Massachusetts General Hospital), Kevin Wang (Princess Margaret Hospital, UHN Toronto), Steve Pieper (Isomics)&amp;lt;br&amp;gt;&lt;br /&gt;
Contacts:&lt;br /&gt;
* Csaba Pinter, &amp;lt;email&amp;gt;pinter.csaba@gmail.com&amp;lt;/email&amp;gt;&lt;br /&gt;
* Andras Lasso, &amp;lt;email&amp;gt;lasso@cs.queensu.ca&amp;lt;/email&amp;gt;&lt;br /&gt;
* [https://discourse.slicer.org Slicer Forum]&lt;br /&gt;
* [[Documentation/SlicerRT/HowToReportAnError|How to report an error]]&lt;br /&gt;
Website: [http://slicerrt.github.io slicerrt.org]&amp;lt;br&amp;gt;&lt;br /&gt;
License: [http://www.slicer.org/pages/LicenseText Slicer license]&amp;lt;br&amp;gt;&lt;br /&gt;
'''Download/install:''' install 3D Slicer, start 3D Slicer, open the Extension Manager, install the SlicerRT extension (see more details [http://slicerrt.github.io/Download.html on the download page])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; margin-left:12px;&amp;quot;&amp;gt;&lt;br /&gt;
importScript('http://www.ohloh.net/p/641228/widgets/project_basic_stats.js');&lt;br /&gt;
&amp;lt;wiki:gadget url=&amp;quot;http://www.ohloh.net/p/641228/widgets/project_search_code.xml&amp;quot; height=&amp;quot;195&amp;quot; border=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Extension Description}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
[[Image:SlicerRT_Logo_3.0_128x128.png]]&lt;br /&gt;
|&lt;br /&gt;
* SlicerRT is a radiation therapy toolkit for 3D Slicer, containing generic RT features for import/export, analysis, visualization, aiming to make 3D Slicer a powerful radiotherapy research platform. SlicerRT development is currently funded by CANARIE.&amp;lt;br&amp;gt;SlicerRT was originally created via funding by Cancer Care Ontario and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&lt;br /&gt;
&lt;br /&gt;
* The SlicerRT extension incorporates [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]] modules and algorithms.&lt;br /&gt;
&lt;br /&gt;
* Additional information for users can be found on the [[Documentation/SlicerRT/UsersGuide|User's Guide]] page &amp;lt;br&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Modules}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
*[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External Beam Planning]] (Treatment planning)&lt;br /&gt;
* Dose analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseVolumeHistogram|Dose volume histogram]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseAccumulation|Dose accumulation]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseComparison|Dose comparison]] (Gamma dose similarity index)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Isodose|Isodose line and surface display]]&lt;br /&gt;
* Contour analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentComparison|Segment comparison]] (Dice Similarity Coefficient, Hausdorff distances)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentMorphology|Segment morphology]] (Add/remove margin, Unify, Intersect, etc.)&lt;br /&gt;
* I/O&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DicomRtImport|DICOM-RT import]], [https://www.slicer.org/wiki/Documentation/Nightly/Modules/DICOM#DICOM_export export] (handles datasets of types RT Structure Set, RT Dose, RT Plan, RT Image)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DicomSroImport|DICOM-SRO import/export]] (handles DICOM Spatial Registration object, both rigid and deformable)&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing Batch processing scripts] (currently only one is available for command-line conversion of RTSS to volume nodes)&lt;br /&gt;
&lt;br /&gt;
* Modules from [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmBSplineDeformableRegistration|Plastimatch Automatic deformable image registration]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmLANDWARP|Plastimatch LANDWARP Landmark]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmSyntheticImageGeneration|Plastimatch Synthetic Image Generation]] (Greg Sharp)[[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Former SlicerRT modules integrated to Slicer core&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Data|Subject hierarchy]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Transforms|Transform visualizer]]&lt;br /&gt;
**DICOM-RT export, as [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/DICOMExport improved DICOM export function]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Segmentations|Segmentations]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentEditor|Segment Editor]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Experimental modules&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External beam planning]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
| [[File:SlicerRt_Montage.jpg|512px|SlicerRT highlights]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Use Cases}}&lt;br /&gt;
* Comparison of dose maps and dose volume histograms from various treatment planning systems&lt;br /&gt;
* Evaluation of the effect of different adaptive techniques (IGRT, image-based non-rigid patient motion compensation, etc.)&lt;br /&gt;
** Calculate couch shift parameters for patient setup correction in IGRT&lt;br /&gt;
* Dose accumulation with motion compensation&lt;br /&gt;
* Testing of treatment planning algorithms&lt;br /&gt;
* Calculation of PTV margin&lt;br /&gt;
* Proton dose calculation&lt;br /&gt;
* Gel dosimetry analysis&lt;br /&gt;
* Tumor volume tracking&lt;br /&gt;
* Treatment plan similarity measurement in the cloud&lt;br /&gt;
* Batch structure set conversion&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Tutorials}}&lt;br /&gt;
&lt;br /&gt;
=== Comprehensive tutorials ===&lt;br /&gt;
&lt;br /&gt;
* '''World Congress 2015 tutorial''' ''(recommended)''&lt;br /&gt;
** Tutorial presentation: [https://www.dropbox.com/s/b7qx3n10s52o5f8/SlicerRT_WorldCongress_TutorialIGRT.pptx?dl=0 pptx] [https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SlicerRT_WorldCongress_TutorialIGRT.pdf pdf]&lt;br /&gt;
** Dataset: [http://slicer.kitware.com/midas3/download/item/205391/WC2015_Gel_Slicelet_Dataset.zip download] from MIDAS&lt;br /&gt;
* '''Summer NA-MIC week 2013 tutorial'''&lt;br /&gt;
** Tutorial presentation: [http://wiki.na-mic.org/Wiki/images/b/b0/SlicerRT_TutorialContestSummer2013.pdf download] from Slicer wiki&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/download/folder/1345/SlicerRtTutorial_Namic2013June.zip download] from MIDAS&lt;br /&gt;
* '''ECR 2013 - Medical University Vienna workshop'''&lt;br /&gt;
** Workshop material: [http://www.na-mic.org/Wiki/index.php/File:Pinter_MedUni2013_Workshop.pdf download] from NA-MIC.org&lt;br /&gt;
* '''RSNA 2012 tutorial'''&lt;br /&gt;
** Tutorial description: [http://www.donotlink.com/bEo SlicerRT wiki: Slicer tutorials at RSNA 2012]&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/folder/859 download] SlicerRT ART dose verification data from Midas server&lt;br /&gt;
&lt;br /&gt;
=== Module tutorials ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_OrthovoltageDoseEngine.pptx External beam planning tutorial for orthovoltage RT] (uses EGSnrc)&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_DoseSurfaceHistogram.pptx Dose surface histogram tutorial]&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_Isodose.pptx Isodose tutorial]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Similar Extensions}}&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]: SlicerRT and Plastimatch are complementary software libraries. Plastimatch focuses on delivering new computational methods radiotherapy, while SlicerRT aims for providing an easy-to-use interface for a wide range of stable, well-tested radiotherapy related features. SlicerRT uses Plastimatch internally for certain operations.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/GelDosimetry|Gel Dosimetry]]: Slicelet facilitating a streamlined workflow to perform true 3D gel dosimetry analysis for commissioning linacs and evaluating new dose calculation procedures&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/FilmDosimetry|Film Dosimetry]]: Slicelet supporting workflow to perform 2D film dosimetry analysis for commissioning new radiation techniques and to validate the accuracy of radiation treatment by enabling visual comparison of the planned dose to the delivered dose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|References}}&lt;br /&gt;
==How to cite==&lt;br /&gt;
Please cite the following paper when referring to SlicerRt in your publication:&amp;lt;br&amp;gt;&lt;br /&gt;
C. Pinter, A. Lasso, A. Wang, D. Jaffray and G. Fichtinger, [http://perk.cs.queensu.ca/sites/perk.cs.queensu.ca/files/Pinter2012_0.pdf &amp;quot;SlicerRT – Radiation therapy research toolkit for 3D Slicer&amp;quot;], Med. Phys., 39(10) pp. 6332-6338, 2012&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@ARTICLE{Pinter2012,&lt;br /&gt;
  author = {Pinter, C. and Lasso, A. and Wang, A. and Jaffray, D. and Fichtinger, G.},&lt;br /&gt;
  title = {SlicerRT – Radiation therapy research toolkit for 3D Slicer},&lt;br /&gt;
  journal = {Med. Phys.},&lt;br /&gt;
  year = {2012},&lt;br /&gt;
  volume = {39},&lt;br /&gt;
  number = {10},&lt;br /&gt;
  pages = {6332-6338},&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Information for Developers}}&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/wiki/SlicerRt-developers-page SlicerRT developers wiki page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DICOM&amp;diff=61314</id>
		<title>Documentation/Nightly/Modules/DICOM</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DICOM&amp;diff=61314"/>
		<updated>2019-07-26T12:34:46Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* DICOM export */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
{{Clear|right}}{{TOC right}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
:'''Author(s)/Contributor(s):''' Steve Pieper (Isomics Inc.), Michael Onken (Offis), Marco Nolden (DFKZ), Julien Finet (Kitware), Stephen Aylward (Kitware), Nicholas Herlambang (AZE), Alireza Mehrtash (BWH), Csaba Pinter (PerkLab, Queen's)&amp;lt;br&amp;gt;&lt;br /&gt;
: '''Acknowledgements:''' This work is part of the [http://www.na-mic.org/ National Alliance for Medical Image Computing] (NA-MIC), funded by the National Institutes of Health through the NIH Roadmap for Medical Research, Grant U54 EB005149, and by Quantitative Image Informatics for Cancer Research (QIICR) (U24 CA180918) &amp;lt;br&amp;gt;&lt;br /&gt;
: '''Contact:''' Steve Pieper, &amp;lt;email&amp;gt;pieper@bwh.harvard.edu&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|isomics}}|{{collaborator|longname|isomics}}&lt;br /&gt;
|{{collaborator|logo|namic}}|{{collaborator|longname|namic}}&lt;br /&gt;
|{{collaborator|logo|nac}}|{{collaborator|longname|nac}}&lt;br /&gt;
|{{collaborator|logo|ctk}}|{{collaborator|longname|ctk}}&lt;br /&gt;
|{{collaborator|logo|qiicr}}|{{collaborator|longname|qiicr}}&lt;br /&gt;
|Image:DICOM-OFFIS-logo.png|DICOM-OFFIS&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-description}}&lt;br /&gt;
&lt;br /&gt;
DICOM is a widely used and sophisticated set of standards for digital radiology (see the [[#References|References]] section for more information). Slicer provides support for a subset of DICOM functionality, with the particular features driven by the needs of clinical research: '''loading''' and '''saving''' data sets from/to disk in DICOM format and '''sending''' and '''receiving''' data sets via DICOM networking.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
&lt;br /&gt;
=== Data import and loading ===&lt;br /&gt;
&lt;br /&gt;
Since DICOM files are often located in several folders, they can cross-reference each other, and can be often interpreted in different ways, importing and loading of DICOM files are performed as two separate steps:&lt;br /&gt;
- Import: User selects a folder that contains DICOM files. Slicer reads header of all files in a folder (and all its subfolders) and stores essential information in the Slicer DICOM database. Optionally Slicer can also make a full copy of the files into the database, which is useful if files are stored on a removable media (CD, DVD, USB drive). All indexed data gets listed in the DICOM browser.&lt;br /&gt;
- Loading: Items that user selected in the DICOM browser are loaded into the scene and displayed in viewers. In advanced mode, loading is performed in two steps: the application examines selected items and offers a list of loadable items that the user can choose from.&lt;br /&gt;
&lt;br /&gt;
==== Data import ====&lt;br /&gt;
&lt;br /&gt;
* Select folders that contain DICOM files&lt;br /&gt;
** Option A: Drag-and-drop the folder that contains DICOM files to the Slicer application window. Slicer displays a popup, asking what to do - click OK (&amp;quot;Load directory in DICOM database&amp;quot;). After import is completed, go to DICOM module.&lt;br /&gt;
** Option B: Go to DICOM module. Click &amp;quot;Import&amp;quot; button in the top-left corner of the DICOM browser. Select folder that contains DICOM files.&lt;br /&gt;
&lt;br /&gt;
Optionally select the Copy option so that the files are copied into the database directory.  Otherwise they will only be referenced in their original location. It is recommended to copy data if importing files from removable media (CD/DVD/USB drives) to be able to load the data set even after media is ejected.&lt;br /&gt;
&lt;br /&gt;
==== Data loading ====&lt;br /&gt;
&lt;br /&gt;
* Go to DICOM module. Click &amp;quot;Show DICOM browser&amp;quot; if the browser window is not visible (window title: &amp;quot;DICOM Browser&amp;quot;; it shows a list of patients, studies, and series).&lt;br /&gt;
* Select items to load. If an item in the patient or study list is selected then by default all series that belong to that item will be loaded.&lt;br /&gt;
* Click &amp;quot;Load&amp;quot; button to load selected items.&lt;br /&gt;
* Go to Data module to see what has been loaded and show/hide them.&lt;br /&gt;
&lt;br /&gt;
Advanced data loading: It is often possible to interpret DICOM data in different ways. If the application loaded data differently than expected then check &amp;quot;Advanced&amp;quot; checkbox, click &amp;quot;Examine&amp;quot; button, select all loadables in the list in the box at the bottom, and click &amp;quot;Load&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Some extensions make Slicer recognize more DICOM information object types. For example, SlicerRT extension makes it possible to load/export radiation therapy information objects (RT structure set, RT dose, RT image, RT plan). Make sure all relevant extensions are installed before attempting to load your data set.&lt;br /&gt;
&lt;br /&gt;
==== Deleting imported data ====&lt;br /&gt;
&lt;br /&gt;
By right clicking on a Patient, Study, or Series, you can delete the entry from the DICOM database.  Note that to avoid accidental data loss, Slicer does not delete the corresponding image data files.&lt;br /&gt;
&lt;br /&gt;
=== DICOM export ===&lt;br /&gt;
&lt;br /&gt;
Data in the scene can be exported to the DICOM database:&lt;br /&gt;
* Prepare DICOM study to export in Data module (subject hierarchy tab). Make sure you have the nodes in the study that you want to export.&lt;br /&gt;
** If you need to create a new patient, then right-click the empty space and choose Create new subject. Studies can be created under patients the same way.&lt;br /&gt;
* Right-click on a data set to export it to DICOM format (export can also be initiated from DICOM browser).&lt;br /&gt;
* Select the export modality in the bottom left of the export dialog.&lt;br /&gt;
* Edit tags for exportables. The metadata from the select study will be automatically filled in to the Export dialog and you can select a Slicer volume to export.&lt;br /&gt;
* Exported files are added to the DICOM database&lt;br /&gt;
&lt;br /&gt;
''Note that you should exercise extreme caution when working with these files in clinical situations, since non-standard or incorrect DICOM files can interfere with clinical operations.''&lt;br /&gt;
&lt;br /&gt;
You can also choose to encapsulate the current MRML scene (via an MRB file) inside a DICOM dataset, which will be treated as a DICOM secondary capture document. This secondary capture information stores all details of the scene but only 3D Slicer can interpret the data. This export feature has not been widely tested and should be considered experimental.&lt;br /&gt;
&lt;br /&gt;
=== Data networking ===&lt;br /&gt;
&lt;br /&gt;
DICOM is also a network communication standard. Slicer supports a DICOM Listener, DICOM Query/Retrieve interface, and a DICOM Send option.  Note that in order to use these features, you must coordinate with the operators of the other DICOM nodes with which you wish to communicate.  For example, you must work out agreement on such topics as network ports and application entity titles (AE Titles).  Be aware that not all equipment supports all networking options, so configuration may be challenging and is often difficult to troubleshoot.&lt;br /&gt;
&lt;br /&gt;
==== Connection Ports ====&lt;br /&gt;
&lt;br /&gt;
Port 104 is the standard DICOM port. All ports below 1024 require root access on unix-like systems (Linux and Mac).  So you can run Slicer with the sudo command to be able to open the port for the DICOM Listener.  Or you can use a different port, like 11112.  You need to configure that on both sides of the connection.  You can only have one process at a time listening on a port so if you have a listener running the second one won't start up.  Also if something adverse happens (a crash) the port may be kept open an you need to either kill the storescp helper process (or just reboot the computer) to free the port.  Consult the [[documentation/{{documentation/version}}/SlicerApplication/ErrorLog|Error Log]] for diagnostic information.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Screenshots}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[image:DICOM Screenshot-1 1204-11-17-10-36.png|thumb|380px|DICOM module in use]]&lt;br /&gt;
|[[Image:Form_224.png|thumb|380px|DICOM Query dialog]]&lt;br /&gt;
|[[Image:DICOM Horizontal View 2014-11-17-09-35.png|thumb|380px|Horizontal table view]]&lt;br /&gt;
|}&lt;br /&gt;
{|&lt;br /&gt;
|[[Image:DICOM-3 2014-11-17-10-42.png‎|thumb|380px|DICOM Browser in Advanced Mode (Control plugins and access to load options)]]&lt;br /&gt;
|[[Image:DICOM4 2014-11-17-09-38.png|thumb|380px|DICOM Meta Data Browser (DICOM header viewer)]]&lt;br /&gt;
|[[Image:DICOM-5 2014-11-17-10-46.png|thumb|380px|More options (change local database directory and table display density)]]&lt;br /&gt;
|}&lt;br /&gt;
{|&lt;br /&gt;
|[[Image:20141103_DICOM_Export_Dialog.png|thumb|380px|DICOM Export Dialog]]&lt;br /&gt;
|[[Image:DICOM-Preferences.png|thumb|380px|DICOM Preferences]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Tutorials ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
* See [http://www.na-mic.org/Wiki/index.php/RSNA_2012#3D_Interactive_Visualization_of_DICOM_images the RSNA 2012 Training on Visualization] for description and sample data (Direct link to [http://www.na-mic.org/Wiki/images/6/66/3DVisualizationDICOM_RadiologyApplications_SoniaPujol_RSNA2012.pdf slides as pdf]).&lt;br /&gt;
* [https://pieper.github.io/content/handson/#/DICOM This screen capture animation] shows how to import and load DICOM data (also includes inspection of the file contents, which is an optional step).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Panels ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels}}&lt;br /&gt;
&lt;br /&gt;
==DICOM import==&lt;br /&gt;
&lt;br /&gt;
Referring to the &amp;quot;DICOM in use&amp;quot; image in the top left of this page, the most important controls for day-to-day use are highlighted with gray callouts.  The are described here in the order you are likely to use them.&lt;br /&gt;
&lt;br /&gt;
*'''LocalDatabase''' (appears when ''&amp;gt;&amp;gt;'' button next to the menu bar is clicked): allows you to select a location on disk for Slicer's database of DICOM files. The application manages content of this folder (stores metadata and copy of imported DICOM files): do not manually copy any data into this folder.&lt;br /&gt;
*'''Import''' all DICOM files in the selected folder (including subfolders) will be parsed and basic information from file headers will be stored in Slicer's DICOM database. If enabled, then Slicer will make a copy of the imported files into the database folder.&lt;br /&gt;
*'''Patient list''' shows patients in the database. Studies available for the selected patient(s) are listed in study list. Multiple patients can be selected.&lt;br /&gt;
*'''Study list''': shows studies for the currently selected patient(s).  Multiple studies can be selected.&lt;br /&gt;
*'''Series list''' shows list of series (images, structure sets, segmentations, registration objects, etc.) available for selected studies.&lt;br /&gt;
*'''Search boxes''' Each patient/study/series can be filtered by typing in these fields.&lt;br /&gt;
*'''Examine button''' Runs each of the DICOM Plugins on the currently selected series and offers the result in the Load Options table.&lt;br /&gt;
*'''Plugin options''' (appears when ''Advanced'' checkbox is checked): you can choose which plugins will be allowed to examine the selected series for loading.&lt;br /&gt;
*'''Loadables list''' displays all possible interpretations of the selected series by the selected plugins.  The plugin that most likely interprets the series correctly, is selected by default.  You can override the defaults if you want to load the data in a different way. There will not always be a one-to-one mapping of selected series to list of loadable items.&lt;br /&gt;
*'''Load''' click this to load currently selected loadables into slicer.&lt;br /&gt;
*'''Metadata''' click this button to see metadata stored in file headers of selected series.&lt;br /&gt;
&lt;br /&gt;
==DICOM export==&lt;br /&gt;
&lt;br /&gt;
===How to export data from the Slicer scene to DICOM files===&lt;br /&gt;
* Open Data module, go to Subject Hierarchy tab (it is the tab shown by default)&lt;br /&gt;
* Make sure the data nodes that you want to export are in a DICOM-compliant hierarchy: parent of the data node is a Study, parent of the study is a Subject. To create a hierarchy, right-click in an empty area of the tree, select &amp;quot;Create new subject&amp;quot;, then right-click on the newly created subject and select &amp;quot;Create child study&amp;quot;, then drag-and-drop your data nodes under this study.&lt;br /&gt;
* Right-click on the data node to be exported and click &amp;quot;Export to DICOM...&amp;quot; to display DICOM export window (you can also show it by clicking &amp;quot;Export&amp;quot; button in the toolbar of DICOM browser module)&lt;br /&gt;
* Choose Output folder: By default, files are written into the folder where Slicer DICOM database is located. &lt;br /&gt;
* Click Export button: Export may take a few minutes. In case of error, the message is displayed in red on the left side of the dialog in the line of the &amp;quot;Save tags on export&amp;quot; checkbox.&lt;br /&gt;
&lt;br /&gt;
This workflow is also explained in a 2-minute [https://youtu.be/nzWf4xHy1BM video tutorial]&lt;br /&gt;
&lt;br /&gt;
===Advanced options===&lt;br /&gt;
* DICOM export window can be also opened from the DICOM browser, by clicking &amp;quot;Export&amp;quot; button in the toolbar&lt;br /&gt;
* Export mode:&lt;br /&gt;
** Export series: export one or more selected series, to be viewed on a standard DICOM-compliant viewer&lt;br /&gt;
** Export entire scene: save the entire Slicer scene into a DICOM secondary capture file; the content can be stored on a DICOM archival system but can only be edited in Slicer&lt;br /&gt;
* Export type: Once the user selected a node, the DICOM plugins generate exportables for the series they can export. The list of the results appear in this section, grouped by plugin. The confidence number will be the average of the confidence numbers for the individual series for that plugin.&lt;br /&gt;
* Editing DICOM tags:&lt;br /&gt;
** DICOM tag editor consists of a list of tables. Tables for the common tags for the patient and study on the top, and the tags for the individual series below them (see image about tag editor below)&lt;br /&gt;
** &amp;quot;Tags&amp;quot; in the displayed table are not written directly to DICOM tags, they are just used by the DICOM plugins to fill DICOM tags in the exported files. This allows much more flexibility and DICOM plugins can auto-populate some information and plugins can expose other export options in this list (e.g. compression, naming convention).&lt;br /&gt;
** Save tags to scene: Checkbox to allow saving the tags back to the MRML nodes as attributes.&lt;br /&gt;
* Import exported data: if checked, the exported files are added to Slicer's DICOM database.&lt;br /&gt;
* The Edit-&amp;gt;Preferences-&amp;gt;DICOM page can be used to select options&lt;br /&gt;
** Generic&lt;br /&gt;
*** Load referenced series will give you the option of easily loading, for example, the master volume of a segmentation when you open the segmentation.  This can also be made to happen automatically.&lt;br /&gt;
** Scalar Volume&lt;br /&gt;
*** You can choose what back-end library to use (currently GDCM, DCMTK, or GDCM with DCMTK fallback with the last option being the default.  This is provided in case some data is unsupported by one library or the other.&lt;br /&gt;
*** Acquisition geometry regularization option supports the creation of a nonlinear transform that corrects for things like missing slices or gantry tilt in the acquisition&lt;br /&gt;
*** Autoloading subseries by time is an option break up some 4D acquisitions into individual volume, but is optional since some volumes are also acquired in time unites and should not be split.&lt;br /&gt;
&lt;br /&gt;
=Slicer DICOM Database=&lt;br /&gt;
&lt;br /&gt;
To organize the data and avoid redundant calculations, Slicer keeps a DICOM Database of information about the DICOM data.  You can have multiple databases on your computer at a time, and switch between them if, for example, they include data from different research projects.  Each database is simply a directory on your local disk that has a few [http://sqlite.org/ SQLite] files and subdirectories to store image data.  Don't manually modify the contents of these directories.  DICOM data can enter the database either through manual import or via a DICOM network transfer.  Modules may also populate the DICOM database with the results of computation.&lt;br /&gt;
&lt;br /&gt;
You can change location where the database is stored by opening the DICOM module, clicking the double arrow (&amp;gt;&amp;gt;) button on the right side of the menu bar, click the button next to &amp;quot;LocalDatabase&amp;quot; label, and select the new location (an empty folder).&lt;br /&gt;
&lt;br /&gt;
Note that the DICOM standard does not specify how files will be organized on disk, so if you have DICOM data from a CDROM or otherwise transferred from a scanner, you cannot in general tell anything about the contents from the file or directory names.  However once the data is imported to the database, it will be organized according the the DICOM standard Patient/Study/Series hierarchy.&lt;br /&gt;
&lt;br /&gt;
=DICOM Loading/Saving and Plugins=&lt;br /&gt;
&lt;br /&gt;
A main function of the DICOM module is to map from ''acquisition'' data organization into ''volume'' representation.  That is, DICOM files typically describe attributes of the image capture, like the sequence of locations of the table during CT acquisition, while Slicer operates on image volumes of regularly spaced pixels.  If, for example, the speed of the table motion is not consistent during an acquisition (which can be the case for some contrast 'bolus chasing' scans, Slicer's DICOM module will warn the user that the acquisition geometry is not consistent and the user should use caution when interpreting analysis results such as measurements. &lt;br /&gt;
&lt;br /&gt;
From a developer perspective, the DICOM module exposes a plug-in architecture that allows acquisition-specific and modality-specific interpretation of DICOM data.  From a user perspective this means that often Slicer will be able to suggest multiple ways of interpreting the data (such as reading DICOM files as a [[Documentation/{{documentation/version}}#Diffusion|Diffusion]] dataset or as a scalar volume.  When it is computable by examining the files, the DICOM module will select the most likely interpretation option by default.  As of this release, standard plugins include scalar volumes and diffusion volumes, while extensions are available for segmentation objects, RT data, and PET/CT data.  More plugins are expected for future versions.  It is a long-term objective to be able to represent most, if not all, of Slicer's data in the corresponding DICOM data objects as the standard evolves to support them.&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
&lt;br /&gt;
See the [[Documentation/{{documentation/version}}/FAQ/DICOM|Slicer DICOM FAQ]] for troubleshooting tips.&lt;br /&gt;
&lt;br /&gt;
==How to obtain DICOM metadata==&lt;br /&gt;
&lt;br /&gt;
* Open DICOM browser&lt;br /&gt;
* Select the data set that you want to load by clicking on a series (item in the listbox in the bottom)&lt;br /&gt;
* Click Metadata button&lt;br /&gt;
* Click Copy Metadata button&lt;br /&gt;
* Paste the copied text to any text editor&lt;br /&gt;
* '''Remove patient name, birthdate, ID, and all other patient identifiable information'''&lt;br /&gt;
* Copy-paste remaining text to Slicer forum post or email&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Similar modules ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar modules}}&lt;br /&gt;
* [[Documentation/{{documentation/version}}/SlicerApplication/LoadingData|Loading Data]] Can read scalar volume DICOM data, bypassing the database.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|Reporting Extension]] reads and writes DICOM Segmentation Objects (label maps).&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|SlicerRT]] reads and write DICOM Radiation Therapy Objects and provides tools for processing them.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|LongitudinalPETCT]] reads all PET/CT studies for a selected patient and provides tools for tracking metabolic activity detected by PET tracers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- References ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
See the [http://commontk.org CTK web site] for more information on the internals of the DICOM implementation.  This tool uses the [http://dicom.offis.de DCMTK DICOM library].&lt;br /&gt;
&lt;br /&gt;
=== Useful links ===&lt;br /&gt;
* The DICOM Homepage: http://dicom.nema.org/&lt;br /&gt;
* DICOM on wikipedia: http://en.wikipedia.org/wiki/DICOM&lt;br /&gt;
* Clean and simple DICOM tag browser: http://dicom.innolitics.com&lt;br /&gt;
* A useful tag lookup site: http://dicomlookup.com/&lt;br /&gt;
* A hyperlinked version of the standard: http://dabsoft.ch/dicom/&lt;br /&gt;
* A handy book about DICOM: http://www.amazon.com/Digital-Imaging-Communications-Medicine-DICOM/dp/3642108490/ref=dp_ob_title_bk&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
&lt;br /&gt;
[[Image:DICOM-architecture.png|thumb|580px|DICOM module architecture.]]&lt;br /&gt;
&lt;br /&gt;
The overall DICOM Implementation in 3D Slicer consists of two main bodies of code embedded within the application.  [http://commontk.org CTK] code is responsible for the implementation of the DICOM database and networking layer.  The CTK code is implemented C++ and follows the Qt style.  The DICOM Module exposes this functionality to slicer users, and provides hooks through which other module can register DICOM Plugins to handle the conversion of specific DICOM data objects into the corresponding MRML representation.  Once the data is in slicer, it can be operated on via the standard slicer mechanisms.&lt;br /&gt;
&lt;br /&gt;
==== Customize table columns in DICOM browser ====&lt;br /&gt;
&lt;br /&gt;
Columns in the browser can be renamed, reordered, shown/hidden, etc. An example snippet to customize the browser can be found in the [https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Customize_table_columns_in_DICOM_browser script repository]&lt;br /&gt;
&lt;br /&gt;
The changes made like this are written into the database (ColumnDisplayProperties table), so the column customizations can be done only once per database.&lt;br /&gt;
&lt;br /&gt;
==== Customize DICOM browser table content ====&lt;br /&gt;
&lt;br /&gt;
The way the raw DICOM tags are represented in the fields of the DICOM tables is determined by the displayed field generator rules. These rules are subclasses of the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/master/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h ctkDICOMDisplayedFieldGeneratorAbstractRule class], and need to be [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/master/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.h#L70 registered] to the displayed field generator in order to take part of the generation.&lt;br /&gt;
&lt;br /&gt;
The fields are [https://github.com/commontk/CTK/9c2af28e84da1abb986036317d75009d4c149923/blob/master/Libs/DICOM/Core/ctkDICOMDatabase.h#L207 updated] when 1) files are added to the database or 2) the database schema is updated (happens when opening an older database with a newer Slicer). In the [https://github.com/commontk/CTK/tree/9c2af28e84da1abb986036317d75009d4c149923 current] version only those files (i.e. instances) are processed for which the displayed fields have never been generated.&lt;br /&gt;
&lt;br /&gt;
When updating the displayed fields, every rule defines the fields it is responsible for using the cached DICOM tags in the database. Tags can be requested to be cached in the rules from the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h#L63 getRequiredDICOMTags] function. New field values are generated by the rules instance by instance. First, the getDisplayedFieldsForInstance function is called for each rule in which the custom values are generated from the raw tags, then the results are merged by calling mergeDisplayedFieldsForInstance for all the rules. Each field can be requested to be merged with &amp;quot;expect same value&amp;quot;, which uses the only non-empty value and throws a warning if conflicting values are encountered, or with &amp;quot;concatenate&amp;quot;, which simply concatenates the displayed field values together.&lt;br /&gt;
&lt;br /&gt;
The existing two rules can be used as examples: the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.cpp default] and the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.cpp RT] rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61312</id>
		<title>Documentation/Nightly/Extensions/SlicerRT</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61312"/>
		<updated>2019-07-25T16:10:31Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add SRO and info for I/O&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
[[{{collaborator|logo|cco}}]] &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|canarie}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|ocairo}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|sparkit}}]]&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
Authors: &amp;lt;b&amp;gt;Csaba Pinter&amp;lt;/b&amp;gt; (PerkLab, Queen's University), &amp;lt;b&amp;gt;Andras Lasso&amp;lt;/b&amp;gt; (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contributors: &amp;lt;b&amp;gt;Greg Sharp&amp;lt;/b&amp;gt; (Massachusetts General Hospital), Kevin Wang (Princess Margaret Hospital, UHN Toronto), Steve Pieper (Isomics)&amp;lt;br&amp;gt;&lt;br /&gt;
Contacts:&lt;br /&gt;
* Csaba Pinter, &amp;lt;email&amp;gt;pinter.csaba@gmail.com&amp;lt;/email&amp;gt;&lt;br /&gt;
* Andras Lasso, &amp;lt;email&amp;gt;lasso@cs.queensu.ca&amp;lt;/email&amp;gt;&lt;br /&gt;
* [https://discourse.slicer.org Slicer Forum]&lt;br /&gt;
* [[Documentation/SlicerRT/HowToReportAnError|How to report an error]]&lt;br /&gt;
Website: [http://slicerrt.github.io slicerrt.org]&amp;lt;br&amp;gt;&lt;br /&gt;
License: [http://www.slicer.org/pages/LicenseText Slicer license]&amp;lt;br&amp;gt;&lt;br /&gt;
'''Download/install:''' install 3D Slicer, start 3D Slicer, open the Extension Manager, install the SlicerRT extension (see more details [http://slicerrt.github.io/Download.html on the download page])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; margin-left:12px;&amp;quot;&amp;gt;&lt;br /&gt;
importScript('http://www.ohloh.net/p/641228/widgets/project_basic_stats.js');&lt;br /&gt;
&amp;lt;wiki:gadget url=&amp;quot;http://www.ohloh.net/p/641228/widgets/project_search_code.xml&amp;quot; height=&amp;quot;195&amp;quot; border=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Extension Description}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
[[Image:SlicerRT_Logo_3.0_128x128.png]]&lt;br /&gt;
|&lt;br /&gt;
* SlicerRT is a radiation therapy toolkit for 3D Slicer, containing generic RT features for import/export, analysis, visualization, aiming to make 3D Slicer a powerful radiotherapy research platform. SlicerRT development is currently funded by CANARIE.&amp;lt;br&amp;gt;SlicerRT was originally created via funding by Cancer Care Ontario and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&lt;br /&gt;
&lt;br /&gt;
* The SlicerRT extension incorporates [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]] modules and algorithms.&lt;br /&gt;
&lt;br /&gt;
* Additional information for users can be found on the [[Documentation/SlicerRT/UsersGuide|User's Guide]] page &amp;lt;br&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Modules}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
*[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External Beam Planning]] (Treatment planning)&lt;br /&gt;
* Dose analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseVolumeHistogram|Dose volume histogram]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseAccumulation|Dose accumulation]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseComparison|Dose comparison]] (Gamma dose similarity index)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Isodose|Isodose line and surface display]]&lt;br /&gt;
* Contour analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentComparison|Segment comparison]] (Dice Similarity Coefficient, Hausdorff distances)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentMorphology|Segment morphology]] (Add/remove margin, Unify, Intersect, etc.)&lt;br /&gt;
* I/O&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DicomRtImport|DICOM-RT import]], [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/DICOMExport export] (handles datasets of types RT Structure Set, RT Dose, RT Plan, RT Image)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DicomSroImport|DICOM-SRO import/export]] (handles DICOM Spatial Registration object, both rigid and deformable)&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing Batch processing scripts] (currently only one is available for command-line conversion of RTSS to volume nodes)&lt;br /&gt;
&lt;br /&gt;
* Modules from [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmBSplineDeformableRegistration|Plastimatch Automatic deformable image registration]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmLANDWARP|Plastimatch LANDWARP Landmark]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmSyntheticImageGeneration|Plastimatch Synthetic Image Generation]] (Greg Sharp)[[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Former SlicerRT modules integrated to Slicer core&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Data|Subject hierarchy]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Transforms|Transform visualizer]]&lt;br /&gt;
**DICOM-RT export, as [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/DICOMExport improved DICOM export function]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Segmentations|Segmentations]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentEditor|Segment Editor]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Experimental modules&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External beam planning]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
| [[File:SlicerRt_Montage.jpg|512px|SlicerRT highlights]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Use Cases}}&lt;br /&gt;
* Comparison of dose maps and dose volume histograms from various treatment planning systems&lt;br /&gt;
* Evaluation of the effect of different adaptive techniques (IGRT, image-based non-rigid patient motion compensation, etc.)&lt;br /&gt;
** Calculate couch shift parameters for patient setup correction in IGRT&lt;br /&gt;
* Dose accumulation with motion compensation&lt;br /&gt;
* Testing of treatment planning algorithms&lt;br /&gt;
* Calculation of PTV margin&lt;br /&gt;
* Proton dose calculation&lt;br /&gt;
* Gel dosimetry analysis&lt;br /&gt;
* Tumor volume tracking&lt;br /&gt;
* Treatment plan similarity measurement in the cloud&lt;br /&gt;
* Batch structure set conversion&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Tutorials}}&lt;br /&gt;
&lt;br /&gt;
=== Comprehensive tutorials ===&lt;br /&gt;
&lt;br /&gt;
* '''World Congress 2015 tutorial''' ''(recommended)''&lt;br /&gt;
** Tutorial presentation: [https://www.dropbox.com/s/b7qx3n10s52o5f8/SlicerRT_WorldCongress_TutorialIGRT.pptx?dl=0 pptx] [https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SlicerRT_WorldCongress_TutorialIGRT.pdf pdf]&lt;br /&gt;
** Dataset: [http://slicer.kitware.com/midas3/download/item/205391/WC2015_Gel_Slicelet_Dataset.zip download] from MIDAS&lt;br /&gt;
* '''Summer NA-MIC week 2013 tutorial'''&lt;br /&gt;
** Tutorial presentation: [http://wiki.na-mic.org/Wiki/images/b/b0/SlicerRT_TutorialContestSummer2013.pdf download] from Slicer wiki&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/download/folder/1345/SlicerRtTutorial_Namic2013June.zip download] from MIDAS&lt;br /&gt;
* '''ECR 2013 - Medical University Vienna workshop'''&lt;br /&gt;
** Workshop material: [http://www.na-mic.org/Wiki/index.php/File:Pinter_MedUni2013_Workshop.pdf download] from NA-MIC.org&lt;br /&gt;
* '''RSNA 2012 tutorial'''&lt;br /&gt;
** Tutorial description: [http://www.donotlink.com/bEo SlicerRT wiki: Slicer tutorials at RSNA 2012]&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/folder/859 download] SlicerRT ART dose verification data from Midas server&lt;br /&gt;
&lt;br /&gt;
=== Module tutorials ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_OrthovoltageDoseEngine.pptx External beam planning tutorial for orthovoltage RT] (uses EGSnrc)&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_DoseSurfaceHistogram.pptx Dose surface histogram tutorial]&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_Isodose.pptx Isodose tutorial]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Similar Extensions}}&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]: SlicerRT and Plastimatch are complementary software libraries. Plastimatch focuses on delivering new computational methods radiotherapy, while SlicerRT aims for providing an easy-to-use interface for a wide range of stable, well-tested radiotherapy related features. SlicerRT uses Plastimatch internally for certain operations.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/GelDosimetry|Gel Dosimetry]]: Slicelet facilitating a streamlined workflow to perform true 3D gel dosimetry analysis for commissioning linacs and evaluating new dose calculation procedures&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/FilmDosimetry|Film Dosimetry]]: Slicelet supporting workflow to perform 2D film dosimetry analysis for commissioning new radiation techniques and to validate the accuracy of radiation treatment by enabling visual comparison of the planned dose to the delivered dose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|References}}&lt;br /&gt;
==How to cite==&lt;br /&gt;
Please cite the following paper when referring to SlicerRt in your publication:&amp;lt;br&amp;gt;&lt;br /&gt;
C. Pinter, A. Lasso, A. Wang, D. Jaffray and G. Fichtinger, [http://perk.cs.queensu.ca/sites/perk.cs.queensu.ca/files/Pinter2012_0.pdf &amp;quot;SlicerRT – Radiation therapy research toolkit for 3D Slicer&amp;quot;], Med. Phys., 39(10) pp. 6332-6338, 2012&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@ARTICLE{Pinter2012,&lt;br /&gt;
  author = {Pinter, C. and Lasso, A. and Wang, A. and Jaffray, D. and Fichtinger, G.},&lt;br /&gt;
  title = {SlicerRT – Radiation therapy research toolkit for 3D Slicer},&lt;br /&gt;
  journal = {Med. Phys.},&lt;br /&gt;
  year = {2012},&lt;br /&gt;
  volume = {39},&lt;br /&gt;
  number = {10},&lt;br /&gt;
  pages = {6332-6338},&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Information for Developers}}&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/wiki/SlicerRt-developers-page SlicerRT developers wiki page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61309</id>
		<title>Documentation/Nightly/Extensions/SlicerRT</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61309"/>
		<updated>2019-07-24T12:32:25Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add tutorials&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
[[{{collaborator|logo|cco}}]] &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|canarie}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|ocairo}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|sparkit}}]]&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
Authors: &amp;lt;b&amp;gt;Csaba Pinter&amp;lt;/b&amp;gt; (PerkLab, Queen's University), &amp;lt;b&amp;gt;Andras Lasso&amp;lt;/b&amp;gt; (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contributors: &amp;lt;b&amp;gt;Greg Sharp&amp;lt;/b&amp;gt; (Massachusetts General Hospital), Kevin Wang (Princess Margaret Hospital, UHN Toronto), Steve Pieper (Isomics)&amp;lt;br&amp;gt;&lt;br /&gt;
Contacts:&lt;br /&gt;
* Csaba Pinter, &amp;lt;email&amp;gt;pinter.csaba@gmail.com&amp;lt;/email&amp;gt;&lt;br /&gt;
* Andras Lasso, &amp;lt;email&amp;gt;lasso@cs.queensu.ca&amp;lt;/email&amp;gt;&lt;br /&gt;
* [https://discourse.slicer.org Slicer Forum]&lt;br /&gt;
* [[Documentation/SlicerRT/HowToReportAnError|How to report an error]]&lt;br /&gt;
Website: [http://slicerrt.github.io slicerrt.org]&amp;lt;br&amp;gt;&lt;br /&gt;
License: [http://www.slicer.org/pages/LicenseText Slicer license]&amp;lt;br&amp;gt;&lt;br /&gt;
'''Download/install:''' install 3D Slicer, start 3D Slicer, open the Extension Manager, install the SlicerRT extension (see more details [http://slicerrt.github.io/Download.html on the download page])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; margin-left:12px;&amp;quot;&amp;gt;&lt;br /&gt;
importScript('http://www.ohloh.net/p/641228/widgets/project_basic_stats.js');&lt;br /&gt;
&amp;lt;wiki:gadget url=&amp;quot;http://www.ohloh.net/p/641228/widgets/project_search_code.xml&amp;quot; height=&amp;quot;195&amp;quot; border=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Extension Description}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
[[Image:SlicerRT_Logo_3.0_128x128.png]]&lt;br /&gt;
|&lt;br /&gt;
* SlicerRT is a radiation therapy toolkit for 3D Slicer, containing generic RT features for import/export, analysis, visualization, aiming to make 3D Slicer a powerful radiotherapy research platform. SlicerRT development is currently funded by CANARIE.&amp;lt;br&amp;gt;SlicerRT was originally created via funding by Cancer Care Ontario and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&lt;br /&gt;
&lt;br /&gt;
* The SlicerRT extension incorporates [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]] modules and algorithms.&lt;br /&gt;
&lt;br /&gt;
* Additional information for users can be found on the [[Documentation/SlicerRT/UsersGuide|User's Guide]] page &amp;lt;br&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Modules}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
*[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External Beam Planning]] (Treatment planning)&lt;br /&gt;
* Dose analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseVolumeHistogram|Dose volume histogram]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseAccumulation|Dose accumulation]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseComparison|Dose comparison]] (Gamma dose similarity index)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Isodose|Isodose line and surface display]]&lt;br /&gt;
* Contour analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentComparison|Segment comparison]] (Dice Similarity Coefficient, Hausdorff distances)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentMorphology|Segment morphology]] (Add/remove margin, Unify, Intersect, etc.)&lt;br /&gt;
* I/O&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DicomRtImport|DICOM-RT import]], [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/DICOMExport export]&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing Batch processing scripts] (currently only one is available for command-line conversion of RTSS to volume nodes)&lt;br /&gt;
&lt;br /&gt;
* Modules from [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmBSplineDeformableRegistration|Plastimatch Automatic deformable image registration]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmLANDWARP|Plastimatch LANDWARP Landmark]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmSyntheticImageGeneration|Plastimatch Synthetic Image Generation]] (Greg Sharp)[[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Former SlicerRT modules integrated to Slicer core&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Data|Subject hierarchy]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Transforms|Transform visualizer]]&lt;br /&gt;
**DICOM-RT export, as [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/DICOMExport improved DICOM export function]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Segmentations|Segmentations]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentEditor|Segment Editor]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Experimental modules&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External beam planning]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
| [[File:SlicerRt_Montage.jpg|512px|SlicerRT highlights]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Use Cases}}&lt;br /&gt;
* Comparison of dose maps and dose volume histograms from various treatment planning systems&lt;br /&gt;
* Evaluation of the effect of different adaptive techniques (IGRT, image-based non-rigid patient motion compensation, etc.)&lt;br /&gt;
** Calculate couch shift parameters for patient setup correction in IGRT&lt;br /&gt;
* Dose accumulation with motion compensation&lt;br /&gt;
* Testing of treatment planning algorithms&lt;br /&gt;
* Calculation of PTV margin&lt;br /&gt;
* Proton dose calculation&lt;br /&gt;
* Gel dosimetry analysis&lt;br /&gt;
* Tumor volume tracking&lt;br /&gt;
* Treatment plan similarity measurement in the cloud&lt;br /&gt;
* Batch structure set conversion&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Tutorials}}&lt;br /&gt;
&lt;br /&gt;
=== Comprehensive tutorials ===&lt;br /&gt;
&lt;br /&gt;
* '''World Congress 2015 tutorial''' ''(recommended)''&lt;br /&gt;
** Tutorial presentation: [https://www.dropbox.com/s/b7qx3n10s52o5f8/SlicerRT_WorldCongress_TutorialIGRT.pptx?dl=0 pptx] [https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SlicerRT_WorldCongress_TutorialIGRT.pdf pdf]&lt;br /&gt;
** Dataset: [http://slicer.kitware.com/midas3/download/item/205391/WC2015_Gel_Slicelet_Dataset.zip download] from MIDAS&lt;br /&gt;
* '''Summer NA-MIC week 2013 tutorial'''&lt;br /&gt;
** Tutorial presentation: [http://wiki.na-mic.org/Wiki/images/b/b0/SlicerRT_TutorialContestSummer2013.pdf download] from Slicer wiki&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/download/folder/1345/SlicerRtTutorial_Namic2013June.zip download] from MIDAS&lt;br /&gt;
* '''ECR 2013 - Medical University Vienna workshop'''&lt;br /&gt;
** Workshop material: [http://www.na-mic.org/Wiki/index.php/File:Pinter_MedUni2013_Workshop.pdf download] from NA-MIC.org&lt;br /&gt;
* '''RSNA 2012 tutorial'''&lt;br /&gt;
** Tutorial description: [http://www.donotlink.com/bEo SlicerRT wiki: Slicer tutorials at RSNA 2012]&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/folder/859 download] SlicerRT ART dose verification data from Midas server&lt;br /&gt;
&lt;br /&gt;
=== Module tutorials ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_OrthovoltageDoseEngine.pptx External beam planning tutorial for orthovoltage RT] (uses EGSnrc)&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_DoseSurfaceHistogram.pptx Dose surface histogram tutorial]&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_Isodose.pptx Isodose tutorial]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Similar Extensions}}&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]: SlicerRT and Plastimatch are complementary software libraries. Plastimatch focuses on delivering new computational methods radiotherapy, while SlicerRT aims for providing an easy-to-use interface for a wide range of stable, well-tested radiotherapy related features. SlicerRT uses Plastimatch internally for certain operations.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/GelDosimetry|Gel Dosimetry]]: Slicelet facilitating a streamlined workflow to perform true 3D gel dosimetry analysis for commissioning linacs and evaluating new dose calculation procedures&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/FilmDosimetry|Film Dosimetry]]: Slicelet supporting workflow to perform 2D film dosimetry analysis for commissioning new radiation techniques and to validate the accuracy of radiation treatment by enabling visual comparison of the planned dose to the delivered dose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|References}}&lt;br /&gt;
==How to cite==&lt;br /&gt;
Please cite the following paper when referring to SlicerRt in your publication:&amp;lt;br&amp;gt;&lt;br /&gt;
C. Pinter, A. Lasso, A. Wang, D. Jaffray and G. Fichtinger, [http://perk.cs.queensu.ca/sites/perk.cs.queensu.ca/files/Pinter2012_0.pdf &amp;quot;SlicerRT – Radiation therapy research toolkit for 3D Slicer&amp;quot;], Med. Phys., 39(10) pp. 6332-6338, 2012&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@ARTICLE{Pinter2012,&lt;br /&gt;
  author = {Pinter, C. and Lasso, A. and Wang, A. and Jaffray, D. and Fichtinger, G.},&lt;br /&gt;
  title = {SlicerRT – Radiation therapy research toolkit for 3D Slicer},&lt;br /&gt;
  journal = {Med. Phys.},&lt;br /&gt;
  year = {2012},&lt;br /&gt;
  volume = {39},&lt;br /&gt;
  number = {10},&lt;br /&gt;
  pages = {6332-6338},&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Information for Developers}}&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/wiki/SlicerRt-developers-page SlicerRT developers wiki page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/Isodose&amp;diff=61308</id>
		<title>Documentation/Nightly/Modules/Isodose</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/Isodose&amp;diff=61308"/>
		<updated>2019-07-24T12:29:41Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add tutorial&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
This work is part of the SparKit project, funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health and Long-Term Care and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&amp;lt;br&amp;gt;&lt;br /&gt;
Author: Kevin Wang (Princess Margaret Cancer Centre)&amp;lt;br&amp;gt;&lt;br /&gt;
Contact: Kevin Wang, &amp;lt;email&amp;gt;kevin.wang@rmp.uhn.on.ca&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT Back to SlicerRT home]&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
|{{collaborator|logo|sparkit}}|{{collaborator|longname|sparkit}}&lt;br /&gt;
|{{collaborator|logo|ocairo}}|{{collaborator|longname|ocairo}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
The {{documentation/modulename}} module creates isosurfaces from an input dose volume and a series of defined isodose levels. The output is a series of surface models grouped under a hierarchy node parent that can be visualized either in the 3D viewer or overlaid on image slices.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
Generate isodose lines and surfaces for a dose distribution&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:SlicerRT_IsodoseModuleUi.png|thumb|407px|Isodose module UI]]&lt;br /&gt;
|[[File:SlicerRT0.6_Isodose.png|thumb|720px|Isodose views]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
* See workflow tutorials involving DVH on the [http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT#Tutorials SlicerRT main page]&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_Isodose.pptx Isodose tutorial]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
* '''Input'''&lt;br /&gt;
** Dose volume&lt;br /&gt;
** Number of Iso levels&lt;br /&gt;
** '''Iso levels table:''' Color, Label and Opacity can be set to the isodose surfaces individually&lt;br /&gt;
** '''Apply:''' Create isodose surfaces&lt;br /&gt;
* '''Display options'''&lt;br /&gt;
** '''Show isodose lines:''' Show/hide isodose lines in 2D slice viewers&lt;br /&gt;
** '''Show isodose surfaces:''' Show/hide isodose surfaces in the 3D view&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{documentation/{{documentation/version}}/module-parametersdescription}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
N/A&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
N/A&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
N/A&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DoseVolumeHistogram&amp;diff=61307</id>
		<title>Documentation/Nightly/Modules/DoseVolumeHistogram</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DoseVolumeHistogram&amp;diff=61307"/>
		<updated>2019-07-24T12:28:51Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add tutorial&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
This work is part of the SparKit project, funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health and Long-Term Care and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&amp;lt;br&amp;gt;&lt;br /&gt;
Author: Csaba Pinter (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contact: Csaba Pinter, &amp;lt;email&amp;gt;pinter@cs.queensu.ca&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT Back to SlicerRT home]&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
|{{collaborator|logo|sparkit}}|{{collaborator|longname|sparkit}}&lt;br /&gt;
|{{collaborator|logo|ocairo}}|{{collaborator|longname|ocairo}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
The {{documentation/modulename}} module enables the user to compute and display the DVH curve from a dose volume and structure (set). DVH metrics, such as volume, minimum, maximum and mean dose, Vdose (the volume that is radiated by a dose greater than a specified dose), and Dvolume (the minimum dose in the most exposed portion of a certain volume in a structure) can be also computed.&lt;br /&gt;
&lt;br /&gt;
The dimensions of the 3D elements (voxels) describing delineated structures are derived from the selected dose distribution volume, in which the voxels have width in the transverse imaging plane as described in the DICOM image header. The image set volume is defined by a grid of voxels derived from the voxel grid in the dose volume. The dose grid is oversampled by a factor currently fixed to the value 2. The centre of each voxel is examined and if found to lie within a structure, is included in the volume for that structure. The dose value at the centre of the cube is interpolated in 3D from the dose grid.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
Evaluate single or accumulated dose distributions against target structures and organs at risk (OARs)&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20181025_DVH_Screenshot_ModulePanel.png|thumb|572px|Dose Volume Histogram module UI]]&lt;br /&gt;
|[[File:20181025_DVH_Screenshot_Viewers.png|thumb|853px| Dose volume histogram views using SlicerRT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
* See workflow tutorials involving DVH on the [http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT#Tutorials SlicerRT main page]&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_DoseSurfaceHistogram.pptx Dose surface histogram tutorial]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
* '''Input'''&lt;br /&gt;
** '''Dose volume:''' The dose distribution using which the DVH is computed and the structure labelmap is created if necessary. All the volumes present in the Slicer scene appear here, however, when selecting a volume that has not been created by a SlicerRT module (such as DicomRtImport or DoseAccumulation), a warning will be displayed. If using such a volume, it is assumed not to contain dose values, so an Intensity Volume Histogram is created.&lt;br /&gt;
** '''Structure set:''' A contour or a contour hierarchy can be selected for which the DVH tables are computed. In case of a hierarchy, the DVH is computed for every contained contour.&lt;br /&gt;
** '''Dose surface histogram:''' If checked, then dose surface histogram (DSH) is calculated instead of a DVH. A current limitation is that open contours are not supported, so for example rectum structure bottom and top is considered.&lt;br /&gt;
* '''Output'''&lt;br /&gt;
** '''Show/hide all:''' After computing histograms, this checkbox adds or removes every histogram from the chart&lt;br /&gt;
** '''Switch layout:''' Switch layout to &amp;quot;four-up quantitative interactive&amp;quot; or &amp;quot;one-up quantitative interactive&amp;quot; so that DVH/DSH chart is visible&lt;br /&gt;
** '''DVH table'''&lt;br /&gt;
*** '''Checkbox:''' show/hide that specific structure in the selected chart&lt;br /&gt;
*** Structure data and computed DVH metrics appear in the columns&lt;br /&gt;
* '''Advanced options'''&lt;br /&gt;
** '''V metric for dose values:''' Values can be entered separated by commas. If 'cc' or '%' is checked, then the V metric for all structures according the entered values will appear in the DVH table in the checked unit(s)&lt;br /&gt;
** '''D metric for volumes:''' Values can be entered separated by commas in either ccs or percents. If 'Gy' is checked then the D metric for the entered volumes are displayed in the DVH table&lt;br /&gt;
** '''Export DVH to file:''' The currently plotted DVH tables are saved in CSV format&lt;br /&gt;
** '''Export DVH metrics to file:''' The currently displayed DVH table can be exported in CSV format&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{documentation/{{documentation/version}}/module-parametersdescription}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
* DVH Comparison&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
* Pinter, C.; Lasso, A.; Wang, A.; Jaffray, D. &amp;amp; Fichtinger, G. SlicerRT: Radiation therapy research toolkit for 3D Slicer Med. Phys., 2012, 39(10), 6332/7&lt;br /&gt;
* Ebert, M. A.; Haworth, A.; Kearvell, R.; Hooton, B.; Hug, B.; Spry, N. A.; Bydder, S. A. &amp;amp; Joseph, D. J. Comparison of DVH data from multiple planning systems Phys. Med. Biol., 2010, 55, N337–N346&lt;br /&gt;
* Drzymala, R. E.; R. Mohan, l. B.; Chu, J.; Goitein, M.; Harms, W. &amp;amp; Urie, M. Dose-Volume Histograms Radiation Oncology Biol. Phys., 1991, 21, 71-78&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
{|align=&amp;quot;left&amp;quot;&lt;br /&gt;
|[[File:20181024_DVH_NodesArchitecture.png|thumb|447px|Dose Volume Histogram nodes architecture]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/ExternalBeamPlanning&amp;diff=61306</id>
		<title>Documentation/Nightly/Modules/ExternalBeamPlanning</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/ExternalBeamPlanning&amp;diff=61306"/>
		<updated>2019-07-24T12:27:41Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add orthovoltage tutorial&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
This work was in part funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health and Long-Term Care and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&amp;lt;br&amp;gt;&lt;br /&gt;
Author: Csaba Pinter (PerkLab, Queen's University), Greg Sharp (Massachusetts General Hospital)&amp;lt;br&amp;gt;&lt;br /&gt;
Contact: Csaba Pinter, &amp;lt;email&amp;gt;csaba.pinter@queensu.ca&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT Back to SlicerRT home]&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
|{{collaborator|logo|ocairo}}|{{collaborator|longname|ocairo}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
The {{documentation/modulename}} module is a generic, extensible module for forward planning of external beam radiation therapy treatments.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
* Proton dose calculation&lt;br /&gt;
* Any dose engine can be integrated (C++, Python, Matlab)&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20171019_EBP_ProstateProton_Planning.png|thumb|820px|External Beam Planning module UI with a prostate proton plan]]&lt;br /&gt;
|[[File:20171019_EBP_ProstateProton_Dose.png|thumb|700px|Output dose of the plan above]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRtDoc/blob/master/tutorials/SlicerRT_Tutorial_OrthovoltageDoseEngine.pptx Orthovoltage RT treatment planning tutorial] (uses EGSnrc)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
* External Beam Planning module&lt;br /&gt;
** Basic plan data: Reference volume, Structure set, Isocenter, Target volume, Dose engine, Prescription dose&lt;br /&gt;
** Beam list&lt;br /&gt;
* Beams module: edit parameters of individual beams&lt;br /&gt;
** Geometry&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20171019_EBP_BeamParameters_Geometry.png|thumb|484px|Beam geometry parameters]]&lt;br /&gt;
|}&lt;br /&gt;
** Energy (extensible by plugins)&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20171019_EBP_ProtonBeamParameters_Energy.png|thumb|483px|Beam energy parameters (including proton-specific parameters)]]&lt;br /&gt;
|}&lt;br /&gt;
** Beam model (extensible by plugins)&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20171019_EBP_ProtonBeamParameters_BeamModel.png|thumb|484px|Beam model parameters (including proton-specific parameters)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{documentation/{{documentation/version}}/module-parametersdescription}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
* N/A&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
* Sharp, G., Pinter, C., Unkelbach, J., Fichtinger, G. (2017). Open Source Proton Treatment Planning in 3D Slicer: Status Update. Proceedings to the 56 Annual Meeting of the Particle Therapy Cooperative Group (PTCOG), 8-13 May 2017. International Journal of Particle Therapy: Summer 2017, Vol. 4, No. 1, pp. 14-83.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
* Sample C++ dose engine: https://github.com/SlicerRt/SlicerRT/blob/master/ExternalBeamPlanning/DoseEngines/qSlicerMockDoseEngine.h&lt;br /&gt;
* Sample Python dose engine: https://github.com/SlicerRt/SlicerRT/blob/master/ExternalBeamPlanning/DoseEngines/Python/MockPythonDoseEngine.py&lt;br /&gt;
* Future plans&lt;br /&gt;
** Inverse planning capabilities&lt;br /&gt;
** Matlab plugin adapter&lt;br /&gt;
** Ports module (apertures, MLC, target volume)&lt;br /&gt;
** Beam groups (common parameters for a group of beams)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/Build_Instructions/Prerequisites&amp;diff=61262</id>
		<title>Documentation/Nightly/Developers/Build Instructions/Prerequisites</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/Build_Instructions/Prerequisites&amp;diff=61262"/>
		<updated>2019-06-27T16:52:43Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Common Prerequisites */ Add direct Qt 5.10.0 download link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== PREREQUISITES ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- For all systems be sure git-lfs is properly installed for use with VTKv9 (required for VTKm checkout) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As of early 2018, Slicer migrated to Qt5. Qt4 support was removed in version 4.11. See instructions at this labs page for the new requirements: https://www.slicer.org/wiki/Documentation/Labs/Qt5-and-VTK8&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Please check that the following tools are installed on your machine.&lt;br /&gt;
&lt;br /&gt;
We try to keep current with the most recent releases of these prerequisites, but sometimes it's critical to use the exact versions specified here.  If you run into issues please do whatever you can to find a combination that works or contact the developer mailing list for suggestions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{{mbox&lt;br /&gt;
| type = protection&lt;br /&gt;
| text = Qt libraries are '''required'''. Consider reading [[Documentation/{{documentation/version}}/Developers/Build_Instructions/Prerequisites/Qt|Qt requirements]].&lt;br /&gt;
| image= [[{{tool|logo|qt}}|x40px]]&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{mbox&lt;br /&gt;
| type = protection&lt;br /&gt;
| text = CMake is '''required'''.&lt;br /&gt;
| image= [[{{tool|logo|cmake}}|x40px]]&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{mbox&lt;br /&gt;
| type = protection&lt;br /&gt;
| text = &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;Git is '''required'''.&lt;br /&gt;
| image= [[{{tool|logo|git}}|x40px]]&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{mbox&lt;br /&gt;
| type = protection&lt;br /&gt;
| text = SVN is '''required'''.&lt;br /&gt;
| image= [[{{tool|logo|svn}}|x40px]]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
The prerequisites listed below are required to be able to configure/build/package/test Slicer.&lt;br /&gt;
&lt;br /&gt;
=== Linux  ===&lt;br /&gt;
* [{{tool|download|cmake}} CMake] &amp;gt;= 3.13.4&lt;br /&gt;
* [{{tool|download|git}} Git] &amp;gt;= 1.7.10&lt;br /&gt;
* [{{tool|download|svn}} Svn] &amp;gt;= 1.7&lt;br /&gt;
* Qt 5.11: &amp;lt;b&amp;gt;tested and recommended&amp;lt;/b&amp;gt;&lt;br /&gt;
** To build Slicer: install Qt using the distribution package manager.&lt;br /&gt;
** To package and redistribute Slicer: download and execute [https://download.qt.io/official_releases/online_installers/qt-unified-linux-x64-online.run qt-unified-linux-x64-online.run], install Qt, make sure to select &amp;lt;tt&amp;gt;qtscript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;qtwebengine&amp;lt;/tt&amp;gt; components.&lt;br /&gt;
* GCC suite&lt;br /&gt;
&lt;br /&gt;
==== Debian ====&lt;br /&gt;
&lt;br /&gt;
* Debian squeeze/wheezy/testing(jessie) users, start by pasting the following lines in a terminal&lt;br /&gt;
 sudo apt-get install subversion git-core git-svn&lt;br /&gt;
 sudo apt-get install build-essential libx11-dev libxt-dev libgl1-mesa-dev libosmesa6-dev libglu1-mesa-dev libfontconfig-dev libxrender-dev libncurses5-dev&lt;br /&gt;
 sudo apt-get install cmake&lt;br /&gt;
 sudo apt-get install qt-sdk&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Ubuntu ====&lt;br /&gt;
&lt;br /&gt;
===== Common Prerequisites =====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 sudo apt-get install subversion git-core git-svn&lt;br /&gt;
&lt;br /&gt;
 sudo apt-get install make gcc g++ libx11-dev libxt-dev libgl1-mesa-dev libglu1-mesa-dev libfontconfig-dev libxrender-dev libncurses5-dev&lt;br /&gt;
&lt;br /&gt;
 sudo apt-get install libosmesa6-dev  # Only for Ubuntu &amp;lt; 14.04.3&lt;br /&gt;
&lt;br /&gt;
{{remark|red|On Ubuntu 14.04.3 LTS, attempting to install &amp;lt;tt&amp;gt;libosmesa6-dev&amp;lt;/tt&amp;gt; results in an error.&amp;lt;pre&amp;gt;&lt;br /&gt;
The following packages have unmet dependencies:&lt;br /&gt;
 libosmesa6-dev : Depends: libosmesa6 (= 10.1.3-0ubuntu0.4) but it is not going to be installed&lt;br /&gt;
 E: Unable to correct problems, you have held broken packages.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
For more details, see [https://bugs.launchpad.net/ubuntu/+source/mesa-lts-utopic/+bug/1424059 Bug 1424059].}}&lt;br /&gt;
&lt;br /&gt;
{{remark|green|Slicer compiles successfully without that package, but &amp;lt;tt&amp;gt;VTK_OPENGL_HAS_OSMESA&amp;lt;/tt&amp;gt; is disabled.}}&lt;br /&gt;
&lt;br /&gt;
* For Qt5.5 on Ubuntu 16.04&lt;br /&gt;
 sudo apt-get install libgstreamer-plugins-base0.10-dev&lt;br /&gt;
&lt;br /&gt;
===== CMake =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Open a terminal and copy the command reported below&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Download stable version of CMake and extract the archive:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install curl&lt;br /&gt;
mkdir ~/Support &amp;amp;&amp;amp; cd ~/Support&lt;br /&gt;
curl -O https://cmake.org/files/v3.13/cmake-3.13.4-Linux-x86_64.tar.gz&lt;br /&gt;
tar -xzvf cmake-3.13.4-Linux-x86_64.tar.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Create symbolic links into &amp;lt;code&amp;gt;~/bin&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir -p ~/bin&lt;br /&gt;
for name in cmake ctest cpack ccmake cmake-gui; do&lt;br /&gt;
  ln -s ~/Support/cmake-3.13.4-Linux-x86_64/bin/$name ~/bin/$name&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{remark|red|You &amp;lt;b&amp;gt;MUST&amp;lt;/b&amp;gt; download the standard CMake binary because the distributed version of CMake cannot be used to build slicer.&amp;lt;br&amp;gt;&lt;br /&gt;
See [[Documentation/{{documentation/version}}/Developers/FAQ/Building#Why_distributed_CMake_can_not_be_used_on_Ubuntu_12.04_and_above_.3F|here]] for more details.}}&lt;br /&gt;
&lt;br /&gt;
==== CentOS ====&lt;br /&gt;
&lt;br /&gt;
See instructions reported in [https://github.com/Slicer/SlicerBuildEnvironment/blob/master/Docker/qt5-centos7/Dockerfile qt5-centos7/Dockerfile]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*CentOS user type:&lt;br /&gt;
 yum install make gcc-c++ libX11-devel libXt-devel libXrender-devel libXext-devel libGLU-devel mesa-libOSMesa-devel mesa-libGL-devel mesa-libGLU-devel ncurses&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Todo: This will have to be added in FAQ: Troubleshoot section&lt;br /&gt;
''glx-utils'' provides ''glxgears'' that can be used to test rendering&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MacOSX ===&lt;br /&gt;
* XCode command line tools must be installed:&lt;br /&gt;
  xcode-select --install&lt;br /&gt;
* El Capitan is what most developers use.&lt;br /&gt;
* CMake 3.12.2 is recommended. Check the minimum required CMake version [https://github.com/Slicer/Slicer/blob/master/CMakeLists.txt#L1 here]&lt;br /&gt;
* Qt 5: &amp;lt;b&amp;gt;tested and recommended&amp;lt;/b&amp;gt;.&lt;br /&gt;
** For building Slicer: download and execute [https://download.qt.io/official_releases/online_installers/qt-unified-mac-x64-online.dmg qt-unified-mac-x64-online.dmg], install Qt 5.10, make sure to select &amp;lt;tt&amp;gt;qtscript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;qtwebengine&amp;lt;/tt&amp;gt; components.&lt;br /&gt;
** For packaging and redistributing Slicer: build Qt using [https://github.com/jcfr/qt-easy-build#readme qt-easy-build]&lt;br /&gt;
&lt;br /&gt;
====MacOSX 10.9.4 (Mavericks)====&lt;br /&gt;
&lt;br /&gt;
''' (1) Make sure to install this update: http://support.apple.com/kb/DL1754'''&lt;br /&gt;
&lt;br /&gt;
''' (2) Use CMake 3.12.2 - it is known to be working and is supported''' (if you want to use CMake already installed on your system, 2.8.12.2 is known to work on Mac OS X 10.9.5)&lt;br /&gt;
&lt;br /&gt;
* Mac Os X &amp;gt;= 10.5 (Leopard)&lt;br /&gt;
* [{{tool|download|cmake}} CMake] &amp;gt;= 2.8.9&lt;br /&gt;
** For Mac Os X &amp;gt;= 10.8 ([http://en.wikipedia.org/wiki/OS_X_Mountain_Lion Mountain Lion]) and/or recent XCode &amp;gt;= 4.5.X - [{{tool|download|cmake}} CMake] &amp;gt;= 2.8.11 is required. See http://www.cmake.org/files/v2.8/cmake-2.8.11-Darwin64-universal.tar.gz&lt;br /&gt;
&amp;lt;!-- Waiting for the official release, get the release candidate rc1 [http://www.cmake.org/files/v2.8/cmake-2.8.11-rc1-Darwin64-universal.tar.gz here]. For explanation, see [[Documentation/{{documentation/version}}/Developers/Build_Instructions#ld:_framework_not_found_QtWebKit|here]] and [[Documentation/{{documentation/version}}/Developers/Build_Instructions#On_MacOSX_10.8.2C_CMake_hangs_forever|here]]. These versions are also known to work: exact version 20130121-g92bd8 [http://www.cmake.org/files/dev/cmake-2.8.10.20130121-g92bd8-Darwin-universal.tar.gz here] (or version &amp;gt;= 2.8.10.20130220 [http://www.cmake.org/files/dev/?C=M;O=D here]).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 $ curl -O http://www.cmake.org/files/v2.8/cmake-2.8.11-Darwin64-universal.tar.gz&lt;br /&gt;
 $ tar -xzvf cmake-2.8.11-Darwin64-universal.tar.gz --strip-components=1&lt;br /&gt;
&lt;br /&gt;
 $ CMake\ 2.8-11.app/Contents/bin/cmake --version&lt;br /&gt;
 cmake version 2.8.11&lt;br /&gt;
&lt;br /&gt;
* [{{tool|download|git}} Git] &amp;gt;= 1.7.10&lt;br /&gt;
* [{{tool|download|svn}} Svn] &amp;gt;= 1.7&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*[[{{tool|logo|cmake}}|x16px]] [{{tool|download|cmake}} CMake] &amp;gt;= 2.8.9&lt;br /&gt;
*[[{{tool|logo|git}}|x16px]] [{{tool|download|git}} Git] &amp;gt;= 1.6.5&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
* XCode (for the SDK libs)&lt;br /&gt;
** After installing XCode, install XCode command line developer tools: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
xcode-select --install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* XQuartz - For Mac Os X &amp;gt;= 10.8 ([http://en.wikipedia.org/wiki/OS_X_Mountain_Lion Mountain Lion]) install XQuartz (http://xquartz.macosforge.org) to get X11 (no longer a default in OS X).&lt;br /&gt;
* Qt 4 &amp;gt;= 4.8.5. We recommend you install the following two packages:&lt;br /&gt;
** Download and install [http://download.qt-project.org/official_releases/qt/4.8/4.8.6/qt-opensource-mac-4.8.6-1.dmg qt-opensource-mac-4.8.6-1.dmg]&lt;br /&gt;
** Download and install [http://download.qt-project.org/official_releases/qt/4.8/4.8.6/qt-opensource-mac-4.8.6-1-debug-libs.dmg qt-opensource-mac-4.8.6-1-debug-libs.dmg]&lt;br /&gt;
** For more details [[Documentation/{{documentation/version}}/Developers/Build_Instructions/Prerequisites/Qt#Mac|here]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
** Newer Xcode versions (e.g. 4.3.2) use clang as the default compiler and '''clang is not compatible with ITK version 3'''.  You should use ITK version 4 with recent versions of Xcode.&lt;br /&gt;
** Xcode with gcc should ork with either version of ITK.&lt;br /&gt;
** OS X Mountain Lion: In Xcode 4.5 you now need to install command line tools (no longer included by default). Install within Xcode under the Xcode-&amp;gt;Preferences-&amp;gt;Downloads tab (otherwise git svn will give errors). Then you will need to install XQuartz (http://xquartz.macosforge.org) to get X11 (no longer a default in OS X).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Mac OSX 10.11 (El Capitan)====&lt;br /&gt;
&lt;br /&gt;
XCode up to version 7 is known to work for Slicer compilation. XCode 8 breaks things on several levels for now. &lt;br /&gt;
Remember to install XCode command line tools (see above) if a reinstall for XCode is needed. &lt;br /&gt;
&lt;br /&gt;
The standard Qt4 installers fail on this version and the 4.8.6 source code won't build.  But [http://slicer-devel.65872.n3.nabble.com/incompatible-qt-4-8-6-with-OS-X-El-Capitan-td4035551.html as described on the slicer-devel mailing list] it is possible to install the [https://github.com/Homebrew/formula-patches/blob/master/qt/el-capitan.patch homebrew version of qt4 which patches it to work on El Capitan] (see below).&lt;br /&gt;
&lt;br /&gt;
* Install the '''OS''', '''Xcode''', and '''XQuartz''' (see MacOSX 10.10 above)&lt;br /&gt;
* Install '''Qt4''' by running the following two commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
brew install qt4&lt;br /&gt;
xcode-select --install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* TCL does not build correctly on El Capitan as of 2015-12-03, so when building Slicer turn `Slicer_USE_PYTHONQT_WITH_TCL` off.&lt;br /&gt;
&lt;br /&gt;
==== Mac OSX 10.12 (Sierra) ====&lt;br /&gt;
&lt;br /&gt;
Similar to 10.11 (El Capitan), there are new issues with Qt4 (caused by Phonon).&lt;br /&gt;
The GitHub user Cartr [https://github.com/Homebrew/homebrew-core/pull/5216 offered a patch to the brew team], and even though it was not integrated (the homebrew team decided to stop patching their recipe to encourage people to use Qt5), he [https://github.com/cartr/homebrew-qt4 turned his formula into a tap] that can be installed (see below).&lt;br /&gt;
&lt;br /&gt;
Follow instructions for 10.11 ''(Installing Xcode, XQuartz, run without TCL)'' but install '''Qt4''' like shown below instead:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
brew install cartr/qt4/qt&lt;br /&gt;
xcode-select --install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Confirmed with Xcode: &lt;br /&gt;
* Version 8.1 (8B62) and cmake version 3.4.20151021-g8fbc8e&lt;br /&gt;
* Version 8.3.3 and cmake 3.5.2&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.9 -DSlicer_USE_PYTHONQT_WITH_TCL:BOOL=OFF ../Slicer&lt;br /&gt;
make -j `sysctl -n hw.ncpu`&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mac OSX 10.14 (Mojave) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Associated discussion topic is https://discourse.slicer.org/t/building-on-mac-10-14-mojave/4554/21&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Install Qt 5.11.2 using [http://download.qt.io/official_releases/online_installers/qt-unified-mac-x64-online.dmg Qt Online Installer for macOS]&lt;br /&gt;
&lt;br /&gt;
* Install XCode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
xcode-select --install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Explicitly set the SDK when running make&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SDKROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk make -j20&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
&lt;br /&gt;
==== Common Prerequisites ====&lt;br /&gt;
* [{{tool|download|cmake}} CMake] &amp;gt;= 3.13.4&lt;br /&gt;
* [{{tool|download|git}} Git] &amp;gt;= 1.7.10&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*[[{{tool|logo|cmake}}|x16px]]  [{{tool|download|cmake}}  CMake] &amp;gt;= 3.13.4&lt;br /&gt;
*[[{{tool|logo|git}}|x16px]]  [{{tool|download|git}}  Git] &amp;gt;= 1.7.10&lt;br /&gt;
* [https://code.google.com/p/msysgit/downloads/list?can=3 ''Git-X.X.X-preview2013XXXX.exe''] recommended.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
** Use of [http://code.google.com/p/tortoisegit/ TortoiseGit] is optional.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
** {{note}}CMake must be able to find ''git.exe'' and ''patch.exe''. If git is installed in the default location then they may be found there, but if they are not found then either add the folder that contains them to PATH environment variable; or set GIT_EXECUTABLE and Patch_EXECUTABLE as environment variables or as CMake variables at configure time.&lt;br /&gt;
&lt;br /&gt;
* Subversion (SVN) client: any SVN client that has command line tools&lt;br /&gt;
** [http://www.sliksvn.com/en/download SlikSvn] &amp;lt;!-- or [http://www.cygwin.com cygwin's svn client]--&amp;gt;, or&lt;br /&gt;
** [https://tortoisesvn.net/downloads.html TortoiseSVN] - make sure you install ''Command line client tools'' component (disabled by default)&lt;br /&gt;
&lt;br /&gt;
* NSIS (optional): Needed if packaging Slicer - Click [http://nsis.sourceforge.net/Download here] to download. Make sure you install the language packs.&lt;br /&gt;
&lt;br /&gt;
* Qt5: Download [https://download.qt.io/official_releases/online_installers/qt-unified-windows-x86-online.exe qt-unified-windows-x86-online.exe] and install Qt along with &amp;lt;tt&amp;gt;qtscript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;qtwebengine&amp;lt;/tt&amp;gt; components. For building with VS2015, Qt version 5.10.x or older is required (newer versions do not compile with VS2015 due to QWebEngine minimum requirement is VS2017). For more details, read [[Documentation/Nightly/Developers/Build Instructions/Prerequisites/Qt5|step-by-step]] guide.&lt;br /&gt;
** Note: 5.10.x has been removed from the unified installer. You can download the 5.10.0 installer from [https://download.qt.io/archive/qt/5.10/5.10.0 here]&lt;br /&gt;
&lt;br /&gt;
==== Tested and recommended build environment ====&lt;br /&gt;
&lt;br /&gt;
* VS2015 (Visual Studio 14 2015 Win64)&lt;br /&gt;
** Make sure you enable installation of component ''Programming languages / Visual C++ / Common Tools for Visual C++ 2015'' (in some distributions, this option is not enabled by default)&lt;br /&gt;
** Installation of [https://msdn.microsoft.com/en-us/library/mt752379.aspx Cumulative Servicing Release for Microsoft Visual Studio 2015 Update 3 (KB3165756)] is required on some older VS2015 distributions&lt;br /&gt;
* Qt 5.10&lt;br /&gt;
* CMake &amp;gt;= 3.13.4&lt;br /&gt;
&lt;br /&gt;
==== Experimental/deprecated build environments ====&lt;br /&gt;
* [https://visualstudio.microsoft.com/vs/community/ Visual Studio 2017 or 2019 (Community or any other edition)] with VS2015 build tools (tested, works well)&lt;br /&gt;
** When configuring Visual Studio installer, enable installation of component ''VC++ 2015.3 v14.00 (v140) toolset for desktop''&lt;br /&gt;
** Visual Studio 2015 toolset must be set in CMake: ''Optional toolset to use (argument to -T)'' need to be set to ''v140''&lt;br /&gt;
* Cygwin (untested, probably does not work)&lt;br /&gt;
** Cygwin suite (building with cygwin gcc not supported, but the cygwin shell environment can be used to run git, svn, etc).&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61221</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61221"/>
		<updated>2019-06-13T20:27:04Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Replace xrange to range for Python3 compatibility&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=&lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the [[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
* [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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
* [https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
* [https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
* [https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
* Capture the full Slicer screen and save it into a file&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
* Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
* Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
* How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
* How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[success, loadedVolumeNode] = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd', returnNode=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Automatically load volumes that are copied into a folder ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to implement a simple background task by using a timer. The background task is to check for any new volume files in folder and if there is any then automatically load it.&lt;br /&gt;
&lt;br /&gt;
There are more efficient methods for file system monitoring or exchanging image data in real-time (for example, using OpenIGTLink), the example below is just for demonstration purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
incomingVolumeFolder = &amp;quot;c:/tmp/incoming&amp;quot;&lt;br /&gt;
incomingVolumesProcessed = []&lt;br /&gt;
&lt;br /&gt;
def checkForNewVolumes():&lt;br /&gt;
  # Check if there is a new file in the &lt;br /&gt;
  from os import listdir&lt;br /&gt;
  from os.path import isfile, join&lt;br /&gt;
  for f in listdir(incomingVolumeFolder):&lt;br /&gt;
    if f in incomingVolumesProcessed:&lt;br /&gt;
      # this is an incoming file, it was already there&lt;br /&gt;
      continue&lt;br /&gt;
    filePath = join(incomingVolumeFolder, f)&lt;br /&gt;
    if not isfile(filePath):&lt;br /&gt;
      # ignore directories&lt;br /&gt;
      continue&lt;br /&gt;
    logging.info(&amp;quot;Loading new file: &amp;quot;+f)&lt;br /&gt;
    incomingVolumesProcessed.append(f)&lt;br /&gt;
    slicer.util.loadVolume(filePath)&lt;br /&gt;
  # Check again in 3000ms&lt;br /&gt;
  qt.QTimer.singleShot(3000, checkForNewVolumes)&lt;br /&gt;
&lt;br /&gt;
# Start monitoring&lt;br /&gt;
checkForNewVolumes()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
=== How to access tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
=== How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
=== How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm', returnNode=True)[1]; slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Export a volume to DICOM file format ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Customize table columns in DICOM browser ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database() # Need to go this way, do not use slicer.dicomDatabase for this&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
* How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
for viewNode in viewNodes:&lt;br /&gt;
  viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
* How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(&amp;quot;ModifiedEvent&amp;quot;, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(&amp;quot;ModifiedEvent&amp;quot;, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Switching to markup fiducial placement mode ==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change markup fiducial display properties ==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a markup point position is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupsNodeModified(markupsNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
  if not sliceView:&lt;br /&gt;
    print(&amp;quot;Markup list was modified&amp;quot;)&lt;br /&gt;
    return&lt;br /&gt;
  movingMarkupIndex = markupsNode.GetAttribute('Markups.MovingMarkupIndex')&lt;br /&gt;
  pos = [0,0,0]&lt;br /&gt;
  markupsNode.GetNthFiducialPosition(int(movingMarkupIndex), pos)  &lt;br /&gt;
  print(&amp;quot;Markup {0} was moved in slice view {1} to {2}&amp;quot;.format(movingMarkupIndex, sliceView, pos))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(vtk.vtkCommand.ModifiedEvent, onMarkupsNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a transform is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a context menu when a markup point is clicked in a slice or 3D view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Example actions to perform&lt;br /&gt;
&lt;br /&gt;
def action1():&lt;br /&gt;
  print('Action1 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action2():&lt;br /&gt;
  print('Action2 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action3():&lt;br /&gt;
  print('Action3 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
# Clicked markup index is saved here to let the action&lt;br /&gt;
# know which markup needs to be manipulated.&lt;br /&gt;
slicer.clickedMarkupIndex = -1&lt;br /&gt;
  &lt;br /&gt;
# Create a simple menu&lt;br /&gt;
&lt;br /&gt;
menu = qt.QMenu()&lt;br /&gt;
a1 = qt.QAction(&amp;quot;Test&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a1.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a1)&lt;br /&gt;
a2 = qt.QAction(&amp;quot;Action&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a2.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a2)&lt;br /&gt;
a3 = qt.QAction(&amp;quot;Here&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a3.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a3)&lt;br /&gt;
&lt;br /&gt;
# Add observer to a markup fiducial list&lt;br /&gt;
&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_INT)&lt;br /&gt;
def markupClickedCallback(caller, eventId, callData):&lt;br /&gt;
  slicer.clickedMarkupIndex = callData&lt;br /&gt;
  print('Open menu on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
  menu.move(qt.QCursor.pos())&lt;br /&gt;
  menu.show()&lt;br /&gt;
&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
observerTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointClickedEvent, markupClickedCallback)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write markup positions to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write annotation ROI to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a simple surface mesh as a model node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to display a simple surface mesh (a box, created by a VTK source filter) as a model node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create and set up polydata source&lt;br /&gt;
box = vtk.vtkCubeSource()&lt;br /&gt;
box.SetXLength(30)&lt;br /&gt;
box.SetYLength(20)&lt;br /&gt;
box.SetZLength(15)&lt;br /&gt;
box.SetCenter(10,20,5)&lt;br /&gt;
&lt;br /&gt;
# Create a model node that displays output of the source&lt;br /&gt;
boxNode = slicer.modules.models.logic().AddModel(box.GetOutputPort())&lt;br /&gt;
&lt;br /&gt;
# Adjust display properties&lt;br /&gt;
boxNode.GetDisplayNode().SetColor(1,0,0)&lt;br /&gt;
boxNode.GetDisplayNode().SetOpacity(0.8)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add a texture mapped plane to the scene as a model ==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# use dummy image data here&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
&lt;br /&gt;
scene = slicer.mrmlScene&lt;br /&gt;
&lt;br /&gt;
# Create model node&lt;br /&gt;
model = slicer.vtkMRMLModelNode()&lt;br /&gt;
model.SetScene(scene)&lt;br /&gt;
model.SetName(scene.GenerateUniqueName(&amp;quot;2DImageModel&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
model.SetAndObservePolyData(planeSource.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create display node&lt;br /&gt;
modelDisplay = slicer.vtkMRMLModelDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
modelDisplay.SetScene(scene)&lt;br /&gt;
scene.AddNode(modelDisplay)&lt;br /&gt;
model.SetAndObserveDisplayNodeID(modelDisplay.GetID())&lt;br /&gt;
&lt;br /&gt;
# Add to scene&lt;br /&gt;
modelDisplay.SetAndObserveTextureImageData(e.GetOutput())&lt;br /&gt;
scene.AddNode(model) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
transform = slicer.vtkMRMLLinearTransformNode()&lt;br /&gt;
scene.AddNode(transform) &lt;br /&gt;
model.SetAndObserveTransformNodeID(transform.GetID())&lt;br /&gt;
&lt;br /&gt;
vTransform = vtk.vtkTransform()&lt;br /&gt;
vTransform.Scale(50,50,50)&lt;br /&gt;
vTransform.RotateX(30)&lt;br /&gt;
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get scalar values at surface of a model ==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export entire scene as VRML ==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export model to Blender, including color by scalar ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export a tract (FiberBundle) to Blender, including color ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Iterate over tract (FiberBundle) streamline points ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a volume ==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a new volume ==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
thresholder = vtk.vtkImageThreshold()&lt;br /&gt;
thresholder.SetInputData(imageData)&lt;br /&gt;
thresholder.SetInValue(fillVoxelValue)&lt;br /&gt;
thresholder.SetOutValue(fillVoxelValue)&lt;br /&gt;
thresholder.Update()&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(thresholder.GetOutput())&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify voxels in a volume ==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.SetScalarComponentFromFloat(distortionVectorPosition_Ijk[0], distortionVectorPosition_Ijk[1], distortionVectorPosition_Ijk[2], 0, fillValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get volume voxel coordinates from markup fiducial RAS coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get markup fiducial RAS coordinates from volume voxel coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get the values of all voxels for a label value  ==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Access values in a DTI tensor volume ==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in range(extent[4], extent[5]+1):&lt;br /&gt;
  for j in range(extent[2], extent[3]+1):&lt;br /&gt;
    for i in range(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change window/level (brightness/contrast) or colormap of a volume ==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Make mouse left-click and drag on the image adjust window/level ==&lt;br /&gt;
&lt;br /&gt;
In older Slicer versions, by default, left-click and drag in a slice view adjusted window/level of the displayed image. Window/level adjustment is now a new mouse mode that can be activated by clicking on its toolbar button or running this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.applicationLogic().GetInteractionNode().SetCurrentInteractionMode(slicer.vtkMRMLInteractionNode.AdjustWindowLevel)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create custom color table ==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Manipulate a Slice View ==&lt;br /&gt;
&lt;br /&gt;
=== Change slice offset ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Change slice orientation ===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show slice views in 3D window ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reset field of view to show background volume maximized ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rotate slice views to volume plane ===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Iterate over current visible slice views, and set foreground and background images ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     sliceWidget = layoutManager.sliceWidget(sliceViewName)&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Synchronize zoom factor between slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.sliceNodes = [slicer.app.layoutManager().sliceWidget(viewName).mrmlSliceNode()&lt;br /&gt;
    for viewName in slicer.app.layoutManager().sliceViewNames()]&lt;br /&gt;
&lt;br /&gt;
slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
def sliceModified(caller, event):&lt;br /&gt;
    if slicer.updatingSliceNodes:&lt;br /&gt;
        # prevent infinite loop of slice node updates triggering slice node updates&lt;br /&gt;
        return&lt;br /&gt;
    slicer.updatingSliceNodes = True&lt;br /&gt;
    fov = caller.GetFieldOfView()&lt;br /&gt;
    for sliceNode in slicer.sliceNodes:&lt;br /&gt;
        if sliceNode != caller:&lt;br /&gt;
            sliceNode.SetFieldOfView(*fov)&lt;br /&gt;
    slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
for sliceNode in slicer.sliceNodes:&lt;br /&gt;
    sliceNode.AddObserver(vtk.vtkCommand.ModifiedEvent, sliceModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change opacity of foreground volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fit slice plane to markup fiducials ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.array([0,0,0])&lt;br /&gt;
p2 = np.array([0,0,0])&lt;br /&gt;
p3 = np.array([0,0,0])&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0, 0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a series of images from a Slice View ==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a new directory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a single MRB file ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a node to file ==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Center the 3D View on the Scene ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Display text in a 3D view or slice view ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide slice view annotations (DataProbe) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Turning off interpolation ==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Customize viewer layout ==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;layout type=&amp;quot;vertical&amp;quot; split=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLViewNode&amp;quot; singletontag=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
   &amp;lt;view class=&amp;quot;vtkMRMLSliceNode&amp;quot; singletontag=&amp;quot;Red&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;orientation&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewlabel&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;viewcolor&amp;quot; action=&amp;quot;default&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&lt;br /&gt;
   &amp;lt;/view&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/layout&amp;gt;&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Built-in layout IDs are all below 100, so you can choose any large random number&lt;br /&gt;
# for your custom layout ID.&lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
&lt;br /&gt;
# Switch to the new custom layout &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
== Customize keyboard shortcuts ==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Disable certain user interactions in slice views ==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change default slice view orientation ==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Set all slice views linked by default ==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set up custom units in slice view ruler ==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in range(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a slice view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceLayoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
sliceLayoutLabel = &amp;quot;T&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
sliceNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
sliceNode.SetName(sliceLayoutName)&lt;br /&gt;
sliceNode.SetLayoutName(sliceLayoutName)&lt;br /&gt;
sliceNode.SetLayoutLabel(sliceLayoutLabel)&lt;br /&gt;
sliceNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
sliceNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
sliceNode = slicer.mrmlScene.AddNode(sliceNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(sliceLayoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
sliceWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
sliceWidget.sliceViewName = sliceLayoutName&lt;br /&gt;
sliceWidget.sliceViewLabel = sliceLayoutLabel&lt;br /&gt;
c = sliceNode.GetLayoutColor()&lt;br /&gt;
sliceWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
sliceWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
sliceWidget.setMRMLSliceNode(sliceNode)&lt;br /&gt;
sliceWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Running an ITK filter in Python using SimpleITK ==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
* See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
* 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&lt;br /&gt;
&lt;br /&gt;
== Get current mouse coordinates in a slice view ==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get DataProbe text ==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get reformatted image from a slice viewer as numpy array ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print voxels.shape&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thick slab reconstruction and maximum/minimum intensity volume projections ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
== Change default file type for nodes (that have never been saved yet) ==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
== Change file type for saving for all volumes (with already existing storage nodes) ==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sequences ==&lt;br /&gt;
&lt;br /&gt;
=== Concatenate all sequences in the scene into a new sequence ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Segmentations ==&lt;br /&gt;
&lt;br /&gt;
=== Create a segmentation from a labelmap volume and display in 3D ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
=== Export labelmap node from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
Export smallest possible labelmap:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export labelmap that matches geometry of a chosen reference volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Export by pressing Ctrl+Shift+s key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPath = &amp;quot;c:/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def exportLabelmap():&lt;br /&gt;
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLSegmentationNode&amp;quot;)&lt;br /&gt;
    referenceVolumeNode = slicer.mrmlScene.GetFirstNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
    labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
    slicer.modules.segmentations.logic().ExportVisibleSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, referenceVolumeNode)&lt;br /&gt;
    filepath = outputPath + &amp;quot;/&amp;quot; + referenceVolumeNode.GetName()+&amp;quot;-label.nrrd&amp;quot;&lt;br /&gt;
    slicer.util.saveNode(labelmapVolumeNode, filepath)&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode.GetDisplayNode().GetColorNode())&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
    slicer.util.delayDisplay(&amp;quot;Segmentation saved to &amp;quot;+filepath)&lt;br /&gt;
&lt;br /&gt;
shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
shortcut.setKey(qt.QKeySequence('Ctrl+Shift+s'))&lt;br /&gt;
shortcut.connect( 'activated()', exportLabelmap)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Export model nodes from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
exportedModelsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelHierarchyNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModelHierarchy(seg, exportedModelsNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show a segmentation in 3D ===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get a representation of a segment ===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = segmentationNode.GetBinaryLabelmapRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using default path and conversion parameters ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using custom path or conversion parameters ===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-convert using a modified conversion parameter ===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get centroid of a segment in world (RAS) coordinates ===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How to run segment editor effects from a script ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
* [https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
* [https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
* [https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
* [https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
== Accessing views, renderers, and cameras ==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide view controller bars ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change 3D view background color ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderer = renderWindow.GetRenderers().GetFirstRenderer()&lt;br /&gt;
renderer.SetBackground(1,0,0)&lt;br /&gt;
renderer.SetBackground2(1,0,0)&lt;br /&gt;
renderWindow.Render()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subject hierarchy == &lt;br /&gt;
==== Get the pseudo-singleton subject hierarchy node ====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
&lt;br /&gt;
==== Create subject hierarchy item ====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
==== Get subject hierarchy item ====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
==== Traverse children of a subject hierarchy item ====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in range(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
==== Manipulate subject hierarchy item ====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data nodes associated to items in a branch (or a leaf item)&lt;br /&gt;
  shNode.SetDisplayVisibilityForBranch(itemID, 1)&lt;br /&gt;
&lt;br /&gt;
==== Filter items in TreeView or ComboBox ====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
=== Listen to subject hierarchy item events ===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
== Plotting ==&lt;br /&gt;
&lt;br /&gt;
=== Create histogram plot of a volume ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Execute external applications ==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
=== Run process in default environment ===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61209</id>
		<title>Documentation/Nightly/Extensions/SlicerRT</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61209"/>
		<updated>2019-06-06T14:16:34Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
[[{{collaborator|logo|cco}}]] &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|canarie}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|ocairo}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|sparkit}}]]&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
Authors: &amp;lt;b&amp;gt;Csaba Pinter&amp;lt;/b&amp;gt; (PerkLab, Queen's University), &amp;lt;b&amp;gt;Andras Lasso&amp;lt;/b&amp;gt; (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contributors: &amp;lt;b&amp;gt;Greg Sharp&amp;lt;/b&amp;gt; (Massachusetts General Hospital), Kevin Wang (Princess Margaret Hospital, UHN Toronto), Steve Pieper (Isomics)&amp;lt;br&amp;gt;&lt;br /&gt;
Contacts:&lt;br /&gt;
* Csaba Pinter, &amp;lt;email&amp;gt;pinter.csaba@gmail.com&amp;lt;/email&amp;gt;&lt;br /&gt;
* Andras Lasso, &amp;lt;email&amp;gt;lasso@cs.queensu.ca&amp;lt;/email&amp;gt;&lt;br /&gt;
* [https://discourse.slicer.org Slicer Forum]&lt;br /&gt;
* [[Documentation/SlicerRT/HowToReportAnError|How to report an error]]&lt;br /&gt;
Website: [http://slicerrt.github.io slicerrt.org]&amp;lt;br&amp;gt;&lt;br /&gt;
License: [http://www.slicer.org/pages/LicenseText Slicer license]&amp;lt;br&amp;gt;&lt;br /&gt;
'''Download/install:''' install 3D Slicer, start 3D Slicer, open the Extension Manager, install the SlicerRT extension (see more details [http://slicerrt.github.io/Download.html on the download page])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; margin-left:12px;&amp;quot;&amp;gt;&lt;br /&gt;
importScript('http://www.ohloh.net/p/641228/widgets/project_basic_stats.js');&lt;br /&gt;
&amp;lt;wiki:gadget url=&amp;quot;http://www.ohloh.net/p/641228/widgets/project_search_code.xml&amp;quot; height=&amp;quot;195&amp;quot; border=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Extension Description}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
[[Image:SlicerRT_Logo_3.0_128x128.png]]&lt;br /&gt;
|&lt;br /&gt;
* SlicerRT is a radiation therapy toolkit for 3D Slicer, containing generic RT features for import/export, analysis, visualization, aiming to make 3D Slicer a powerful radiotherapy research platform. SlicerRT development is currently funded by CANARIE.&amp;lt;br&amp;gt;SlicerRT was originally created via funding by Cancer Care Ontario and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&lt;br /&gt;
&lt;br /&gt;
* The SlicerRT extension incorporates [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]] modules and algorithms.&lt;br /&gt;
&lt;br /&gt;
* Additional information for users can be found on the [[Documentation/SlicerRT/UsersGuide|User's Guide]] page &amp;lt;br&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Modules}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
*[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External Beam Planning]] (Treatment planning)&lt;br /&gt;
* Dose analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseVolumeHistogram|Dose volume histogram]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseAccumulation|Dose accumulation]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseComparison|Dose comparison]] (Gamma dose similarity index)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Isodose|Isodose line and surface display]]&lt;br /&gt;
* Contour analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentComparison|Segment comparison]] (Dice Similarity Coefficient, Hausdorff distances)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentMorphology|Segment morphology]] (Add/remove margin, Unify, Intersect, etc.)&lt;br /&gt;
* I/O&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DicomRtImport|DICOM-RT import]], [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/DICOMExport export]&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing Batch processing scripts] (currently only one is available for command-line conversion of RTSS to volume nodes)&lt;br /&gt;
&lt;br /&gt;
* Modules from [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmBSplineDeformableRegistration|Plastimatch Automatic deformable image registration]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmLANDWARP|Plastimatch LANDWARP Landmark]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmSyntheticImageGeneration|Plastimatch Synthetic Image Generation]] (Greg Sharp)[[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Former SlicerRT modules integrated to Slicer core&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Data|Subject hierarchy]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Transforms|Transform visualizer]]&lt;br /&gt;
**DICOM-RT export, as [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/DICOMExport improved DICOM export function]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Segmentations|Segmentations]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentEditor|Segment Editor]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Experimental modules&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External beam planning]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
| [[File:SlicerRt_Montage.jpg|512px|SlicerRT highlights]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Use Cases}}&lt;br /&gt;
* Comparison of dose maps and dose volume histograms from various treatment planning systems&lt;br /&gt;
* Evaluation of the effect of different adaptive techniques (IGRT, image-based non-rigid patient motion compensation, etc.)&lt;br /&gt;
** Calculate couch shift parameters for patient setup correction in IGRT&lt;br /&gt;
* Dose accumulation with motion compensation&lt;br /&gt;
* Testing of treatment planning algorithms&lt;br /&gt;
* Calculation of PTV margin&lt;br /&gt;
* Proton dose calculation&lt;br /&gt;
* Gel dosimetry analysis&lt;br /&gt;
* Tumor volume tracking&lt;br /&gt;
* Treatment plan similarity measurement in the cloud&lt;br /&gt;
* Batch structure set conversion&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Tutorials}}&lt;br /&gt;
* '''World Congress 2015 tutorial''' ''(recommended)''&lt;br /&gt;
** Tutorial presentation: [https://www.dropbox.com/s/b7qx3n10s52o5f8/SlicerRT_WorldCongress_TutorialIGRT.pptx?dl=0 pptx] [https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SlicerRT_WorldCongress_TutorialIGRT.pdf pdf]&lt;br /&gt;
** Dataset: [http://slicer.kitware.com/midas3/download/item/205391/WC2015_Gel_Slicelet_Dataset.zip download] from MIDAS&lt;br /&gt;
* '''Summer NA-MIC week 2013 tutorial'''&lt;br /&gt;
** Tutorial presentation: [http://wiki.na-mic.org/Wiki/images/b/b0/SlicerRT_TutorialContestSummer2013.pdf download] from Slicer wiki&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/download/folder/1345/SlicerRtTutorial_Namic2013June.zip download] from MIDAS&lt;br /&gt;
* '''ECR 2013 - Medical University Vienna workshop'''&lt;br /&gt;
** Workshop material: [http://www.na-mic.org/Wiki/index.php/File:Pinter_MedUni2013_Workshop.pdf download] from NA-MIC.org&lt;br /&gt;
* '''RSNA 2012 tutorial'''&lt;br /&gt;
** Tutorial description: [http://www.donotlink.com/bEo SlicerRT wiki: Slicer tutorials at RSNA 2012]&lt;br /&gt;
&amp;lt;!-- Original link: https://www.assembla.com/spaces/slicerrt/wiki/20121127_Slicer_tutorials_at_RSNA_2012 --&amp;gt;&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/folder/859 download] SlicerRT ART dose verification data from Midas server&lt;br /&gt;
* Summer NA-MIC week 2012 tutorial '''(deprecated)'''&lt;br /&gt;
** Tutorial presentation: [https://www.assembla.com/spaces/slicerrt/documents/aAuMq81Eqr4ztvacwqjQXA/download/aAuMq81Eqr4ztvacwqjQXA download] from the SlicerRT website&lt;br /&gt;
&amp;lt;!-- Original link: https://www.assembla.com/spaces/slicerrt/documents/bMuwgYTKur4yP-acwqjQWU/download/bMuwgYTKur4yP-acwqjQWU --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Similar Extensions}}&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]: SlicerRT and Plastimatch are complementary software libraries. Plastimatch focuses on delivering new computational methods radiotherapy, while SlicerRT aims for providing an easy-to-use interface for a wide range of stable, well-tested radiotherapy related features. SlicerRT uses Plastimatch internally for certain operations.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/GelDosimetry|Gel Dosimetry]]: Slicelet facilitating a streamlined workflow to perform true 3D gel dosimetry analysis for commissioning linacs and evaluating new dose calculation procedures&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/FilmDosimetry|Film Dosimetry]]: Slicelet supporting workflow to perform 2D film dosimetry analysis for commissioning new radiation techniques and to validate the accuracy of radiation treatment by enabling visual comparison of the planned dose to the delivered dose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|References}}&lt;br /&gt;
==How to cite==&lt;br /&gt;
Please cite the following paper when referring to SlicerRt in your publication:&amp;lt;br&amp;gt;&lt;br /&gt;
C. Pinter, A. Lasso, A. Wang, D. Jaffray and G. Fichtinger, [http://perk.cs.queensu.ca/sites/perk.cs.queensu.ca/files/Pinter2012_0.pdf &amp;quot;SlicerRT – Radiation therapy research toolkit for 3D Slicer&amp;quot;], Med. Phys., 39(10) pp. 6332-6338, 2012&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@ARTICLE{Pinter2012,&lt;br /&gt;
  author = {Pinter, C. and Lasso, A. and Wang, A. and Jaffray, D. and Fichtinger, G.},&lt;br /&gt;
  title = {SlicerRT – Radiation therapy research toolkit for 3D Slicer},&lt;br /&gt;
  journal = {Med. Phys.},&lt;br /&gt;
  year = {2012},&lt;br /&gt;
  volume = {39},&lt;br /&gt;
  number = {10},&lt;br /&gt;
  pages = {6332-6338},&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Information for Developers}}&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/wiki/SlicerRt-developers-page SlicerRT developers wiki page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61208</id>
		<title>Documentation/Nightly/Extensions/SlicerRT</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerRT&amp;diff=61208"/>
		<updated>2019-06-06T14:13:32Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
[[{{collaborator|logo|cco}}]] &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|canarie}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|ocairo}}]]&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
[[{{collaborator|logo|sparkit}}]]&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
Authors: &amp;lt;b&amp;gt;Csaba Pinter&amp;lt;/b&amp;gt; (PerkLab, Queen's University), &amp;lt;b&amp;gt;Andras Lasso&amp;lt;/b&amp;gt; (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contributors: &amp;lt;b&amp;gt;Greg Sharp&amp;lt;/b&amp;gt; (Massachusetts General Hospital), Kevin Wang (Princess Margaret Hospital, UHN Toronto), Steve Pieper (Isomics)&amp;lt;br&amp;gt;&lt;br /&gt;
Contacts:&lt;br /&gt;
* Csaba Pinter, &amp;lt;email&amp;gt;pinter.csaba@gmail.com&amp;lt;/email&amp;gt;&lt;br /&gt;
* Andras Lasso, &amp;lt;email&amp;gt;lasso@cs.queensu.ca&amp;lt;/email&amp;gt;&lt;br /&gt;
* [https://discourse.slicer.org Slicer Forum]&lt;br /&gt;
* [[Documentation/SlicerRT/HowToReportAnError|How to report an error]]&lt;br /&gt;
Website: [http://slicerrt.github.io slicerrt.org]&amp;lt;br&amp;gt;&lt;br /&gt;
License: [http://www.slicer.org/pages/LicenseText Slicer license]&amp;lt;br&amp;gt;&lt;br /&gt;
'''Download/install:''' install 3D Slicer, start 3D Slicer, open the Extension Manager, install the SlicerRT extension (see more details [http://slicerrt.github.io/Download.html on the download page])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; margin-left:12px;&amp;quot;&amp;gt;&lt;br /&gt;
importScript('http://www.ohloh.net/p/641228/widgets/project_basic_stats.js');&lt;br /&gt;
&amp;lt;wiki:gadget url=&amp;quot;http://www.ohloh.net/p/641228/widgets/project_search_code.xml&amp;quot; height=&amp;quot;195&amp;quot; border=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Extension Description}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
[[Image:SlicerRT_Logo_3.0_128x128.png]]&lt;br /&gt;
|&lt;br /&gt;
* SlicerRT is one of the themes of the SparKit (Software Platform and Adaptive Radiotherapy Kit) project with the goal of making 3D Slicer a powerful radiotherapy research platform.&amp;lt;br&amp;gt;SparKit is a project funded by Cancer Care Ontario and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&lt;br /&gt;
&lt;br /&gt;
* The SlicerRT extension incorporates [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]] modules and algorithms.&lt;br /&gt;
&lt;br /&gt;
* Additional information for users can be found on the [[Documentation/SlicerRT/UsersGuide|User's Guide]] page &amp;lt;br&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Modules}}&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
*[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External Beam Planning]] (Treatment planning)&lt;br /&gt;
* Dose analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseVolumeHistogram|Dose volume histogram]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseAccumulation|Dose accumulation]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DoseComparison|Dose comparison]] (Gamma dose similarity index)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Isodose|Isodose line and surface display]]&lt;br /&gt;
* Contour analysis&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentComparison|Segment comparison]] (Dice Similarity Coefficient, Hausdorff distances)&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentMorphology|Segment morphology]] (Add/remove margin, Unify, Intersect, etc.)&lt;br /&gt;
* I/O&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/DicomRtImport|DICOM-RT import]], [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/DICOMExport export]&lt;br /&gt;
*[https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing Batch processing scripts] (currently only one is available for command-line conversion of RTSS to volume nodes)&lt;br /&gt;
&lt;br /&gt;
* Modules from [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmBSplineDeformableRegistration|Plastimatch Automatic deformable image registration]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmLANDWARP|Plastimatch LANDWARP Landmark]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/PlmSyntheticImageGeneration|Plastimatch Synthetic Image Generation]] (Greg Sharp)[[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Former SlicerRT modules integrated to Slicer core&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Data|Subject hierarchy]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Transforms|Transform visualizer]]&lt;br /&gt;
**DICOM-RT export, as [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/DICOMExport improved DICOM export function]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/Segmentations|Segmentations]]&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/SegmentEditor|Segment Editor]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Experimental modules&lt;br /&gt;
**[[Documentation/{{documentation/version}}/Modules/ExternalBeamPlanning|External beam planning]] [[image:UnderConstruction.png|tumb|10px]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
| [[File:SlicerRt_Montage.jpg|512px|SlicerRT highlights]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Use Cases}}&lt;br /&gt;
* Comparison of dose maps and dose volume histograms from various treatment planning systems&lt;br /&gt;
* Evaluation of the effect of different adaptive techniques (IGRT, image-based non-rigid patient motion compensation, etc.)&lt;br /&gt;
** Calculate couch shift parameters for patient setup correction in IGRT&lt;br /&gt;
* Dose accumulation with motion compensation&lt;br /&gt;
* Testing of treatment planning algorithms&lt;br /&gt;
* Calculation of PTV margin&lt;br /&gt;
* Proton dose calculation&lt;br /&gt;
* Gel dosimetry analysis&lt;br /&gt;
* Tumor volume tracking&lt;br /&gt;
* Treatment plan similarity measurement in the cloud&lt;br /&gt;
* Batch structure set conversion&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Tutorials}}&lt;br /&gt;
* '''World Congress 2015 tutorial''' ''(recommended)''&lt;br /&gt;
** Tutorial presentation: [https://www.dropbox.com/s/b7qx3n10s52o5f8/SlicerRT_WorldCongress_TutorialIGRT.pptx?dl=0 pptx] [https://github.com/SlicerRt/SlicerRtDoc/raw/master/tutorials/SlicerRT_WorldCongress_TutorialIGRT.pdf pdf]&lt;br /&gt;
** Dataset: [http://slicer.kitware.com/midas3/download/item/205391/WC2015_Gel_Slicelet_Dataset.zip download] from MIDAS&lt;br /&gt;
* '''Summer NA-MIC week 2013 tutorial'''&lt;br /&gt;
** Tutorial presentation: [http://wiki.na-mic.org/Wiki/images/b/b0/SlicerRT_TutorialContestSummer2013.pdf download] from Slicer wiki&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/download/folder/1345/SlicerRtTutorial_Namic2013June.zip download] from MIDAS&lt;br /&gt;
* '''ECR 2013 - Medical University Vienna workshop'''&lt;br /&gt;
** Workshop material: [http://www.na-mic.org/Wiki/index.php/File:Pinter_MedUni2013_Workshop.pdf download] from NA-MIC.org&lt;br /&gt;
* '''RSNA 2012 tutorial'''&lt;br /&gt;
** Tutorial description: [http://www.donotlink.com/bEo SlicerRT wiki: Slicer tutorials at RSNA 2012]&lt;br /&gt;
&amp;lt;!-- Original link: https://www.assembla.com/spaces/slicerrt/wiki/20121127_Slicer_tutorials_at_RSNA_2012 --&amp;gt;&lt;br /&gt;
** Sample data: [http://slicer.kitware.com/midas3/folder/859 download] SlicerRT ART dose verification data from Midas server&lt;br /&gt;
* Summer NA-MIC week 2012 tutorial '''(deprecated)'''&lt;br /&gt;
** Tutorial presentation: [https://www.assembla.com/spaces/slicerrt/documents/aAuMq81Eqr4ztvacwqjQXA/download/aAuMq81Eqr4ztvacwqjQXA download] from the SlicerRT website&lt;br /&gt;
&amp;lt;!-- Original link: https://www.assembla.com/spaces/slicerrt/documents/bMuwgYTKur4yP-acwqjQWU/download/bMuwgYTKur4yP-acwqjQWU --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Similar Extensions}}&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Plastimatch|Plastimatch]]: SlicerRT and Plastimatch are complementary software libraries. Plastimatch focuses on delivering new computational methods radiotherapy, while SlicerRT aims for providing an easy-to-use interface for a wide range of stable, well-tested radiotherapy related features. SlicerRT uses Plastimatch internally for certain operations.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/GelDosimetry|Gel Dosimetry]]: Slicelet facilitating a streamlined workflow to perform true 3D gel dosimetry analysis for commissioning linacs and evaluating new dose calculation procedures&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Modules/FilmDosimetry|Film Dosimetry]]: Slicelet supporting workflow to perform 2D film dosimetry analysis for commissioning new radiation techniques and to validate the accuracy of radiation treatment by enabling visual comparison of the planned dose to the delivered dose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|References}}&lt;br /&gt;
==How to cite==&lt;br /&gt;
Please cite the following paper when referring to SlicerRt in your publication:&amp;lt;br&amp;gt;&lt;br /&gt;
C. Pinter, A. Lasso, A. Wang, D. Jaffray and G. Fichtinger, [http://perk.cs.queensu.ca/sites/perk.cs.queensu.ca/files/Pinter2012_0.pdf &amp;quot;SlicerRT – Radiation therapy research toolkit for 3D Slicer&amp;quot;], Med. Phys., 39(10) pp. 6332-6338, 2012&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@ARTICLE{Pinter2012,&lt;br /&gt;
  author = {Pinter, C. and Lasso, A. and Wang, A. and Jaffray, D. and Fichtinger, G.},&lt;br /&gt;
  title = {SlicerRT – Radiation therapy research toolkit for 3D Slicer},&lt;br /&gt;
  journal = {Med. Phys.},&lt;br /&gt;
  year = {2012},&lt;br /&gt;
  volume = {39},&lt;br /&gt;
  number = {10},&lt;br /&gt;
  pages = {6332-6338},&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-section|Information for Developers}}&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/wiki/SlicerRt-developers-page SlicerRT developers wiki page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/extension-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DICOM&amp;diff=61134</id>
		<title>Documentation/Nightly/Modules/DICOM</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DICOM&amp;diff=61134"/>
		<updated>2019-05-08T16:28:30Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Customize DICOM browser table content */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
{{Clear|right}}{{TOC right}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
:'''Author(s)/Contributor(s):''' Steve Pieper (Isomics Inc.), Michael Onken (Offis), Marco Nolden (DFKZ), Julien Finet (Kitware), Stephen Aylward (Kitware), Nicholas Herlambang (AZE), Alireza Mehrtash (BWH), Csaba Pinter (PerkLab, Queen's)&amp;lt;br&amp;gt;&lt;br /&gt;
: '''Acknowledgements:''' This work is part of the [http://www.na-mic.org/ National Alliance for Medical Image Computing] (NA-MIC), funded by the National Institutes of Health through the NIH Roadmap for Medical Research, Grant U54 EB005149, and by Quantitative Image Informatics for Cancer Research (QIICR) (U24 CA180918) &amp;lt;br&amp;gt;&lt;br /&gt;
: '''Contact:''' Steve Pieper, &amp;lt;email&amp;gt;pieper@bwh.harvard.edu&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|isomics}}|{{collaborator|longname|isomics}}&lt;br /&gt;
|{{collaborator|logo|namic}}|{{collaborator|longname|namic}}&lt;br /&gt;
|{{collaborator|logo|nac}}|{{collaborator|longname|nac}}&lt;br /&gt;
|{{collaborator|logo|ctk}}|{{collaborator|longname|ctk}}&lt;br /&gt;
|{{collaborator|logo|qiicr}}|{{collaborator|longname|qiicr}}&lt;br /&gt;
|Image:DICOM-OFFIS-logo.png|DICOM-OFFIS&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-description}}&lt;br /&gt;
&lt;br /&gt;
DICOM is a widely used and sophisticated set of standards for digital radiology (see the [[#References|References]] section for more information). Slicer provides support for a subset of DICOM functionality, with the particular features driven by the needs of clinical research: '''loading''' and '''saving''' data sets from/to disk in DICOM format and '''sending''' and '''receiving''' data sets via DICOM networking.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
&lt;br /&gt;
=== Data import and loading ===&lt;br /&gt;
&lt;br /&gt;
Since DICOM files are often located in several folders, they can cross-reference each other, and can be often interpreted in different ways, importing and loading of DICOM files are performed as two separate steps:&lt;br /&gt;
- Import: User selects a folder that contains DICOM files. Slicer reads header of all files in a folder (and all its subfolders) and stores essential information in the Slicer DICOM database. Optionally Slicer can also make a full copy of the files into the database, which is useful if files are stored on a removable media (CD, DVD, USB drive). All indexed data gets listed in the DICOM browser.&lt;br /&gt;
- Loading: Items that user selected in the DICOM browser are loaded into the scene and displayed in viewers. In advanced mode, loading is performed in two steps: the application examines selected items and offers a list of loadable items that the user can choose from.&lt;br /&gt;
&lt;br /&gt;
==== Data import ====&lt;br /&gt;
&lt;br /&gt;
* Select folders that contain DICOM files&lt;br /&gt;
** Option A: Drag-and-drop the folder that contains DICOM files to the Slicer application window. Slicer displays a popup, asking what to do - click OK (&amp;quot;Load directory in DICOM database&amp;quot;). After import is completed, go to DICOM module.&lt;br /&gt;
** Option B: Go to DICOM module. Click &amp;quot;Import&amp;quot; button in the top-left corner of the DICOM browser. Select folder that contains DICOM files.&lt;br /&gt;
&lt;br /&gt;
Optionally select the Copy option so that the files are copied into the database directory.  Otherwise they will only be referenced in their original location. It is recommended to copy data if importing files from removable media (CD/DVD/USB drives) to be able to load the data set even after media is ejected.&lt;br /&gt;
&lt;br /&gt;
==== Data loading ====&lt;br /&gt;
&lt;br /&gt;
* Go to DICOM module. Click &amp;quot;Show DICOM browser&amp;quot; if the browser window is not visible (window title: &amp;quot;DICOM Browser&amp;quot;; it shows a list of patients, studies, and series).&lt;br /&gt;
* Select items to load. If an item in the patient or study list is selected then by default all series that belong to that item will be loaded.&lt;br /&gt;
* Click &amp;quot;Load&amp;quot; button to load selected items.&lt;br /&gt;
* Go to Data module to see what has been loaded and show/hide them.&lt;br /&gt;
&lt;br /&gt;
Advanced data loading: It is often possible to interpret DICOM data in different ways. If the application loaded data differently than expected then check &amp;quot;Advanced&amp;quot; checkbox, click &amp;quot;Examine&amp;quot; button, select all loadables in the list in the box at the bottom, and click &amp;quot;Load&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Some extensions make Slicer recognize more DICOM information object types. For example, SlicerRT extension makes it possible to load/export radiation therapy information objects (RT structure set, RT dose, RT image, RT plan). Make sure all relevant extensions are installed before attempting to load your data set.&lt;br /&gt;
&lt;br /&gt;
==== Deleting imported data ====&lt;br /&gt;
&lt;br /&gt;
By right clicking on a Patient, Study, or Series, you can delete the entry from the DICOM database.  Note that to avoid accidental data loss, Slicer does not delete the corresponding image data files.&lt;br /&gt;
&lt;br /&gt;
=== DICOM export ===&lt;br /&gt;
&lt;br /&gt;
Data in the scene can be exported to the DICOM database:&lt;br /&gt;
* Right-click on a data set in Data module (subject hierarchy tab) to export it to DICOM format. Export can also be initiated from DICOM browser.&lt;br /&gt;
* Edit tags for exportables. The metadata from the select study will be automatically filled in to the Export dialog and you can select a Slicer volume to export.&lt;br /&gt;
* Exported files are added to the DICOM database&lt;br /&gt;
&lt;br /&gt;
''Note that you should exercise extreme caution when working with these files in clinical situations, since non-standard or incorrect DICOM files can interfere with clinical operations.''&lt;br /&gt;
&lt;br /&gt;
You can also choose to encapsulate the current MRML scene (via an MRB file) inside a DICOM dataset, which will be treated as a DICOM secondary capture document. This secondary capture information stores all details of the scene but only 3D Slicer can interpret the data. This export feature has not been widely tested and should be considered experimental.&lt;br /&gt;
&lt;br /&gt;
=== Data networking ===&lt;br /&gt;
&lt;br /&gt;
DICOM is also a network communication standard. Slicer supports a DICOM Listener, DICOM Query/Retrieve interface, and a DICOM Send option.  Note that in order to use these features, you must coordinate with the operators of the other DICOM nodes with which you wish to communicate.  For example, you must work out agreement on such topics as network ports and application entity titles (AE Titles).  Be aware that not all equipment supports all networking options, so configuration may be challenging and is often difficult to troubleshoot.&lt;br /&gt;
&lt;br /&gt;
==== Connection Ports ====&lt;br /&gt;
&lt;br /&gt;
Port 104 is the standard DICOM port. All ports below 1024 require root access on unix-like systems (Linux and Mac).  So you can run Slicer with the sudo command to be able to open the port for the DICOM Listener.  Or you can use a different port, like 11112.  You need to configure that on both sides of the connection.  You can only have one process at a time listening on a port so if you have a listener running the second one won't start up.  Also if something adverse happens (a crash) the port may be kept open an you need to either kill the storescp helper process (or just reboot the computer) to free the port.  Consult the [[documentation/{{documentation/version}}/SlicerApplication/ErrorLog|Error Log]] for diagnostic information.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Screenshots}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[image:DICOM Screenshot-1 1204-11-17-10-36.png|thumb|380px|DICOM module in use]]&lt;br /&gt;
|[[Image:Form_224.png|thumb|380px|DICOM Query dialog]]&lt;br /&gt;
|[[Image:DICOM Horizontal View 2014-11-17-09-35.png|thumb|380px|Horizontal table view]]&lt;br /&gt;
|}&lt;br /&gt;
{|&lt;br /&gt;
|[[Image:DICOM-3 2014-11-17-10-42.png‎|thumb|380px|DICOM Browser in Advanced Mode (Control plugins and access to load options)]]&lt;br /&gt;
|[[Image:DICOM4 2014-11-17-09-38.png|thumb|380px|DICOM Meta Data Browser (DICOM header viewer)]]&lt;br /&gt;
|[[Image:DICOM-5 2014-11-17-10-46.png|thumb|380px|More options (change local database directory and table display density)]]&lt;br /&gt;
|}&lt;br /&gt;
{|&lt;br /&gt;
|[[Image:20141103_DICOM_Export_Dialog.png|thumb|380px|DICOM Export Dialog]]&lt;br /&gt;
|[[Image:DICOM-Preferences.png|thumb|380px|DICOM Preferences]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Tutorials ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
* See [http://www.na-mic.org/Wiki/index.php/RSNA_2012#3D_Interactive_Visualization_of_DICOM_images the RSNA 2012 Training on Visualization] for description and sample data (Direct link to [http://www.na-mic.org/Wiki/images/6/66/3DVisualizationDICOM_RadiologyApplications_SoniaPujol_RSNA2012.pdf slides as pdf]).&lt;br /&gt;
* [https://pieper.github.io/content/handson/#/DICOM This screen capture animation] shows how to import and load DICOM data (also includes inspection of the file contents, which is an optional step).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Panels ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels}}&lt;br /&gt;
&lt;br /&gt;
==DICOM import==&lt;br /&gt;
&lt;br /&gt;
Referring to the &amp;quot;DICOM in use&amp;quot; image in the top left of this page, the most important controls for day-to-day use are highlighted with gray callouts.  The are described here in the order you are likely to use them.&lt;br /&gt;
&lt;br /&gt;
*'''LocalDatabase''' (appears when ''&amp;gt;&amp;gt;'' button next to the menu bar is clicked): allows you to select a location on disk for Slicer's database of DICOM files. The application manages content of this folder (stores metadata and copy of imported DICOM files): do not manually copy any data into this folder.&lt;br /&gt;
*'''Import''' all DICOM files in the selected folder (including subfolders) will be parsed and basic information from file headers will be stored in Slicer's DICOM database. If enabled, then Slicer will make a copy of the imported files into the database folder.&lt;br /&gt;
*'''Patient list''' shows patients in the database. Studies available for the selected patient(s) are listed in study list. Multiple patients can be selected.&lt;br /&gt;
*'''Study list''': shows studies for the currently selected patient(s).  Multiple studies can be selected.&lt;br /&gt;
*'''Series list''' shows list of series (images, structure sets, segmentations, registration objects, etc.) available for selected studies.&lt;br /&gt;
*'''Search boxes''' Each patient/study/series can be filtered by typing in these fields.&lt;br /&gt;
*'''Examine button''' Runs each of the DICOM Plugins on the currently selected series and offers the result in the Load Options table.&lt;br /&gt;
*'''Plugin options''' (appears when ''Advanced'' checkbox is checked): you can choose which plugins will be allowed to examine the selected series for loading.&lt;br /&gt;
*'''Loadables list''' displays all possible interpretations of the selected series by the selected plugins.  The plugin that most likely interprets the series correctly, is selected by default.  You can override the defaults if you want to load the data in a different way. There will not always be a one-to-one mapping of selected series to list of loadable items.&lt;br /&gt;
*'''Load''' click this to load currently selected loadables into slicer.&lt;br /&gt;
*'''Metadata''' click this button to see metadata stored in file headers of selected series.&lt;br /&gt;
&lt;br /&gt;
==DICOM export==&lt;br /&gt;
&lt;br /&gt;
===How to export data from the Slicer scene to DICOM files===&lt;br /&gt;
* Open Data module, go to Subject Hierarchy tab (it is the tab shown by default)&lt;br /&gt;
* Make sure the data nodes that you want to export are in a DICOM-compliant hierarchy: parent of the data node is a Study, parent of the study is a Subject. To create a hierarchy, right-click in an empty area of the tree, select &amp;quot;Create new subject&amp;quot;, then right-click on the newly created subject and select &amp;quot;Create child study&amp;quot;, then drag-and-drop your data nodes under this study.&lt;br /&gt;
* Right-click on the data node to be exported and click &amp;quot;Export to DICOM...&amp;quot; to display DICOM export window (you can also show it by clicking &amp;quot;Export&amp;quot; button in the toolbar of DICOM browser module)&lt;br /&gt;
* Choose Output folder: By default, files are written into the folder where Slicer DICOM database is located. &lt;br /&gt;
* Click Export button: Export may take a few minutes. In case of error, the message is displayed in red on the left side of the dialog in the line of the &amp;quot;Save tags on export&amp;quot; checkbox.&lt;br /&gt;
&lt;br /&gt;
This workflow is also explained in a 2-minute [https://youtu.be/nzWf4xHy1BM video tutorial]&lt;br /&gt;
&lt;br /&gt;
===Advanced options===&lt;br /&gt;
* DICOM export window can be also opened from the DICOM browser, by clicking &amp;quot;Export&amp;quot; button in the toolbar&lt;br /&gt;
* Export mode:&lt;br /&gt;
** Export series: export one or more selected series, to be viewed on a standard DICOM-compliant viewer&lt;br /&gt;
** Export entire scene: save the entire Slicer scene into a DICOM secondary capture file; the content can be stored on a DICOM archival system but can only be edited in Slicer&lt;br /&gt;
* Export type: Once the user selected a node, the DICOM plugins generate exportables for the series they can export. The list of the results appear in this section, grouped by plugin. The confidence number will be the average of the confidence numbers for the individual series for that plugin.&lt;br /&gt;
* Editing DICOM tags:&lt;br /&gt;
** DICOM tag editor consists of a list of tables. Tables for the common tags for the patient and study on the top, and the tags for the individual series below them (see image about tag editor below)&lt;br /&gt;
** &amp;quot;Tags&amp;quot; in the displayed table are not written directly to DICOM tags, they are just used by the DICOM plugins to fill DICOM tags in the exported files. This allows much more flexibility and DICOM plugins can auto-populate some information and plugins can expose other export options in this list (e.g. compression, naming convention).&lt;br /&gt;
** Save tags to scene: Checkbox to allow saving the tags back to the MRML nodes as attributes.&lt;br /&gt;
* Import exported data: if checked, the exported files are added to Slicer's DICOM database.&lt;br /&gt;
* The Edit-&amp;gt;Preferences-&amp;gt;DICOM page can be used to select options&lt;br /&gt;
** Generic&lt;br /&gt;
*** Load referenced series will give you the option of easily loading, for example, the master volume of a segmentation when you open the segmentation.  This can also be made to happen automatically.&lt;br /&gt;
** Scalar Volume&lt;br /&gt;
*** You can choose what back-end library to use (currently GDCM, DCMTK, or GDCM with DCMTK fallback with the last option being the default.  This is provided in case some data is unsupported by one library or the other.&lt;br /&gt;
*** Acquisition geometry regularization option supports the creation of a nonlinear transform that corrects for things like missing slices or gantry tilt in the acquisition&lt;br /&gt;
*** Autoloading subseries by time is an option break up some 4D acquisitions into individual volume, but is optional since some volumes are also acquired in time unites and should not be split.&lt;br /&gt;
&lt;br /&gt;
=Slicer DICOM Database=&lt;br /&gt;
&lt;br /&gt;
To organize the data and avoid redundant calculations, Slicer keeps a DICOM Database of information about the DICOM data.  You can have multiple databases on your computer at a time, and switch between them if, for example, they include data from different research projects.  Each database is simply a directory on your local disk that has a few [http://sqlite.org/ SQLite] files and subdirectories to store image data.  Don't manually modify the contents of these directories.  DICOM data can enter the database either through manual import or via a DICOM network transfer.  Modules may also populate the DICOM database with the results of computation.&lt;br /&gt;
&lt;br /&gt;
You can change location where the database is stored by opening the DICOM module, clicking the double arrow (&amp;gt;&amp;gt;) button on the right side of the menu bar, click the button next to &amp;quot;LocalDatabase&amp;quot; label, and select the new location (an empty folder).&lt;br /&gt;
&lt;br /&gt;
Note that the DICOM standard does not specify how files will be organized on disk, so if you have DICOM data from a CDROM or otherwise transferred from a scanner, you cannot in general tell anything about the contents from the file or directory names.  However once the data is imported to the database, it will be organized according the the DICOM standard Patient/Study/Series hierarchy.&lt;br /&gt;
&lt;br /&gt;
=DICOM Loading/Saving and Plugins=&lt;br /&gt;
&lt;br /&gt;
A main function of the DICOM module is to map from ''acquisition'' data organization into ''volume'' representation.  That is, DICOM files typically describe attributes of the image capture, like the sequence of locations of the table during CT acquisition, while Slicer operates on image volumes of regularly spaced pixels.  If, for example, the speed of the table motion is not consistent during an acquisition (which can be the case for some contrast 'bolus chasing' scans, Slicer's DICOM module will warn the user that the acquisition geometry is not consistent and the user should use caution when interpreting analysis results such as measurements. &lt;br /&gt;
&lt;br /&gt;
From a developer perspective, the DICOM module exposes a plug-in architecture that allows acquisition-specific and modality-specific interpretation of DICOM data.  From a user perspective this means that often Slicer will be able to suggest multiple ways of interpreting the data (such as reading DICOM files as a [[Documentation/{{documentation/version}}#Diffusion|Diffusion]] dataset or as a scalar volume.  When it is computable by examining the files, the DICOM module will select the most likely interpretation option by default.  As of this release, standard plugins include scalar volumes and diffusion volumes, while extensions are available for segmentation objects, RT data, and PET/CT data.  More plugins are expected for future versions.  It is a long-term objective to be able to represent most, if not all, of Slicer's data in the corresponding DICOM data objects as the standard evolves to support them.&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
&lt;br /&gt;
See the [[Documentation/{{documentation/version}}/FAQ/DICOM|Slicer DICOM FAQ]] for troubleshooting tips.&lt;br /&gt;
&lt;br /&gt;
==How to obtain DICOM metadata==&lt;br /&gt;
&lt;br /&gt;
* Open DICOM browser&lt;br /&gt;
* Select the data set that you want to load by clicking on a series (item in the listbox in the bottom)&lt;br /&gt;
* Click Metadata button&lt;br /&gt;
* Click Copy Metadata button&lt;br /&gt;
* Paste the copied text to any text editor&lt;br /&gt;
* '''Remove patient name, birthdate, ID, and all other patient identifiable information'''&lt;br /&gt;
* Copy-paste remaining text to Slicer forum post or email&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Similar modules ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar modules}}&lt;br /&gt;
* [[Documentation/{{documentation/version}}/SlicerApplication/LoadingData|Loading Data]] Can read scalar volume DICOM data, bypassing the database.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|Reporting Extension]] reads and writes DICOM Segmentation Objects (label maps).&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|SlicerRT]] reads and write DICOM Radiation Therapy Objects and provides tools for processing them.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|LongitudinalPETCT]] reads all PET/CT studies for a selected patient and provides tools for tracking metabolic activity detected by PET tracers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- References ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
See the [http://commontk.org CTK web site] for more information on the internals of the DICOM implementation.  This tool uses the [http://dicom.offis.de DCMTK DICOM library].&lt;br /&gt;
&lt;br /&gt;
=== Useful links ===&lt;br /&gt;
* The DICOM Homepage: http://dicom.nema.org/&lt;br /&gt;
* DICOM on wikipedia: http://en.wikipedia.org/wiki/DICOM&lt;br /&gt;
* Clean and simple DICOM tag browser: http://dicom.innolitics.com&lt;br /&gt;
* A useful tag lookup site: http://dicomlookup.com/&lt;br /&gt;
* A hyperlinked version of the standard: http://dabsoft.ch/dicom/&lt;br /&gt;
* A handy book about DICOM: http://www.amazon.com/Digital-Imaging-Communications-Medicine-DICOM/dp/3642108490/ref=dp_ob_title_bk&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
&lt;br /&gt;
[[Image:DICOM-architecture.png|thumb|580px|DICOM module architecture.]]&lt;br /&gt;
&lt;br /&gt;
The overall DICOM Implementation in 3D Slicer consists of two main bodies of code embedded within the application.  [http://commontk.org CTK] code is responsible for the implementation of the DICOM database and networking layer.  The CTK code is implemented C++ and follows the Qt style.  The DICOM Module exposes this functionality to slicer users, and provides hooks through which other module can register DICOM Plugins to handle the conversion of specific DICOM data objects into the corresponding MRML representation.  Once the data is in slicer, it can be operated on via the standard slicer mechanisms.&lt;br /&gt;
&lt;br /&gt;
==== Customize table columns in DICOM browser ====&lt;br /&gt;
&lt;br /&gt;
Columns in the browser can be renamed, reordered, shown/hidden, etc. An example snippet to customize the browser can be found in the [https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Customize_table_columns_in_DICOM_browser script repository]&lt;br /&gt;
&lt;br /&gt;
The changes made like this are written into the database (ColumnDisplayProperties table), so the column customizations can be done only once per database.&lt;br /&gt;
&lt;br /&gt;
==== Customize DICOM browser table content ====&lt;br /&gt;
&lt;br /&gt;
The way the raw DICOM tags are represented in the fields of the DICOM tables is determined by the displayed field generator rules. These rules are subclasses of the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/master/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h ctkDICOMDisplayedFieldGeneratorAbstractRule class], and need to be [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/master/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.h#L70 registered] to the displayed field generator in order to take part of the generation.&lt;br /&gt;
&lt;br /&gt;
The fields are [https://github.com/commontk/CTK/9c2af28e84da1abb986036317d75009d4c149923/blob/master/Libs/DICOM/Core/ctkDICOMDatabase.h#L207 updated] when 1) files are added to the database or 2) the database schema is updated (happens when opening an older database with a newer Slicer). In the [https://github.com/commontk/CTK/tree/9c2af28e84da1abb986036317d75009d4c149923 current] version only those files (i.e. instances) are processed for which the displayed fields have never been generated.&lt;br /&gt;
&lt;br /&gt;
When updating the displayed fields, every rule defines the fields it is responsible for using the cached DICOM tags in the database. Tags can be requested to be cached in the rules from the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h#L63 getRequiredDICOMTags] function. New field values are generated by the rules instance by instance. First, the getDisplayedFieldsForInstance function is called for each rule in which the custom values are generated from the raw tags, then the results are merged by calling mergeDisplayedFieldsForInstance for all the rules. Each field can be requested to be merged with &amp;quot;expect same value&amp;quot;, which uses the only non-empty value and throws a warning if conflicting values are encountered, or with &amp;quot;concatenate&amp;quot;, which simply concatenates the displayed field values together.&lt;br /&gt;
&lt;br /&gt;
The existing two rules can be used as examples: the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.cpp default] and the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.cpp RT] rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DICOM&amp;diff=61029</id>
		<title>Documentation/Nightly/Modules/DICOM</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DICOM&amp;diff=61029"/>
		<updated>2019-04-16T16:08:42Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Customize table columns in DICOM browser */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
{{Clear|right}}{{TOC right}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
:'''Author(s)/Contributor(s):''' Steve Pieper (Isomics Inc.), Michael Onken (Offis), Marco Nolden (DFKZ), Julien Finet (Kitware), Stephen Aylward (Kitware), Nicholas Herlambang (AZE), Alireza Mehrtash (BWH), Csaba Pinter (PerkLab, Queen's)&amp;lt;br&amp;gt;&lt;br /&gt;
: '''Acknowledgements:''' This work is part of the [http://www.na-mic.org/ National Alliance for Medical Image Computing] (NA-MIC), funded by the National Institutes of Health through the NIH Roadmap for Medical Research, Grant U54 EB005149, and by Quantitative Image Informatics for Cancer Research (QIICR) (U24 CA180918) &amp;lt;br&amp;gt;&lt;br /&gt;
: '''Contact:''' Steve Pieper, &amp;lt;email&amp;gt;pieper@bwh.harvard.edu&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|isomics}}|{{collaborator|longname|isomics}}&lt;br /&gt;
|{{collaborator|logo|namic}}|{{collaborator|longname|namic}}&lt;br /&gt;
|{{collaborator|logo|nac}}|{{collaborator|longname|nac}}&lt;br /&gt;
|{{collaborator|logo|ctk}}|{{collaborator|longname|ctk}}&lt;br /&gt;
|{{collaborator|logo|qiicr}}|{{collaborator|longname|qiicr}}&lt;br /&gt;
|Image:DICOM-OFFIS-logo.png|DICOM-OFFIS&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-description}}&lt;br /&gt;
&lt;br /&gt;
*A new DICOM infrastructure was put in place beginning with Slicer 4.0. &lt;br /&gt;
*DICOM data is stored in a local data base, which is based on SQLite.&lt;br /&gt;
*DICOM data can be imported from disk into this data base.&lt;br /&gt;
*DICOM data can be created from the scene contents and exported to DICOM files.&lt;br /&gt;
*DICOM data can be retrieved from a PACS system after proper configuration of Slicer.&lt;br /&gt;
*DICOM data can be loaded into Slicer from the local database. A graphical user interface with display of thumbnails is available for data selection.&lt;br /&gt;
*Plans for the near future include support for storing data from slicer into the data base and uploading data from the data base into a PACS system.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
This module is used for DICOM import and export.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Screenshots}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[image:DICOM Screenshot-1 1204-11-17-10-36.png|thumb|380px|DICOM module in use]]&lt;br /&gt;
|[[Image:Form_224.png|thumb|380px|DICOM Query dialog]]&lt;br /&gt;
|[[Image:DICOM Horizontal View 2014-11-17-09-35.png|thumb|380px|Horizontal table view]]&lt;br /&gt;
|}&lt;br /&gt;
{|&lt;br /&gt;
|[[Image:DICOM-3 2014-11-17-10-42.png‎|thumb|380px|DICOM Browser in Advanced Mode (Control plugins and access to load options)]]&lt;br /&gt;
|[[Image:DICOM4 2014-11-17-09-38.png|thumb|380px|DICOM Meta Data Browser (DICOM header viewer)]]&lt;br /&gt;
|[[Image:DICOM-5 2014-11-17-10-46.png|thumb|380px|More options (change local database directory and table display density)]]&lt;br /&gt;
|}&lt;br /&gt;
{|&lt;br /&gt;
|[[Image:20141103_DICOM_Export_Dialog.png|thumb|380px|DICOM Export Dialog]]&lt;br /&gt;
|[[Image:DICOM-Preferences.png|thumb|380px|DICOM Preferences]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=DICOM Concepts=&lt;br /&gt;
&lt;br /&gt;
DICOM is a widely used and sophisticated set of standards for digital radiology (see the [[#References|References]] section for more information).  Slicer provides support for a subset of DICOM functionality, with the particular features driven by the needs of clinical research.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=DICOM Organization=&lt;br /&gt;
&lt;br /&gt;
To organize the data and avoid redundant calculations, Slicer keeps a DICOM Database of information about the DICOM data.  You can have multiple databases on your computer at a time, and switch between them if, for example, they include data from different research projects.  Each database is simply a directory on your local disk that has a few [http://sqlite.org/ SQLite] files and subdirectories to store image data.  Don't manually modify the contents of these directories.  DICOM data can enter the database either through manual import or via a DICOM network transfer.  Modules may also populate the DICOM database with the results of computation.&lt;br /&gt;
&lt;br /&gt;
By right clicking on a Patient, Study, or Series, you can delete the entry from the DICOM database.  Note that to avoid accidental data loss, Slicer does not delete the corresponding image data files.&lt;br /&gt;
&lt;br /&gt;
By selecting a Study and right clicking to get a context menu, you can choose to Export data from Slicer into DICOM.  The metadata from the select study will be automatically filled in to the Export dialog and you can select a Slicer volume to export.  ''Note that you should exercise extreme caution when working with these files in clinical situations, since non-standard or incorrect DICOM files can interfere with clinical operations.''   You can also choose to encapsulate the current MRML scene (via an MRB file) inside a DICOM dataset, which will be treated as a DICOM Secondary Capture document (note that the export feature has not been widely tested and should be considered experimental). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=DICOM Data on the File System=&lt;br /&gt;
&lt;br /&gt;
The basic steps are as follows:&lt;br /&gt;
&lt;br /&gt;
*Click the Import button in the DICOM Browser&lt;br /&gt;
*Select the folder which contains the data&lt;br /&gt;
** Optionally select the Copy option so that the files are copied into the database directory.  Otherwise they will only be referenced in their original locaion.&lt;br /&gt;
&lt;br /&gt;
Note that the DICOM standard does not specify how files will be organized on disk, so if you have DICOM data from a CDROM or otherwise transferred from a scanner, you cannot in general tell anything about the contents from the file or directory names.  However once the data is imported to the database, it will be organized according the the DICOM standard Patient/Study/Series hierarchy.&lt;br /&gt;
&lt;br /&gt;
=Data in the scene=&lt;br /&gt;
&lt;br /&gt;
Data in the scene can be exported to the DICOM database:&lt;br /&gt;
* Select data to be exported in Subject Hierarchy module or initiate export from DICOM browser&lt;br /&gt;
* Edit tags for exportables&lt;br /&gt;
* Exported files are added to the DICOM database&lt;br /&gt;
&lt;br /&gt;
=DICOM Networking=&lt;br /&gt;
&lt;br /&gt;
DICOM is also a network communication standard.  Slicer supports a DICOM Listener, DICOM Query/Retrieve interface, and a DICOM Send option.  Note that in order to use these features, you must coordinate with the operators of the other DICOM nodes with which you wish to communicate.  For example, you must work out agreement on such topics as network ports and application entity titles (AE Titles).  Be aware that not all equipment supports all networking options, so configuration may be challenging and is often difficult to troubleshoot.&lt;br /&gt;
&lt;br /&gt;
== Connection Ports ==&lt;br /&gt;
Port 104 is the standard DICOM port. All ports below 1024 require root access on unix-like systems (Linux and Mac).  So you can run Slicer with the sudo command to be able to open the port for the DICOM Listener.  Or you can use a different port, like 11112.  You need to configure that on both sides of the connection.  You can only have one process at a time listening on a port so if you have a listener running the second one won't start up.  Also if something adverse happens (a crash) the port may be kept open an you need to either kill the storescp helper process (or just reboot the computer) to free the port.  Consult the [[documentation/{{documentation/version}}/SlicerApplication/ErrorLog|Error Log]] for diagnostic information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=DICOM Loading/Saving and Plugins=&lt;br /&gt;
&lt;br /&gt;
A main function of the DICOM module is to map from ''acquisition'' data organization into ''volume'' representation.  That is, DICOM files typically describe attributes of the image capture, like the sequence of locations of the table during CT acquisition, while Slicer operates on image volumes of regularly spaced pixels.  If, for example, the speed of the table motion is not consistent during an acquisition (which can be the case for some contrast 'bolus chasing' scans, Slicer's DICOM module will warn the user that the acquisition geometry is not consistent and the user should use caution when interpreting analysis results such as measurements. &lt;br /&gt;
&lt;br /&gt;
From a developer perspective, the DICOM module exposes a plug-in architecture that allows acquisition-specific and modality-specific interpretation of DICOM data.  From a user perspective this means that often Slicer will be able to suggest multiple ways of interpreting the data (such as reading DICOM files as a [[Documentation/{{documentation/version}}#Diffusion|Diffusion]] dataset or as a scalar volume.  When it is computable by examining the files, the DICOM module will select the most likely interpretation option by default.  As of this release, standard plugins include scalar volumes and diffusion volumes, while extensions are available for segmentation objects, RT data, and PET/CT data.  More plugins are expected for future versions.  It is a long-term objective to be able to represent most, if not all, of Slicer's data in the corresponding DICOM data objects as the standard evolves to support them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Tutorials ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
* See [http://www.na-mic.org/Wiki/index.php/RSNA_2012#3D_Interactive_Visualization_of_DICOM_images the RSNA 2012 Training on Visualization] for description and sample data (Direct link to [http://www.na-mic.org/Wiki/images/6/66/3DVisualizationDICOM_RadiologyApplications_SoniaPujol_RSNA2012.pdf slides as pdf]).&lt;br /&gt;
* [https://pieper.github.io/content/handson/#/DICOM This screen capture animation] shows how to import and load DICOM data (also includes inspection of the file contents, which is an optional step).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Panels ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels}}&lt;br /&gt;
&lt;br /&gt;
==DICOM import==&lt;br /&gt;
&lt;br /&gt;
Referring to the &amp;quot;DICOM in use&amp;quot; image in the top left of this page, the most important controls for day-to-day use are highlighted with gray callouts.  The are described here in the order you are likely to use them.&lt;br /&gt;
&lt;br /&gt;
*'''LocalDatabase''' (appears when ''&amp;gt;&amp;gt;'' button next to the menu bar is clicked): allows you to select a location on disk for Slicer's database of DICOM files. The application manages content of this folder (stores metadata and copy of imported DICOM files): do not manually copy any data into this folder.&lt;br /&gt;
*'''Import''' all DICOM files in the selected folder (including subfolders) will be parsed and basic information from file headers will be stored in Slicer's DICOM database. If enabled, then Slicer will make a copy of the imported files into the database folder.&lt;br /&gt;
*'''Patient list''' shows patients in the database. Studies available for the selected patient(s) are listed in study list. Multiple patients can be selected.&lt;br /&gt;
*'''Study list''': shows studies for the currently selected patient(s).  Multiple studies can be selected.&lt;br /&gt;
*'''Series list''' shows list of series (images, structure sets, segmentations, registration objects, etc.) available for selected studies.&lt;br /&gt;
*'''Search boxes''' Each patient/study/series can be filtered by typing in these fields.&lt;br /&gt;
*'''Examine button''' Runs each of the DICOM Plugins on the currently selected series and offers the result in the Load Options table.&lt;br /&gt;
*'''Plugin options''' (appears when ''Advanced'' checkbox is checked): you can choose which plugins will be allowed to examine the selected series for loading.&lt;br /&gt;
*'''Loadables list''' displays all possible interpretations of the selected series by the selected plugins.  The plugin that most likely interprets the series correctly, is selected by default.  You can override the defaults if you want to load the data in a different way. There will not always be a one-to-one mapping of selected series to list of loadable items.&lt;br /&gt;
*'''Load''' click this to load currently selected loadables into slicer.&lt;br /&gt;
*'''Metadata''' click this button to see metadata stored in file headers of selected series.&lt;br /&gt;
&lt;br /&gt;
==DICOM export==&lt;br /&gt;
&lt;br /&gt;
===How to export data from the Slicer scene to DICOM files===&lt;br /&gt;
* Open Data module, go to Subject Hierarchy tab (it is the tab shown by default)&lt;br /&gt;
* Make sure the data nodes that you want to export are in a DICOM-compliant hierarchy: parent of the data node is a Study, parent of the study is a Subject. To create a hierarchy, right-click in an empty area of the tree, select &amp;quot;Create new subject&amp;quot;, then right-click on the newly created subject and select &amp;quot;Create child study&amp;quot;, then drag-and-drop your data nodes under this study.&lt;br /&gt;
* Right-click on the data node to be exported and click &amp;quot;Export to DICOM...&amp;quot; to display DICOM export window (you can also show it by clicking &amp;quot;Export&amp;quot; button in the toolbar of DICOM browser module)&lt;br /&gt;
* Choose Output folder: By default, files are written into the folder where Slicer DICOM database is located. &lt;br /&gt;
* Click Export button: Export may take a few minutes. In case of error, the message is displayed in red on the left side of the dialog in the line of the &amp;quot;Save tags on export&amp;quot; checkbox.&lt;br /&gt;
&lt;br /&gt;
This workflow is also explained in a 2-minute [https://youtu.be/nzWf4xHy1BM video tutorial]&lt;br /&gt;
&lt;br /&gt;
===Advanced options===&lt;br /&gt;
* DICOM export window can be also opened from the DICOM browser, by clicking &amp;quot;Export&amp;quot; button in the toolbar&lt;br /&gt;
* Export mode:&lt;br /&gt;
** Export series: export one or more selected series, to be viewed on a standard DICOM-compliant viewer&lt;br /&gt;
** Export entire scene: save the entire Slicer scene into a DICOM secondary capture file; the content can be stored on a DICOM archival system but can only be edited in Slicer&lt;br /&gt;
* Export type: Once the user selected a node, the DICOM plugins generate exportables for the series they can export. The list of the results appear in this section, grouped by plugin. The confidence number will be the average of the confidence numbers for the individual series for that plugin.&lt;br /&gt;
* Editing DICOM tags:&lt;br /&gt;
** DICOM tag editor consists of a list of tables. Tables for the common tags for the patient and study on the top, and the tags for the individual series below them (see image about tag editor below)&lt;br /&gt;
** &amp;quot;Tags&amp;quot; in the displayed table are not written directly to DICOM tags, they are just used by the DICOM plugins to fill DICOM tags in the exported files. This allows much more flexibility and DICOM plugins can auto-populate some information and plugins can expose other export options in this list (e.g. compression, naming convention).&lt;br /&gt;
** Save tags to scene: Checkbox to allow saving the tags back to the MRML nodes as attributes.&lt;br /&gt;
* Import exported data: if checked, the exported files are added to Slicer's DICOM database.&lt;br /&gt;
* The Edit-&amp;gt;Preferences-&amp;gt;DICOM page can be used to select options&lt;br /&gt;
** Generic&lt;br /&gt;
*** Load referenced series will give you the option of easily loading, for example, the master volume of a segmentation when you open the segmentation.  This can also be made to happen automatically.&lt;br /&gt;
** Scalar Volume&lt;br /&gt;
*** You can choose what back-end library to use (currently GDCM, DCMTK, or GDCM with DCMTK fallback with the last option being the default.  This is provided in case some data is unsupported by one library or the other.&lt;br /&gt;
*** Acquisition geometry regularization option supports the creation of a nonlinear transform that corrects for things like missing slices or gantry tilt in the acquisition&lt;br /&gt;
*** Autoloading subseries by time is an option break up some 4D acquisitions into individual volume, but is optional since some volumes are also acquired in time unites and should not be split.&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
&lt;br /&gt;
==How to obtain DICOM metadata==&lt;br /&gt;
&lt;br /&gt;
* Open DICOM browser&lt;br /&gt;
* Select the data set that you want to load by clicking on a series (item in the listbox in the bottom)&lt;br /&gt;
* Click Metadata button&lt;br /&gt;
* Click Copy Metadata button&lt;br /&gt;
* Paste the copied text to any text editor&lt;br /&gt;
* '''Remove patient name, birthdate, ID, and all other patient identifiable information'''&lt;br /&gt;
* Copy-paste remaining text to Slicer forum post or email&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Similar modules ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar modules}}&lt;br /&gt;
* [[Documentation/{{documentation/version}}/SlicerApplication/LoadingData|Loading Data]] Can read scalar volume DICOM data, bypassing the database.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|Reporting Extension]] reads and writes DICOM Segmentation Objects (label maps).&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|SlicerRT]] reads and write DICOM Radiation Therapy Objects and provides tools for processing them.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|LongitudinalPETCT]] reads all PET/CT studies for a selected patient and provides tools for tracking metabolic activity detected by PET tracers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- References ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
See the [http://commontk.org CTK web site] for more information on the internals of the DICOM implementation.  This tool uses the [http://dicom.offis.de DCMTK DICOM library].&lt;br /&gt;
&lt;br /&gt;
=== Useful links ===&lt;br /&gt;
* See the [[Documentation/{{documentation/version}}/FAQ/DICOM|Slicer DICOM FAQ]]&lt;br /&gt;
* The DICOM Homepage: http://dicom.nema.org/&lt;br /&gt;
* DICOM on wikipedia: http://en.wikipedia.org/wiki/DICOM&lt;br /&gt;
* Clean and simple DICOM tag browser: http://dicom.innolitics.com&lt;br /&gt;
* A useful tag lookup site: http://dicomlookup.com/&lt;br /&gt;
* A hyperlinked version of the standard: http://dabsoft.ch/dicom/&lt;br /&gt;
* A handy book about DICOM: http://www.amazon.com/Digital-Imaging-Communications-Medicine-DICOM/dp/3642108490/ref=dp_ob_title_bk&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:DICOM-architecture.png|thumb|580px|DICOM module architecture.]]&lt;br /&gt;
&lt;br /&gt;
The overall DICOM Implementation in 3D Slicer consists of two main bodies of code embedded within the application.  [http://commontk.org CTK] code is responsible for the implementation of the DICOM database and networking layer.  The CTK code is implemented C++ and follows the Qt style.  The DICOM Module exposes this functionality to slicer users, and provides hooks through which other module can register DICOM Plugins to handle the conversion of specific DICOM data objects into the corresponding MRML representation.  Once the data is in slicer, it can be operated on via the standard slicer mechanisms.&lt;br /&gt;
&lt;br /&gt;
==== Customize table columns in DICOM browser ====&lt;br /&gt;
&lt;br /&gt;
Columns in the browser can be renamed, reordered, shown/hidden, etc. An example snippet to customize the browser can be found in the [https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Customize_table_columns_in_DICOM_browser script repository]&lt;br /&gt;
&lt;br /&gt;
The changes made like this are written into the database (ColumnDisplayProperties table), so the column customizations can be done only once per database.&lt;br /&gt;
&lt;br /&gt;
==== Customize DICOM browser table content ====&lt;br /&gt;
&lt;br /&gt;
The way the raw DICOM tags are represented in the fields of the DICOM tables is determined by the displayed field generator rules. These rules are subclasses of the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/master/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h ctkDICOMDisplayedFieldGeneratorAbstractRule class], and need to be [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/master/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.h#L70 registered] to the displayed field generator in order to take part of the generation.&lt;br /&gt;
&lt;br /&gt;
The fields are [https://github.com/commontk/CTK/9c2af28e84da1abb986036317d75009d4c149923/blob/master/Libs/DICOM/Core/ctkDICOMDatabase.h#L207 updated] when 1) files are added to the database or 2) the database schema is updated (happens when opening an older database with a newer Slicer). In the [https://github.com/commontk/CTK/tree/9c2af28e84da1abb986036317d75009d4c149923 current] version only those files (i.e. instances) are processed for which the displayed fields have never been generated.&lt;br /&gt;
&lt;br /&gt;
When updating the displayed fields, every rule defines the fields it is responsible for using the cached DICOM tags in the database. Tags can be requested to be cached in the rules from the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h#L63 getRequiredDICOMTags] function. New field values are generated by the rules instance by instance. First, the getDisplayedFieldsForInstance function is called for each rule in which the custom values are generated from the raw tags, then the results are merged by calling mergeDisplayedFieldsForInstance for all the rules. Each field can requested to be merged with &amp;quot;expect same value&amp;quot;, which uses the only non-empty value and throws a warning if conflicting values are encountered, or with &amp;quot;concatenate&amp;quot;, which simply concatenates the displayed field values together.&lt;br /&gt;
&lt;br /&gt;
The existing two rules can be used as examples: the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.cpp default] and the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.cpp RT] rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61028</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61028"/>
		<updated>2019-04-16T16:07:17Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Customize table columns in DICOM browser */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=&lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the [[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
* [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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
* [https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
* [https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
* [https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
* Capture the full Slicer screen and save it into a file&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
* Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
* Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
* How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
* How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[success, loadedVolumeNode] = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd', returnNode=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
=== How to access tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
=== How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
=== How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm', returnNode=True)[1]; slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Export a volume to DICOM file format ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Customize table columns in DICOM browser ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database() # Need to go this way, do not use slicer.dicomDatabase for this&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
* How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
  viewNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  viewNodes.UnRegister(slicer.mrmlScene)&lt;br /&gt;
  viewNodes.InitTraversal()&lt;br /&gt;
  viewNode = viewNodes.GetNextItemAsObject()&lt;br /&gt;
  while viewNode:&lt;br /&gt;
    viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
    viewNode = viewNodes.GetNextItemAsObject()&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
* How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(&amp;quot;ModifiedEvent&amp;quot;, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(&amp;quot;ModifiedEvent&amp;quot;, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Switching to markup fiducial placement mode ==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change markup fiducial display properties ==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a markup point position is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupsNodeModified(markupsNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
  if not sliceView:&lt;br /&gt;
    print(&amp;quot;Markup list was modified&amp;quot;)&lt;br /&gt;
    return&lt;br /&gt;
  movingMarkupIndex = markupsNode.GetAttribute('Markups.MovingMarkupIndex')&lt;br /&gt;
  pos = [0,0,0]&lt;br /&gt;
  markupsNode.GetNthFiducialPosition(int(movingMarkupIndex), pos)  &lt;br /&gt;
  print(&amp;quot;Markup {0} was moved in slice view {1} to {2}&amp;quot;.format(movingMarkupIndex, sliceView, pos))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(vtk.vtkCommand.ModifiedEvent, onMarkupsNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a transform is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a context menu when a markup point is clicked in a slice or 3D view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Example actions to perform&lt;br /&gt;
&lt;br /&gt;
def action1():&lt;br /&gt;
  print('Action1 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action2():&lt;br /&gt;
  print('Action2 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action3():&lt;br /&gt;
  print('Action3 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
# Clicked markup index is saved here to let the action&lt;br /&gt;
# know which markup needs to be manipulated.&lt;br /&gt;
slicer.clickedMarkupIndex = -1&lt;br /&gt;
  &lt;br /&gt;
# Create a simple menu&lt;br /&gt;
&lt;br /&gt;
menu = qt.QMenu()&lt;br /&gt;
a1 = qt.QAction(&amp;quot;Test&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a1.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a1)&lt;br /&gt;
a2 = qt.QAction(&amp;quot;Action&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a2.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a2)&lt;br /&gt;
a3 = qt.QAction(&amp;quot;Here&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a3.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a3)&lt;br /&gt;
&lt;br /&gt;
# Add observer to a markup fiducial list&lt;br /&gt;
&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_INT)&lt;br /&gt;
def markupClickedCallback(caller, eventId, callData):&lt;br /&gt;
  slicer.clickedMarkupIndex = callData&lt;br /&gt;
  print('Open menu on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
  menu.move(qt.QCursor.pos())&lt;br /&gt;
  menu.show()&lt;br /&gt;
&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
observerTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointClickedEvent, markupClickedCallback)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write markup positions to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write annotation ROI to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add a texture mapped plane to the scene as a model ==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# use dummy image data here&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
&lt;br /&gt;
scene = slicer.mrmlScene&lt;br /&gt;
&lt;br /&gt;
# Create model node&lt;br /&gt;
model = slicer.vtkMRMLModelNode()&lt;br /&gt;
model.SetScene(scene)&lt;br /&gt;
model.SetName(scene.GenerateUniqueName(&amp;quot;2DImageModel&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
model.SetAndObservePolyData(planeSource.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create display node&lt;br /&gt;
modelDisplay = slicer.vtkMRMLModelDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
modelDisplay.SetScene(scene)&lt;br /&gt;
scene.AddNode(modelDisplay)&lt;br /&gt;
model.SetAndObserveDisplayNodeID(modelDisplay.GetID())&lt;br /&gt;
&lt;br /&gt;
# Add to scene&lt;br /&gt;
modelDisplay.SetAndObserveTextureImageData(e.GetOutput())&lt;br /&gt;
scene.AddNode(model) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
transform = slicer.vtkMRMLLinearTransformNode()&lt;br /&gt;
scene.AddNode(transform) &lt;br /&gt;
model.SetAndObserveTransformNodeID(transform.GetID())&lt;br /&gt;
&lt;br /&gt;
vTransform = vtk.vtkTransform()&lt;br /&gt;
vTransform.Scale(50,50,50)&lt;br /&gt;
vTransform.RotateX(30)&lt;br /&gt;
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get scalar values at surface of a model ==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export entire scene as VRML ==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export model to Blender, including color by scalar ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export a tract (FiberBundle) to Blender, including color ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Iterate over tract (FiberBundle) streamline points ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a volume ==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a new volume ==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
thresholder = vtk.vtkImageThreshold()&lt;br /&gt;
thresholder.SetInputData(imageData)&lt;br /&gt;
thresholder.SetInValue(fillVoxelValue)&lt;br /&gt;
thresholder.SetOutValue(fillVoxelValue)&lt;br /&gt;
thresholder.Update()&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(thresholder.GetOutput())&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify voxels in a volume ==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in xrange(extent[4], extent[5]+1):&lt;br /&gt;
  for j in xrange(extent[2], extent[3]+1):&lt;br /&gt;
    for i in xrange(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.SetScalarComponentFromFloat(distortionVectorPosition_Ijk[0], distortionVectorPosition_Ijk[1], distortionVectorPosition_Ijk[2], 0, fillValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get volume voxel coordinates from markup fiducial RAS coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get markup fiducial RAS coordinates from volume voxel coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get the values of all voxels for a label value  ==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Access values in a DTI tensor volume ==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in xrange(extent[4], extent[5]+1):&lt;br /&gt;
  for j in xrange(extent[2], extent[3]+1):&lt;br /&gt;
    for i in xrange(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change window/level (brightness/contrast) or colormap of a volume ==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create custom color table ==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Manipulate a Slice View ==&lt;br /&gt;
&lt;br /&gt;
=== Change slice offset ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Change slice orientation ===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show slice views in 3D window ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reset field of view to show background volume maximized ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rotate slice views to volume plane ===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Iterate over current visible slice views, and set foreground and background images ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     sliceWidget = layoutManager.sliceWidget(sliceViewName)&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Synchronize zoom factor between slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.sliceNodes = [slicer.app.layoutManager().sliceWidget(viewName).mrmlSliceNode()&lt;br /&gt;
    for viewName in slicer.app.layoutManager().sliceViewNames()]&lt;br /&gt;
&lt;br /&gt;
slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
def sliceModified(caller, event):&lt;br /&gt;
    if slicer.updatingSliceNodes:&lt;br /&gt;
        # prevent infinite loop of slice node updates triggering slice node updates&lt;br /&gt;
        return&lt;br /&gt;
    slicer.updatingSliceNodes = True&lt;br /&gt;
    fov = caller.GetFieldOfView()&lt;br /&gt;
    for sliceNode in slicer.sliceNodes:&lt;br /&gt;
        if sliceNode != caller:&lt;br /&gt;
            sliceNode.SetFieldOfView(*fov)&lt;br /&gt;
    slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
for sliceNode in slicer.sliceNodes:&lt;br /&gt;
    sliceNode.AddObserver(vtk.vtkCommand.ModifiedEvent, sliceModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change opacity of foreground volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fit slice plane to markup fiducials ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.array([0,0,0])&lt;br /&gt;
p2 = np.array([0,0,0])&lt;br /&gt;
p3 = np.array([0,0,0])&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0, 0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a series of images from a Slice View ==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a new directory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a single MRB file ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a node to file ==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Center the 3D View on the Scene ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Display text in a 3D view or slice view ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide slice view annotations (DataProbe) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Turning off interpolation ==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Customize viewer layout ==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = (&amp;quot;&amp;lt;layout type=\&amp;quot;vertical\&amp;quot; split=\&amp;quot;true\&amp;quot; &amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;view class=\&amp;quot;vtkMRMLViewNode\&amp;quot; singletontag=\&amp;quot;1\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;    &amp;lt;property name=\&amp;quot;viewlabel\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;/view&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;/item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;view class=\&amp;quot;vtkMRMLSliceNode\&amp;quot; singletontag=\&amp;quot;Red\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;   &amp;lt;property name=\&amp;quot;orientation\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;   &amp;lt;property name=\&amp;quot;viewlabel\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;   &amp;lt;property name=\&amp;quot;viewcolor\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;/view&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;/item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;&amp;lt;/layout&amp;gt;&amp;quot;)&lt;br /&gt;
  &lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
== Customize keyboard shortcuts ==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Disable certain user interactions in slice views ==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change default slice view orientation ==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Set all slice views linked by default ==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set up custom units in slice view ruler ==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in xrange(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a slice view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceLayoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
sliceLayoutLabel = &amp;quot;T&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
sliceNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
sliceNode.SetName(sliceLayoutName)&lt;br /&gt;
sliceNode.SetLayoutName(sliceLayoutName)&lt;br /&gt;
sliceNode.SetLayoutLabel(sliceLayoutLabel)&lt;br /&gt;
sliceNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
sliceNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
sliceNode = slicer.mrmlScene.AddNode(sliceNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(sliceLayoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
sliceWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
sliceWidget.sliceViewName = sliceLayoutName&lt;br /&gt;
sliceWidget.sliceViewLabel = sliceLayoutLabel&lt;br /&gt;
c = sliceNode.GetLayoutColor()&lt;br /&gt;
sliceWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
sliceWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
sliceWidget.setMRMLSliceNode(sliceNode)&lt;br /&gt;
sliceWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Running an ITK filter in Python using SimpleITK ==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
* See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
* 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&lt;br /&gt;
&lt;br /&gt;
== Get current mouse coordinates in a slice view ==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get DataProbe text ==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get reformatted image from a slice viewer as numpy array ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print voxels.shape&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thick slab reconstruction and maximum/minimum intensity volume projections ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
== Change default file type for nodes (that have never been saved yet) ==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
== Change file type for saving for all volumes (with already existing storage nodes) ==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sequences ==&lt;br /&gt;
&lt;br /&gt;
=== Concatenate all sequences in the scene into a new sequence ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Segmentations ==&lt;br /&gt;
&lt;br /&gt;
=== Create a segmentation from a labelmap volume and display in 3D ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
=== Export labelmap node from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Export model nodes from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
exportedModelsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelHierarchyNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModelHierarchy(seg, exportedModelsNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show a segmentation in 3D ===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get a representation of a segment ===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = segmentationNode.GetBinaryLabelmapRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using default path and conversion parameters ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using custom path or conversion parameters ===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-convert using a modified conversion parameter ===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get centroid of a segment in world (RAS) coordinates ===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How to run segment editor effects from a script ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
* [https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
* [https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
* [https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
* [https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
== Accessing views, renderers, and cameras ==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide view controller bars ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change 3D view background color ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderer = renderWindow.GetRenderers().GetFirstRenderer()&lt;br /&gt;
renderer.SetBackground(1,0,0)&lt;br /&gt;
renderer.SetBackground2(1,0,0)&lt;br /&gt;
renderWindow.Render()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subject hierarchy == &lt;br /&gt;
==== Get the pseudo-singleton subject hierarchy node ====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
&lt;br /&gt;
==== Create subject hierarchy item ====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
==== Get subject hierarchy item ====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
==== Traverse children of a subject hierarchy item ====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in xrange(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
==== Manipulate subject hierarchy item ====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data nodes associated to items in a branch (or a leaf item)&lt;br /&gt;
  shNode.SetDisplayVisibilityForBranch(itemID, 1)&lt;br /&gt;
&lt;br /&gt;
==== Filter items in TreeView or ComboBox ====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
=== Listen to subject hierarchy item events ===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
== Plotting ==&lt;br /&gt;
&lt;br /&gt;
=== Create histogram plot of a volume ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Execute external applications ==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
=== Run process in default environment ===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DICOM&amp;diff=61027</id>
		<title>Documentation/Nightly/Modules/DICOM</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DICOM&amp;diff=61027"/>
		<updated>2019-04-16T16:04:39Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add developer info ablut DICOM browser customization&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
{{Clear|right}}{{TOC right}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
:'''Author(s)/Contributor(s):''' Steve Pieper (Isomics Inc.), Michael Onken (Offis), Marco Nolden (DFKZ), Julien Finet (Kitware), Stephen Aylward (Kitware), Nicholas Herlambang (AZE), Alireza Mehrtash (BWH), Csaba Pinter (PerkLab, Queen's)&amp;lt;br&amp;gt;&lt;br /&gt;
: '''Acknowledgements:''' This work is part of the [http://www.na-mic.org/ National Alliance for Medical Image Computing] (NA-MIC), funded by the National Institutes of Health through the NIH Roadmap for Medical Research, Grant U54 EB005149, and by Quantitative Image Informatics for Cancer Research (QIICR) (U24 CA180918) &amp;lt;br&amp;gt;&lt;br /&gt;
: '''Contact:''' Steve Pieper, &amp;lt;email&amp;gt;pieper@bwh.harvard.edu&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|isomics}}|{{collaborator|longname|isomics}}&lt;br /&gt;
|{{collaborator|logo|namic}}|{{collaborator|longname|namic}}&lt;br /&gt;
|{{collaborator|logo|nac}}|{{collaborator|longname|nac}}&lt;br /&gt;
|{{collaborator|logo|ctk}}|{{collaborator|longname|ctk}}&lt;br /&gt;
|{{collaborator|logo|qiicr}}|{{collaborator|longname|qiicr}}&lt;br /&gt;
|Image:DICOM-OFFIS-logo.png|DICOM-OFFIS&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-description}}&lt;br /&gt;
&lt;br /&gt;
*A new DICOM infrastructure was put in place beginning with Slicer 4.0. &lt;br /&gt;
*DICOM data is stored in a local data base, which is based on SQLite.&lt;br /&gt;
*DICOM data can be imported from disk into this data base.&lt;br /&gt;
*DICOM data can be created from the scene contents and exported to DICOM files.&lt;br /&gt;
*DICOM data can be retrieved from a PACS system after proper configuration of Slicer.&lt;br /&gt;
*DICOM data can be loaded into Slicer from the local database. A graphical user interface with display of thumbnails is available for data selection.&lt;br /&gt;
*Plans for the near future include support for storing data from slicer into the data base and uploading data from the data base into a PACS system.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
This module is used for DICOM import and export.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Screenshots}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[image:DICOM Screenshot-1 1204-11-17-10-36.png|thumb|380px|DICOM module in use]]&lt;br /&gt;
|[[Image:Form_224.png|thumb|380px|DICOM Query dialog]]&lt;br /&gt;
|[[Image:DICOM Horizontal View 2014-11-17-09-35.png|thumb|380px|Horizontal table view]]&lt;br /&gt;
|}&lt;br /&gt;
{|&lt;br /&gt;
|[[Image:DICOM-3 2014-11-17-10-42.png‎|thumb|380px|DICOM Browser in Advanced Mode (Control plugins and access to load options)]]&lt;br /&gt;
|[[Image:DICOM4 2014-11-17-09-38.png|thumb|380px|DICOM Meta Data Browser (DICOM header viewer)]]&lt;br /&gt;
|[[Image:DICOM-5 2014-11-17-10-46.png|thumb|380px|More options (change local database directory and table display density)]]&lt;br /&gt;
|}&lt;br /&gt;
{|&lt;br /&gt;
|[[Image:20141103_DICOM_Export_Dialog.png|thumb|380px|DICOM Export Dialog]]&lt;br /&gt;
|[[Image:DICOM-Preferences.png|thumb|380px|DICOM Preferences]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=DICOM Concepts=&lt;br /&gt;
&lt;br /&gt;
DICOM is a widely used and sophisticated set of standards for digital radiology (see the [[#References|References]] section for more information).  Slicer provides support for a subset of DICOM functionality, with the particular features driven by the needs of clinical research.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=DICOM Organization=&lt;br /&gt;
&lt;br /&gt;
To organize the data and avoid redundant calculations, Slicer keeps a DICOM Database of information about the DICOM data.  You can have multiple databases on your computer at a time, and switch between them if, for example, they include data from different research projects.  Each database is simply a directory on your local disk that has a few [http://sqlite.org/ SQLite] files and subdirectories to store image data.  Don't manually modify the contents of these directories.  DICOM data can enter the database either through manual import or via a DICOM network transfer.  Modules may also populate the DICOM database with the results of computation.&lt;br /&gt;
&lt;br /&gt;
By right clicking on a Patient, Study, or Series, you can delete the entry from the DICOM database.  Note that to avoid accidental data loss, Slicer does not delete the corresponding image data files.&lt;br /&gt;
&lt;br /&gt;
By selecting a Study and right clicking to get a context menu, you can choose to Export data from Slicer into DICOM.  The metadata from the select study will be automatically filled in to the Export dialog and you can select a Slicer volume to export.  ''Note that you should exercise extreme caution when working with these files in clinical situations, since non-standard or incorrect DICOM files can interfere with clinical operations.''   You can also choose to encapsulate the current MRML scene (via an MRB file) inside a DICOM dataset, which will be treated as a DICOM Secondary Capture document (note that the export feature has not been widely tested and should be considered experimental). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=DICOM Data on the File System=&lt;br /&gt;
&lt;br /&gt;
The basic steps are as follows:&lt;br /&gt;
&lt;br /&gt;
*Click the Import button in the DICOM Browser&lt;br /&gt;
*Select the folder which contains the data&lt;br /&gt;
** Optionally select the Copy option so that the files are copied into the database directory.  Otherwise they will only be referenced in their original locaion.&lt;br /&gt;
&lt;br /&gt;
Note that the DICOM standard does not specify how files will be organized on disk, so if you have DICOM data from a CDROM or otherwise transferred from a scanner, you cannot in general tell anything about the contents from the file or directory names.  However once the data is imported to the database, it will be organized according the the DICOM standard Patient/Study/Series hierarchy.&lt;br /&gt;
&lt;br /&gt;
=Data in the scene=&lt;br /&gt;
&lt;br /&gt;
Data in the scene can be exported to the DICOM database:&lt;br /&gt;
* Select data to be exported in Subject Hierarchy module or initiate export from DICOM browser&lt;br /&gt;
* Edit tags for exportables&lt;br /&gt;
* Exported files are added to the DICOM database&lt;br /&gt;
&lt;br /&gt;
=DICOM Networking=&lt;br /&gt;
&lt;br /&gt;
DICOM is also a network communication standard.  Slicer supports a DICOM Listener, DICOM Query/Retrieve interface, and a DICOM Send option.  Note that in order to use these features, you must coordinate with the operators of the other DICOM nodes with which you wish to communicate.  For example, you must work out agreement on such topics as network ports and application entity titles (AE Titles).  Be aware that not all equipment supports all networking options, so configuration may be challenging and is often difficult to troubleshoot.&lt;br /&gt;
&lt;br /&gt;
== Connection Ports ==&lt;br /&gt;
Port 104 is the standard DICOM port. All ports below 1024 require root access on unix-like systems (Linux and Mac).  So you can run Slicer with the sudo command to be able to open the port for the DICOM Listener.  Or you can use a different port, like 11112.  You need to configure that on both sides of the connection.  You can only have one process at a time listening on a port so if you have a listener running the second one won't start up.  Also if something adverse happens (a crash) the port may be kept open an you need to either kill the storescp helper process (or just reboot the computer) to free the port.  Consult the [[documentation/{{documentation/version}}/SlicerApplication/ErrorLog|Error Log]] for diagnostic information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=DICOM Loading/Saving and Plugins=&lt;br /&gt;
&lt;br /&gt;
A main function of the DICOM module is to map from ''acquisition'' data organization into ''volume'' representation.  That is, DICOM files typically describe attributes of the image capture, like the sequence of locations of the table during CT acquisition, while Slicer operates on image volumes of regularly spaced pixels.  If, for example, the speed of the table motion is not consistent during an acquisition (which can be the case for some contrast 'bolus chasing' scans, Slicer's DICOM module will warn the user that the acquisition geometry is not consistent and the user should use caution when interpreting analysis results such as measurements. &lt;br /&gt;
&lt;br /&gt;
From a developer perspective, the DICOM module exposes a plug-in architecture that allows acquisition-specific and modality-specific interpretation of DICOM data.  From a user perspective this means that often Slicer will be able to suggest multiple ways of interpreting the data (such as reading DICOM files as a [[Documentation/{{documentation/version}}#Diffusion|Diffusion]] dataset or as a scalar volume.  When it is computable by examining the files, the DICOM module will select the most likely interpretation option by default.  As of this release, standard plugins include scalar volumes and diffusion volumes, while extensions are available for segmentation objects, RT data, and PET/CT data.  More plugins are expected for future versions.  It is a long-term objective to be able to represent most, if not all, of Slicer's data in the corresponding DICOM data objects as the standard evolves to support them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Tutorials ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
* See [http://www.na-mic.org/Wiki/index.php/RSNA_2012#3D_Interactive_Visualization_of_DICOM_images the RSNA 2012 Training on Visualization] for description and sample data (Direct link to [http://www.na-mic.org/Wiki/images/6/66/3DVisualizationDICOM_RadiologyApplications_SoniaPujol_RSNA2012.pdf slides as pdf]).&lt;br /&gt;
* [https://pieper.github.io/content/handson/#/DICOM This screen capture animation] shows how to import and load DICOM data (also includes inspection of the file contents, which is an optional step).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Panels ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels}}&lt;br /&gt;
&lt;br /&gt;
==DICOM import==&lt;br /&gt;
&lt;br /&gt;
Referring to the &amp;quot;DICOM in use&amp;quot; image in the top left of this page, the most important controls for day-to-day use are highlighted with gray callouts.  The are described here in the order you are likely to use them.&lt;br /&gt;
&lt;br /&gt;
*'''LocalDatabase''' (appears when ''&amp;gt;&amp;gt;'' button next to the menu bar is clicked): allows you to select a location on disk for Slicer's database of DICOM files. The application manages content of this folder (stores metadata and copy of imported DICOM files): do not manually copy any data into this folder.&lt;br /&gt;
*'''Import''' all DICOM files in the selected folder (including subfolders) will be parsed and basic information from file headers will be stored in Slicer's DICOM database. If enabled, then Slicer will make a copy of the imported files into the database folder.&lt;br /&gt;
*'''Patient list''' shows patients in the database. Studies available for the selected patient(s) are listed in study list. Multiple patients can be selected.&lt;br /&gt;
*'''Study list''': shows studies for the currently selected patient(s).  Multiple studies can be selected.&lt;br /&gt;
*'''Series list''' shows list of series (images, structure sets, segmentations, registration objects, etc.) available for selected studies.&lt;br /&gt;
*'''Search boxes''' Each patient/study/series can be filtered by typing in these fields.&lt;br /&gt;
*'''Examine button''' Runs each of the DICOM Plugins on the currently selected series and offers the result in the Load Options table.&lt;br /&gt;
*'''Plugin options''' (appears when ''Advanced'' checkbox is checked): you can choose which plugins will be allowed to examine the selected series for loading.&lt;br /&gt;
*'''Loadables list''' displays all possible interpretations of the selected series by the selected plugins.  The plugin that most likely interprets the series correctly, is selected by default.  You can override the defaults if you want to load the data in a different way. There will not always be a one-to-one mapping of selected series to list of loadable items.&lt;br /&gt;
*'''Load''' click this to load currently selected loadables into slicer.&lt;br /&gt;
*'''Metadata''' click this button to see metadata stored in file headers of selected series.&lt;br /&gt;
&lt;br /&gt;
==DICOM export==&lt;br /&gt;
&lt;br /&gt;
===How to export data from the Slicer scene to DICOM files===&lt;br /&gt;
* Open Data module, go to Subject Hierarchy tab (it is the tab shown by default)&lt;br /&gt;
* Make sure the data nodes that you want to export are in a DICOM-compliant hierarchy: parent of the data node is a Study, parent of the study is a Subject. To create a hierarchy, right-click in an empty area of the tree, select &amp;quot;Create new subject&amp;quot;, then right-click on the newly created subject and select &amp;quot;Create child study&amp;quot;, then drag-and-drop your data nodes under this study.&lt;br /&gt;
* Right-click on the data node to be exported and click &amp;quot;Export to DICOM...&amp;quot; to display DICOM export window (you can also show it by clicking &amp;quot;Export&amp;quot; button in the toolbar of DICOM browser module)&lt;br /&gt;
* Choose Output folder: By default, files are written into the folder where Slicer DICOM database is located. &lt;br /&gt;
* Click Export button: Export may take a few minutes. In case of error, the message is displayed in red on the left side of the dialog in the line of the &amp;quot;Save tags on export&amp;quot; checkbox.&lt;br /&gt;
&lt;br /&gt;
This workflow is also explained in a 2-minute [https://youtu.be/nzWf4xHy1BM video tutorial]&lt;br /&gt;
&lt;br /&gt;
===Advanced options===&lt;br /&gt;
* DICOM export window can be also opened from the DICOM browser, by clicking &amp;quot;Export&amp;quot; button in the toolbar&lt;br /&gt;
* Export mode:&lt;br /&gt;
** Export series: export one or more selected series, to be viewed on a standard DICOM-compliant viewer&lt;br /&gt;
** Export entire scene: save the entire Slicer scene into a DICOM secondary capture file; the content can be stored on a DICOM archival system but can only be edited in Slicer&lt;br /&gt;
* Export type: Once the user selected a node, the DICOM plugins generate exportables for the series they can export. The list of the results appear in this section, grouped by plugin. The confidence number will be the average of the confidence numbers for the individual series for that plugin.&lt;br /&gt;
* Editing DICOM tags:&lt;br /&gt;
** DICOM tag editor consists of a list of tables. Tables for the common tags for the patient and study on the top, and the tags for the individual series below them (see image about tag editor below)&lt;br /&gt;
** &amp;quot;Tags&amp;quot; in the displayed table are not written directly to DICOM tags, they are just used by the DICOM plugins to fill DICOM tags in the exported files. This allows much more flexibility and DICOM plugins can auto-populate some information and plugins can expose other export options in this list (e.g. compression, naming convention).&lt;br /&gt;
** Save tags to scene: Checkbox to allow saving the tags back to the MRML nodes as attributes.&lt;br /&gt;
* Import exported data: if checked, the exported files are added to Slicer's DICOM database.&lt;br /&gt;
* The Edit-&amp;gt;Preferences-&amp;gt;DICOM page can be used to select options&lt;br /&gt;
** Generic&lt;br /&gt;
*** Load referenced series will give you the option of easily loading, for example, the master volume of a segmentation when you open the segmentation.  This can also be made to happen automatically.&lt;br /&gt;
** Scalar Volume&lt;br /&gt;
*** You can choose what back-end library to use (currently GDCM, DCMTK, or GDCM with DCMTK fallback with the last option being the default.  This is provided in case some data is unsupported by one library or the other.&lt;br /&gt;
*** Acquisition geometry regularization option supports the creation of a nonlinear transform that corrects for things like missing slices or gantry tilt in the acquisition&lt;br /&gt;
*** Autoloading subseries by time is an option break up some 4D acquisitions into individual volume, but is optional since some volumes are also acquired in time unites and should not be split.&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
&lt;br /&gt;
==How to obtain DICOM metadata==&lt;br /&gt;
&lt;br /&gt;
* Open DICOM browser&lt;br /&gt;
* Select the data set that you want to load by clicking on a series (item in the listbox in the bottom)&lt;br /&gt;
* Click Metadata button&lt;br /&gt;
* Click Copy Metadata button&lt;br /&gt;
* Paste the copied text to any text editor&lt;br /&gt;
* '''Remove patient name, birthdate, ID, and all other patient identifiable information'''&lt;br /&gt;
* Copy-paste remaining text to Slicer forum post or email&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Similar modules ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar modules}}&lt;br /&gt;
* [[Documentation/{{documentation/version}}/SlicerApplication/LoadingData|Loading Data]] Can read scalar volume DICOM data, bypassing the database.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|Reporting Extension]] reads and writes DICOM Segmentation Objects (label maps).&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|SlicerRT]] reads and write DICOM Radiation Therapy Objects and provides tools for processing them.&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Extensions/Reporting|LongitudinalPETCT]] reads all PET/CT studies for a selected patient and provides tools for tracking metabolic activity detected by PET tracers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- References ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
See the [http://commontk.org CTK web site] for more information on the internals of the DICOM implementation.  This tool uses the [http://dicom.offis.de DCMTK DICOM library].&lt;br /&gt;
&lt;br /&gt;
=== Useful links ===&lt;br /&gt;
* See the [[Documentation/{{documentation/version}}/FAQ/DICOM|Slicer DICOM FAQ]]&lt;br /&gt;
* The DICOM Homepage: http://dicom.nema.org/&lt;br /&gt;
* DICOM on wikipedia: http://en.wikipedia.org/wiki/DICOM&lt;br /&gt;
* Clean and simple DICOM tag browser: http://dicom.innolitics.com&lt;br /&gt;
* A useful tag lookup site: http://dicomlookup.com/&lt;br /&gt;
* A hyperlinked version of the standard: http://dabsoft.ch/dicom/&lt;br /&gt;
* A handy book about DICOM: http://www.amazon.com/Digital-Imaging-Communications-Medicine-DICOM/dp/3642108490/ref=dp_ob_title_bk&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:DICOM-architecture.png|thumb|580px|DICOM module architecture.]]&lt;br /&gt;
&lt;br /&gt;
The overall DICOM Implementation in 3D Slicer consists of two main bodies of code embedded within the application.  [http://commontk.org CTK] code is responsible for the implementation of the DICOM database and networking layer.  The CTK code is implemented C++ and follows the Qt style.  The DICOM Module exposes this functionality to slicer users, and provides hooks through which other module can register DICOM Plugins to handle the conversion of specific DICOM data objects into the corresponding MRML representation.  Once the data is in slicer, it can be operated on via the standard slicer mechanisms.&lt;br /&gt;
&lt;br /&gt;
==== Customize table columns in DICOM browser ====&lt;br /&gt;
&lt;br /&gt;
Columns in the browser can be renamed, reordered, shown/hidden, etc. An example snippet to customize the browser can be found in the [https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Customize_table_columns_in_DICOM_browser script repository]&lt;br /&gt;
&lt;br /&gt;
==== Customize DICOM browser table content ====&lt;br /&gt;
&lt;br /&gt;
The way the raw DICOM tags are represented in the fields of the DICOM tables is determined by the displayed field generator rules. These rules are subclasses of the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/master/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h ctkDICOMDisplayedFieldGeneratorAbstractRule class], and need to be [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/master/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.h#L70 registered] to the displayed field generator in order to take part of the generation.&lt;br /&gt;
&lt;br /&gt;
The fields are [https://github.com/commontk/CTK/9c2af28e84da1abb986036317d75009d4c149923/blob/master/Libs/DICOM/Core/ctkDICOMDatabase.h#L207 updated] when 1) files are added to the database or 2) the database schema is updated (happens when opening an older database with a newer Slicer). In the [https://github.com/commontk/CTK/tree/9c2af28e84da1abb986036317d75009d4c149923 current] version only those files (i.e. instances) are processed for which the displayed fields have never been generated.&lt;br /&gt;
&lt;br /&gt;
When updating the displayed fields, every rule defines the fields it is responsible for using the cached DICOM tags in the database. Tags can be requested to be cached in the rules from the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h#L63 getRequiredDICOMTags] function. New field values are generated by the rules instance by instance. First, the getDisplayedFieldsForInstance function is called for each rule in which the custom values are generated from the raw tags, then the results are merged by calling mergeDisplayedFieldsForInstance for all the rules. Each field can requested to be merged with &amp;quot;expect same value&amp;quot;, which uses the only non-empty value and throws a warning if conflicting values are encountered, or with &amp;quot;concatenate&amp;quot;, which simply concatenates the displayed field values together.&lt;br /&gt;
&lt;br /&gt;
The existing two rules can be used as examples: the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.cpp default] and the [https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.cpp RT] rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61026</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=61026"/>
		<updated>2019-04-16T15:13:20Z</updated>

		<summary type="html">&lt;p&gt;Pinter: /* Export a volume to DICOM file format */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=&lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the [[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
* [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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
* [https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
* [https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
* [https://github.com/lassoan/SlicerLineProfile/blob/master/LineProfile/LineProfile.py LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
* Capture the full Slicer screen and save it into a file&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
* Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
* Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
* How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
* How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[success, loadedVolumeNode] = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd', returnNode=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
=== How to access tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
=== How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
=== How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm', returnNode=True)[1]; slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Export a volume to DICOM file format ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Customize table columns in DICOM browser ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get browser and database&lt;br /&gt;
dicomBrowser = slicer.modules.dicom.widgetRepresentation().self().dicomBrowser&lt;br /&gt;
dicomDatabase = dicomBrowser.database() # Need to go this way, do not use slicer.dicomDatabase for this&lt;br /&gt;
# Apply customization on major changes&lt;br /&gt;
dicomBrowser.connect('databaseDirectoryChanged(QString)', self.customizeDicomTableColumns)&lt;br /&gt;
dicomDatabase.connect('schemaUpdated()', self.customizeDicomTableColumns)&lt;br /&gt;
&lt;br /&gt;
# Change column order&lt;br /&gt;
dicomDatabase.setWeightForField('Series', 'SeriesDescription', 7)&lt;br /&gt;
dicomDatabase.setWeightForField('Studies', 'StudyDescription', 6)&lt;br /&gt;
# Change column visibility&lt;br /&gt;
dicomDatabase.setVisibilityForField('Patients', 'PatientsBirthDate', False)&lt;br /&gt;
# Change column name&lt;br /&gt;
dicomDatabase.setDisplayedNameForField('Series', 'DisplayedCount', 'Number of images')&lt;br /&gt;
# Customize table manager in DICOM browser&lt;br /&gt;
dicomTableManager = dicomBrowser.dicomTableManager()&lt;br /&gt;
dicomTableManager.selectionMode = qt.QAbstractItemView.SingleSelection&lt;br /&gt;
dicomTableManager.autoSelectSeries = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
* How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
  viewNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  viewNodes.UnRegister(slicer.mrmlScene)&lt;br /&gt;
  viewNodes.InitTraversal()&lt;br /&gt;
  viewNode = viewNodes.GetNextItemAsObject()&lt;br /&gt;
  while viewNode:&lt;br /&gt;
    viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
    viewNode = viewNodes.GetNextItemAsObject()&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
* How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(&amp;quot;ModifiedEvent&amp;quot;, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(&amp;quot;ModifiedEvent&amp;quot;, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Switching to markup fiducial placement mode ==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, ''qSlicerMarkupsPlaceWidget'' widget can be used to initiate markup placement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Temporary markups node&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def placementModeChanged(active):&lt;br /&gt;
  print(&amp;quot;Placement: &amp;quot; +(&amp;quot;active&amp;quot; if active else &amp;quot;inactive&amp;quot;))&lt;br /&gt;
  # You can inspect what is in the markups node here, delete the temporary markup node, etc.&lt;br /&gt;
&lt;br /&gt;
# Create and set up widget that contains a single &amp;quot;place markup&amp;quot; button. The widget can be placed in the module GUI.&lt;br /&gt;
placeWidget = slicer.qSlicerMarkupsPlaceWidget()&lt;br /&gt;
placeWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
placeWidget.setCurrentNode(markupsNode)&lt;br /&gt;
placeWidget.buttonsVisible=False&lt;br /&gt;
placeWidget.placeButton().show()&lt;br /&gt;
placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)', placementModeChanged)&lt;br /&gt;
placeWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change markup fiducial display properties ==&lt;br /&gt;
&lt;br /&gt;
Display properties are stored in display node(s) associated with the fiducial node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fiducialNode = getNode('F')&lt;br /&gt;
fiducialDisplayNode = fiducialNode.GetDisplayNode()&lt;br /&gt;
fiducialDisplayNode.SetVisibility(False) # Hide all points&lt;br /&gt;
fiducialDisplayNode.SetVisibility(True) # Show all points&lt;br /&gt;
fiducialDisplayNode.SetSelectedColor(1,1,0) # Set color to yellow&lt;br /&gt;
fiducialDisplayNode.SetViewNodeIDs([&amp;quot;vtkMRMLSliceNodeRed&amp;quot;, &amp;quot;vtkMRMLViewNode1&amp;quot;]) # Only show in red slice view and first 3D view&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a markup point position is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupsNodeModified(markupsNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
  if not sliceView:&lt;br /&gt;
    print(&amp;quot;Markup list was modified&amp;quot;)&lt;br /&gt;
    return&lt;br /&gt;
  movingMarkupIndex = markupsNode.GetAttribute('Markups.MovingMarkupIndex')&lt;br /&gt;
  pos = [0,0,0]&lt;br /&gt;
  markupsNode.GetNthFiducialPosition(int(movingMarkupIndex), pos)  &lt;br /&gt;
  print(&amp;quot;Markup {0} was moved in slice view {1} to {2}&amp;quot;.format(movingMarkupIndex, sliceView, pos))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(vtk.vtkCommand.ModifiedEvent, onMarkupsNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a transform is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a context menu when a markup point is clicked in a slice or 3D view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Example actions to perform&lt;br /&gt;
&lt;br /&gt;
def action1():&lt;br /&gt;
  print('Action1 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action2():&lt;br /&gt;
  print('Action2 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action3():&lt;br /&gt;
  print('Action3 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
# Clicked markup index is saved here to let the action&lt;br /&gt;
# know which markup needs to be manipulated.&lt;br /&gt;
slicer.clickedMarkupIndex = -1&lt;br /&gt;
  &lt;br /&gt;
# Create a simple menu&lt;br /&gt;
&lt;br /&gt;
menu = qt.QMenu()&lt;br /&gt;
a1 = qt.QAction(&amp;quot;Test&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a1.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a1)&lt;br /&gt;
a2 = qt.QAction(&amp;quot;Action&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a2.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a2)&lt;br /&gt;
a3 = qt.QAction(&amp;quot;Here&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a3.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a3)&lt;br /&gt;
&lt;br /&gt;
# Add observer to a markup fiducial list&lt;br /&gt;
&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_INT)&lt;br /&gt;
def markupClickedCallback(caller, eventId, callData):&lt;br /&gt;
  slicer.clickedMarkupIndex = callData&lt;br /&gt;
  print('Open menu on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
  menu.move(qt.QCursor.pos())&lt;br /&gt;
  menu.show()&lt;br /&gt;
&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
observerTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointClickedEvent, markupClickedCallback)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write markup positions to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupNode = getNode('F')&lt;br /&gt;
outputFileName = 'c:/tmp/test.json'&lt;br /&gt;
&lt;br /&gt;
# Get markup positions&lt;br /&gt;
data = []&lt;br /&gt;
for fidIndex in range(markupNode.GetNumberOfFiducials()):&lt;br /&gt;
  coords=[0,0,0]&lt;br /&gt;
  markupNode.GetNthFiducialPosition(fidIndex,coords)&lt;br /&gt;
  data.append({'label': markupNode.GetNthFiducialLabel(), 'position': coords})&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Write annotation ROI to JSON file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
roiNode = getNode('R')&lt;br /&gt;
outputFileName = &amp;quot;c:/tmp/test.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Get annotation ROI data&lt;br /&gt;
center = [0,0,0]&lt;br /&gt;
radius = [0,0,0]&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(0, center)&lt;br /&gt;
roiNode.GetControlPointWorldCoordinates(1, radius)&lt;br /&gt;
data = {'center': radius, 'radius': radius}&lt;br /&gt;
&lt;br /&gt;
# Write to json file&lt;br /&gt;
import json&lt;br /&gt;
with open(outputFileName, 'w') as outfile:&lt;br /&gt;
  json.dump(data, outfile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add a texture mapped plane to the scene as a model ==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# use dummy image data here&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
&lt;br /&gt;
scene = slicer.mrmlScene&lt;br /&gt;
&lt;br /&gt;
# Create model node&lt;br /&gt;
model = slicer.vtkMRMLModelNode()&lt;br /&gt;
model.SetScene(scene)&lt;br /&gt;
model.SetName(scene.GenerateUniqueName(&amp;quot;2DImageModel&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
model.SetAndObservePolyData(planeSource.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create display node&lt;br /&gt;
modelDisplay = slicer.vtkMRMLModelDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
modelDisplay.SetScene(scene)&lt;br /&gt;
scene.AddNode(modelDisplay)&lt;br /&gt;
model.SetAndObserveDisplayNodeID(modelDisplay.GetID())&lt;br /&gt;
&lt;br /&gt;
# Add to scene&lt;br /&gt;
modelDisplay.SetAndObserveTextureImageData(e.GetOutput())&lt;br /&gt;
scene.AddNode(model) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
transform = slicer.vtkMRMLLinearTransformNode()&lt;br /&gt;
scene.AddNode(transform) &lt;br /&gt;
model.SetAndObserveTransformNodeID(transform.GetID())&lt;br /&gt;
&lt;br /&gt;
vTransform = vtk.vtkTransform()&lt;br /&gt;
vTransform.Scale(50,50,50)&lt;br /&gt;
vTransform.RotateX(30)&lt;br /&gt;
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get scalar values at surface of a model ==&lt;br /&gt;
&lt;br /&gt;
The following script allows getting selected scalar value at a selected position of a model. Position can be selected by moving the mouse while holding down Shift key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode('sphere')&lt;br /&gt;
modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(&amp;quot;Normals&amp;quot;)&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
if not markupsNode:&lt;br /&gt;
  markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;,&amp;quot;F&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize&lt;br /&gt;
pointsLocator.SetDataSet(modelNode.GetPolyData())&lt;br /&gt;
pointsLocator.BuildLocator()&lt;br /&gt;
&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  if markupsNode.GetNumberOfFiducials() == 0:&lt;br /&gt;
    markupsNode.AddFiducial(*ras)&lt;br /&gt;
  else:&lt;br /&gt;
    markupsNode.SetNthFiducialPosition(0,*ras)&lt;br /&gt;
  closestPointId = pointsLocator.FindClosestPoint(ras)&lt;br /&gt;
  closestPointValue = modelPointValues.GetTuple(closestPointId)&lt;br /&gt;
  print(&amp;quot;RAS = &amp;quot; + repr(ras) + &amp;quot;    value = &amp;quot; + repr(closestPointValue))&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
observationId = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&lt;br /&gt;
# To stop printing of values run this:&lt;br /&gt;
# crosshairNode.RemoveObserver(observationId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export entire scene as VRML ==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export model to Blender, including color by scalar ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export a tract (FiberBundle) to Blender, including color ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Iterate over tract (FiberBundle) streamline points ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a volume ==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a new volume ==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
thresholder = vtk.vtkImageThreshold()&lt;br /&gt;
thresholder.SetInputData(imageData)&lt;br /&gt;
thresholder.SetInValue(fillVoxelValue)&lt;br /&gt;
thresholder.SetOutValue(fillVoxelValue)&lt;br /&gt;
thresholder.Update()&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(thresholder.GetOutput())&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify voxels in a volume ==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in xrange(extent[4], extent[5]+1):&lt;br /&gt;
  for j in xrange(extent[2], extent[3]+1):&lt;br /&gt;
    for i in xrange(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.SetScalarComponentFromFloat(distortionVectorPosition_Ijk[0], distortionVectorPosition_Ijk[1], distortionVectorPosition_Ijk[2], 0, fillValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get volume voxel coordinates from markup fiducial RAS coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get markup fiducial RAS coordinates from volume voxel coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get the values of all voxels for a label value  ==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Access values in a DTI tensor volume ==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in xrange(extent[4], extent[5]+1):&lt;br /&gt;
  for j in xrange(extent[2], extent[3]+1):&lt;br /&gt;
    for i in xrange(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change window/level (brightness/contrast) or colormap of a volume ==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create custom color table ==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Manipulate a Slice View ==&lt;br /&gt;
&lt;br /&gt;
=== Change slice offset ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Change slice orientation ===&lt;br /&gt;
&lt;br /&gt;
Get 'Red' slice node and rotate around X and Y axes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
sliceToRas = sliceNode.GetSliceToRAS()&lt;br /&gt;
transform=vtk.vtkTransform()&lt;br /&gt;
transform.SetMatrix(SliceToRAS)&lt;br /&gt;
transform.RotateX(20)&lt;br /&gt;
transform.RotateY(15)&lt;br /&gt;
sliceToRas.DeepCopy(transform.GetMatrix())&lt;br /&gt;
sliceNode.UpdateMatrices()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show slice views in 3D window ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reset field of view to show background volume maximized ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rotate slice views to volume plane ===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Iterate over current visible slice views, and set foreground and background images ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     sliceWidget = layoutManager.sliceWidget(sliceViewName)&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Synchronize zoom factor between slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.sliceNodes = [slicer.app.layoutManager().sliceWidget(viewName).mrmlSliceNode()&lt;br /&gt;
    for viewName in slicer.app.layoutManager().sliceViewNames()]&lt;br /&gt;
&lt;br /&gt;
slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
def sliceModified(caller, event):&lt;br /&gt;
    if slicer.updatingSliceNodes:&lt;br /&gt;
        # prevent infinite loop of slice node updates triggering slice node updates&lt;br /&gt;
        return&lt;br /&gt;
    slicer.updatingSliceNodes = True&lt;br /&gt;
    fov = caller.GetFieldOfView()&lt;br /&gt;
    for sliceNode in slicer.sliceNodes:&lt;br /&gt;
        if sliceNode != caller:&lt;br /&gt;
            sliceNode.SetFieldOfView(*fov)&lt;br /&gt;
    slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
for sliceNode in slicer.sliceNodes:&lt;br /&gt;
    sliceNode.AddObserver(vtk.vtkCommand.ModifiedEvent, sliceModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change opacity of foreground volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fit slice plane to markup fiducials ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.array([0,0,0])&lt;br /&gt;
p2 = np.array([0,0,0])&lt;br /&gt;
p3 = np.array([0,0,0])&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0, 0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a series of images from a Slice View ==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a new directory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a single MRB file ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a node to file ==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Center the 3D View on the Scene ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Display text in a 3D view or slice view ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide slice view annotations (DataProbe) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Turning off interpolation ==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Customize viewer layout ==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = (&amp;quot;&amp;lt;layout type=\&amp;quot;vertical\&amp;quot; split=\&amp;quot;true\&amp;quot; &amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;view class=\&amp;quot;vtkMRMLViewNode\&amp;quot; singletontag=\&amp;quot;1\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;    &amp;lt;property name=\&amp;quot;viewlabel\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;/view&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;/item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;view class=\&amp;quot;vtkMRMLSliceNode\&amp;quot; singletontag=\&amp;quot;Red\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;   &amp;lt;property name=\&amp;quot;orientation\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;   &amp;lt;property name=\&amp;quot;viewlabel\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;   &amp;lt;property name=\&amp;quot;viewcolor\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;/view&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;/item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;&amp;lt;/layout&amp;gt;&amp;quot;)&lt;br /&gt;
  &lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
== Customize keyboard shortcuts ==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Disable certain user interactions in slice views ==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change default slice view orientation ==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Set all slice views linked by default ==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set up custom units in slice view ruler ==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in xrange(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a slice view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceLayoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
sliceLayoutLabel = &amp;quot;T&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
sliceNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
sliceNode.SetName(sliceLayoutName)&lt;br /&gt;
sliceNode.SetLayoutName(sliceLayoutName)&lt;br /&gt;
sliceNode.SetLayoutLabel(sliceLayoutLabel)&lt;br /&gt;
sliceNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
sliceNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
sliceNode = slicer.mrmlScene.AddNode(sliceNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(sliceLayoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
sliceWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
sliceWidget.sliceViewName = sliceLayoutName&lt;br /&gt;
sliceWidget.sliceViewLabel = sliceLayoutLabel&lt;br /&gt;
c = sliceNode.GetLayoutColor()&lt;br /&gt;
sliceWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
sliceWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
sliceWidget.setMRMLSliceNode(sliceNode)&lt;br /&gt;
sliceWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Running an ITK filter in Python using SimpleITK ==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SampleData&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
&lt;br /&gt;
# Get input volume node&lt;br /&gt;
inputVolumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
# Create new volume node for output&lt;br /&gt;
outputVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode', 'MRHeadFiltered')&lt;br /&gt;
&lt;br /&gt;
# Run processing&lt;br /&gt;
inputImage = sitkUtils.PullVolumeFromSlicer(inputVolumeNode)&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushVolumeToSlicer(outputImage, outputVolumeNode)&lt;br /&gt;
&lt;br /&gt;
# Show processing result&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=outputVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
* See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
* 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&lt;br /&gt;
&lt;br /&gt;
== Get current mouse coordinates in a slice view ==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get DataProbe text ==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get reformatted image from a slice viewer as numpy array ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNodeID = 'vtkMRMLSliceNodeRed'&lt;br /&gt;
&lt;br /&gt;
# Get image data from slice view&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(sliceNodeID)&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslicedImage = vtk.vtkImageData()&lt;br /&gt;
reslicedImage.DeepCopy(reslice.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create new volume node using resliced image&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;)&lt;br /&gt;
volumeNode.SetIJKToRASMatrix(sliceNode.GetXYToRAS())&lt;br /&gt;
volumeNode.SetAndObserveImageData(reslicedImage)&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&lt;br /&gt;
# Get voxels as a numpy array&lt;br /&gt;
voxels = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
print voxels.shape&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thick slab reconstruction and maximum/minimum intensity volume projections ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
== Change default file type for nodes (that have never been saved yet) ==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
== Change file type for saving for all volumes (with already existing storage nodes) ==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sequences ==&lt;br /&gt;
&lt;br /&gt;
=== Concatenate all sequences in the scene into a new sequence ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all sequence nodes in the scene&lt;br /&gt;
sequenceNodes = slicer.util.getNodesByClass('vtkMRMLSequenceNode')&lt;br /&gt;
mergedSequenceNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceNode', 'Merged sequence')&lt;br /&gt;
&lt;br /&gt;
# Merge all sequence nodes into a new sequence node&lt;br /&gt;
mergedIndexValue = 0&lt;br /&gt;
for sequenceNode in sequenceNodes:&lt;br /&gt;
    for itemIndex in range(sequenceNode.GetNumberOfDataNodes()):&lt;br /&gt;
        dataNode = sequenceNode.GetNthDataNode(itemIndex)&lt;br /&gt;
        mergedSequenceNode.SetDataNodeAtValue(dataNode, str(mergedIndexValue))&lt;br /&gt;
        mergedIndexValue += 1&lt;br /&gt;
    # Delete the sequence node we copied the data from, to prevent sharing of the same&lt;br /&gt;
    # node by multiple sequences&lt;br /&gt;
    slicer.mrmlScene.RemoveNode(sequenceNode)&lt;br /&gt;
&lt;br /&gt;
# Create a sequence browser node for the new merged sequence&lt;br /&gt;
mergedSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSequenceBrowserNode', 'Merged')&lt;br /&gt;
mergedSequenceBrowserNode.AddSynchronizedSequenceNode(mergedSequenceNode)&lt;br /&gt;
slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(mergedSequenceBrowserNode)&lt;br /&gt;
# Show proxy node in slice viewers&lt;br /&gt;
mergedProxyNode = mergedSequenceBrowserNode.GetProxyNode(mergedSequenceNode)&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mergedProxyNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Segmentations ==&lt;br /&gt;
&lt;br /&gt;
=== Create a segmentation from a labelmap volume and display in 3D ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
=== Export labelmap node from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Export model nodes from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
exportedModelsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelHierarchyNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModelHierarchy(seg, exportedModelsNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show a segmentation in 3D ===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get a representation of a segment ===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = segmentationNode.GetBinaryLabelmapRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using default path and conversion parameters ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using custom path or conversion parameters ===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-convert using a modified conversion parameter ===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get centroid of a segment in world (RAS) coordinates ===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How to run segment editor effects from a script ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
* [https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
* [https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
* [https://gist.github.com/lassoan/5ad51c89521d3cd9c5faf65767506b37 create fat/muscle/bone segment by thresholding and report volume of each segment]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
* [https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
== Accessing views, renderers, and cameras ==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide view controller bars ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.app.layoutManager().threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().sliceWidget('Red').sliceController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().plotWidget(0).plotController().setVisible(False)&lt;br /&gt;
slicer.app.layoutManager().tableWidget(0).tableController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change 3D view background color ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderer = renderWindow.GetRenderers().GetFirstRenderer()&lt;br /&gt;
renderer.SetBackground(1,0,0)&lt;br /&gt;
renderer.SetBackground2(1,0,0)&lt;br /&gt;
renderWindow.Render()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subject hierarchy == &lt;br /&gt;
==== Get the pseudo-singleton subject hierarchy node ====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
&lt;br /&gt;
==== Create subject hierarchy item ====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
==== Get subject hierarchy item ====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
==== Traverse children of a subject hierarchy item ====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in xrange(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
==== Manipulate subject hierarchy item ====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data nodes associated to items in a branch (or a leaf item)&lt;br /&gt;
  shNode.SetDisplayVisibilityForBranch(itemID, 1)&lt;br /&gt;
&lt;br /&gt;
==== Filter items in TreeView or ComboBox ====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
=== Listen to subject hierarchy item events ===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
== Plotting ==&lt;br /&gt;
&lt;br /&gt;
=== Create histogram plot of a volume ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Execute external applications ==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
=== Run process in default environment ===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/SlicerExecutionModel&amp;diff=60933</id>
		<title>Documentation/Nightly/Developers/SlicerExecutionModel</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/SlicerExecutionModel&amp;diff=60933"/>
		<updated>2019-03-20T19:44:36Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add parameter references section (and specify compatibility for reference attributes)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The Slicer Execution Model is designed to improve the acceptance and productivity of Slicer application developers. The Execution Model provides a simple mechanism for incorporating command line programs as Slicer modules. These command line modules are self-describing, emitting an XML description of its command line arguments. Slicer uses this XML description to construct a GUI for the module.&lt;br /&gt;
&lt;br /&gt;
=== Types of Slicer Plugins ===&lt;br /&gt;
&lt;br /&gt;
There are various types of plugins that Slicer supports as command line modules. This variety allows a breadth of integration choices to balance performance and flexibility.&lt;br /&gt;
&lt;br /&gt;
==== Shared object plugins (dll, so) with global symbols ====&lt;br /&gt;
&lt;br /&gt;
Shared object plugins with global symbols integrate into Slicer tighter than the Executable plugins.  Shared object plugins with global symbols can transfer data directly to/from a MRML scene using standard itk::ImageFileReader and itk::ImageFileWriter (and the ImageIO class provided with Slicer, itk::MRMLIDImageIO).  Communicating directly with the MRML scene avoids the overhead of reading and writing images to disk.  Slicer looks for a standard entry point to execute the module called ModuleEntryPoint defined as&lt;br /&gt;
&lt;br /&gt;
 int ModuleEntryPoint(int argc, char* argv[]);&lt;br /&gt;
&lt;br /&gt;
Slicer also looks for the global symbols XMLModuleDescription, ModuleLogoImage, ModuleLogoWidth, ModuleLogoHeight, ModuleLogoPixelSize, and ModuleLogoLength.  These global symbols provide the xml module description and data for the module logo. The data types for these symbols are&lt;br /&gt;
&lt;br /&gt;
          char *XMLModuleDescription;&lt;br /&gt;
 unsigned char *ModuleLogoImage;&lt;br /&gt;
           int  ModuleLogoWidth;&lt;br /&gt;
           int  ModuleLogoHeight;&lt;br /&gt;
           int  ModuleLogoPixelSize;&lt;br /&gt;
 unsigned long  ModuleLogoLength;&lt;br /&gt;
&lt;br /&gt;
These global symbols are accessed during module discovery. The ModuleLogoImage, ModuleLogoWidth, ModuleLogoHeight, ModuleLogoPixelSize, and ModuleLogoLength are optional.&lt;br /&gt;
&lt;br /&gt;
=====Controlling what symbols are exported from a shared library module=====&lt;br /&gt;
&lt;br /&gt;
Shared Object Modules are loaded into Slicer using standard &amp;quot;dlopen&amp;quot; style calls. The ModuleEntryPoint is located within the shared library and cached for later use. The ModuleEntryPoint, however, may not be the only function accessible to Slicer within the shared library. To protect against symbol clash at runtime, all functions and variables accessible within file scope of the shared library should be put in an anonymous namespace.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Use an anonymous namespace to keep class types and function names&lt;br /&gt;
// from colliding when module is used as shared object module.  Every&lt;br /&gt;
// thing should be in an anonymous namespace except for the module&lt;br /&gt;
// entry point, e.g. main() or ModuleEntryPoint()&lt;br /&gt;
//&lt;br /&gt;
namespace {&lt;br /&gt;
    // functions like DoIt() should be put in the anonymous namespace&lt;br /&gt;
    template&amp;lt;class T&amp;gt; int DoIt( int argc, char * argv[], const T&amp;amp; targ)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
} // end of anonymous namespace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[] )&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Shared object plugins (dll, so) with entry points ====&lt;br /&gt;
&lt;br /&gt;
Shared object plugins with entry points integrate into Slicer tighter than the Executable plugins. Shared object plugins with entry points can transfer data directly to/from a MRML scene using standard itk::ImageFileReader and itk::ImageFileWriter (and the ImageIO class provided with Slicer, itk::MRMLIDImageIO). Communicating directly with the MRML scene avoids the overhead of reading and writing images to disk. Slicer looks for standard entry points for executing the module as well as for querying the module for its xml description and logos. The entry points are defined as&lt;br /&gt;
&lt;br /&gt;
           int  ModuleEntryPoint(int argc, char* argv[]);&lt;br /&gt;
          char *GetXMLModuleDescription();&lt;br /&gt;
 unsigned char *GetModuleLogo()(int *width, int *height, int *pixel_size, unsigned long *bufferLength);&lt;br /&gt;
&lt;br /&gt;
GetXMLModuleDescription() and GetModuleLogo() are accessed during module discovery. GetModuleLogo() is optional.&lt;br /&gt;
&lt;br /&gt;
==== Executable plugins with global symbols ====&lt;br /&gt;
&lt;br /&gt;
Executable plugins with global symbols allow for a single executable to be developed that can be integrated into Slicer 3 or run standalone on a cluster. Plugins of this type are opened but not executed at module discovery time.  Slicer 3 looks for the global symbols XMLModuleDescription, ModuleLogoImage, ModuleLogoWidth, ModuleLogoHeight, ModuleLogoPixelSize, and ModuleLogoLength.  The data types for these symbols are&lt;br /&gt;
 &lt;br /&gt;
          char *XMLModuleDescription;&lt;br /&gt;
 unsigned char *ModuleLogoImage;&lt;br /&gt;
           int  ModuleLogoWidth;&lt;br /&gt;
           int  ModuleLogoHeight;&lt;br /&gt;
           int  ModuleLogoPixelSize;&lt;br /&gt;
 unsigned long  ModuleLogoLength;&lt;br /&gt;
&lt;br /&gt;
These global symbols are access during module discovery. ModuleLogoImage, ModuleLogoWidth, ModuleLogoHeight, ModuleLogoPixelSize, ModuleLogoLength are optional.&lt;br /&gt;
&lt;br /&gt;
==== Executable plugins (exe) with command line options ====&lt;br /&gt;
&lt;br /&gt;
Executable plugins with command line options are the most flexible type of plugin. This approach allows for legacy applications to be integrated into Slicer using a wrapper around the legacy application.  Plugins of this type are executed at module discovery time, passing in the command line argument &amp;quot;--xml&amp;quot;. The plugin responds to the &amp;quot;--xml&amp;quot; query by emitting the xml description of the module. The plugin is also executed at module discovery time with a &amp;quot;--logo&amp;quot; command line argument. The plugin responds to the &amp;quot;--logo&amp;quot; query by emitting a logo description. &lt;br /&gt;
&lt;br /&gt;
This type of plugin allows for legacy applications to be integrated into Slicer. A developer can provide Slicer with a small executable or shell script that responds to the &amp;quot;--xml&amp;quot; and &amp;quot;--logo&amp;quot; command line arguments needed for Slicer 3 integration and otherwise spawns the legacy executable passing down any command line arguments.&lt;br /&gt;
&lt;br /&gt;
 &amp;gt; module.exe --xml&lt;br /&gt;
 &amp;gt; module.exe --logo&lt;br /&gt;
&lt;br /&gt;
==== Script plugins with Python ====&lt;br /&gt;
&lt;br /&gt;
Python scripts are found using the discovery mechanisms for the other plugins. Since Python plugins are fundamentally different from the shared and executable plugins, they are documented on their own [[Documentation/Nightly/Developers/SlicerExecutionModel/Python|page]].&lt;br /&gt;
&lt;br /&gt;
=== Calling Command Line Modules from Other Code ===&lt;br /&gt;
&lt;br /&gt;
In addition to the automated GUI that shows up in the Slicer user interface, the Execution Model can be used to encapsulate functionality that is invoked by other parts of the program.  For instance, the Editor Module can invoke the Model Maker Module to build models.  By invoking a command line module in this way, you get the advantage of background processing with progress reporting.  See [[Documentation/Nightly/Developers/SlicerExecutionModel/Programmatic Invocation|this page]] for more details.&lt;br /&gt;
&lt;br /&gt;
=== Architecture === &lt;br /&gt;
[[Image:ExecutionModelPlugins.png|600px|Plugin architecture]]&lt;br /&gt;
[[Image:CommandLineModule.png|400px|Module architecture]]&lt;br /&gt;
[[Image:ModuleFactory.png|400px|Module factory ]]&lt;br /&gt;
[[Image:Class_parser_state_coll_graph.png|400px|Module description]]&lt;br /&gt;
&lt;br /&gt;
== Module Description ==&lt;br /&gt;
&lt;br /&gt;
Modules are described using XML. The XML is used to generate the C++ command line code and the GUI for the application.&lt;br /&gt;
&lt;br /&gt;
=== XML Schema ===&lt;br /&gt;
&lt;br /&gt;
At a minimum, each module description must contain:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;executable&amp;gt;&lt;br /&gt;
 &amp;lt;title&amp;gt;A title&amp;lt;/title&amp;gt;&lt;br /&gt;
 &amp;lt;description&amp;gt;A description&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
   At least one parameter&lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &amp;lt;/executable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the following descriptions of each XML tag, CLP means command line processing and GUI means graphical user interface. Unless otherwise specified, tags are optional.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;executable&amp;gt; (required)&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;category&amp;gt;&lt;br /&gt;
:: Classifies the executable (e.g. Filtering, Segmentation). Category can be a ''dot'' separated string. Multiple categories can be given and should be separated by a ''semicolon''.&lt;br /&gt;
:: ''for CLP'', not used.&lt;br /&gt;
:: ''for GUI'', used on the menu selector to group executables. ''Dot'' separated strings can be used to generate sub-menus. ''Semicolon'' separated strings can be used to create multiple categories.&lt;br /&gt;
;; &amp;lt;/category&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;title&amp;gt; (required)&lt;br /&gt;
:: A word or two describing the executable (e.g. Median Filter, Anisotropic Diffusion&lt;br /&gt;
:: ''for CLP'', not used.&lt;br /&gt;
:: ''for GUI'', used to label the frame containing the GUI for the executable. Also, GUI names for volumes use this label as a prefix.&lt;br /&gt;
;; &amp;lt;/title&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;description&amp;gt; (required)&lt;br /&gt;
:: A long description of the executable. Any double quotes will be converted to single quotes.&lt;br /&gt;
:: ''for CLP'', appears at the end of the --help.&lt;br /&gt;
:: ''for GUI'', appears in the help frame.&lt;br /&gt;
;; &amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;version&amp;gt;&lt;br /&gt;
:: The version of the command line executable. A suggested format is:&lt;br /&gt;
::: ''major''.''minor''.''patch''.''build''.''status''&lt;br /&gt;
::: where status is&lt;br /&gt;
:::: vc: version controlled (pre-alpha), build can be a serial revision number, if any (like svn might have).&lt;br /&gt;
:::: a: alpha&lt;br /&gt;
:::: b: beta&lt;br /&gt;
:::: rc: release candidate&lt;br /&gt;
:::: fcs: first customer ship&lt;br /&gt;
:: ''for CLP'', reported in response to --version.&lt;br /&gt;
:: ''for GUI'', not used.&lt;br /&gt;
;; &amp;lt;/version&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;documentation-url&amp;gt;&lt;br /&gt;
:: The location of extended documentation for the executable, (e.g. http://www.na-mic.org/foo.html).&lt;br /&gt;
;; &amp;lt;/documentation-url&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;license&amp;gt;&lt;br /&gt;
:: The type of license or a url containing the license, (e.g. Berkeley, Apache, http://www.slicer.org/copyright/copyright.txt).&lt;br /&gt;
:: ''for CLP'', not used.&lt;br /&gt;
:: ''for GUI'', may show up in the Help or About section.&lt;br /&gt;
;; &amp;lt;/license&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;contributor&amp;gt;&lt;br /&gt;
:: The author(s) of the command line executable (e.g. Pieper, Jim Miller).&lt;br /&gt;
:: for ''CLP'', appears as part of --help&lt;br /&gt;
:: for ''GUI'', may show up in the Help or About section.&lt;br /&gt;
;; &amp;lt;/contributor&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;acknowledgements&amp;gt;&lt;br /&gt;
:: Acknowledgements for funding agency, employer, colleague, (e.g. This work is part of the National Alliance for Medical Image Computing NAMIC), funded by the National Institutes of Health through the NIH Roadmap for Medical Research, Grant U54 EB005149).&lt;br /&gt;
:: for ''CLP'', appears as part of --help&lt;br /&gt;
:: for ''GUI'', may show up in the Help of About section.&lt;br /&gt;
;; &amp;lt;/acknowledgements&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;parameters [advanced=&amp;quot;true|''false''&amp;quot;]&amp;gt; (required for each group of parameters)&lt;br /&gt;
:: Starts a group of parameters.&lt;br /&gt;
:: for ''CLP'', not used.&lt;br /&gt;
:: for ''GUI'', defines a widget (in tk, a frame) that contains other widgets. If ''advanced'' is true, the frame will be closed initially.&lt;br /&gt;
&lt;br /&gt;
;;; &amp;lt;label&amp;gt; (required)&lt;br /&gt;
::: A short string that summarizes a parameter group, (e.g. I/O, Diffusion)&lt;br /&gt;
::: for ''CLP'', not used.&lt;br /&gt;
::: for ''GUI'', used to label the frame.&lt;br /&gt;
;;; &amp;lt;/label&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;; &amp;lt;description&amp;gt; (required)&lt;br /&gt;
::: A short description of the parameter group, (e.g. Input/Output Parameters, Anitostropic Diffusion Parameters). Any double quotes will be converted to single quotes.&lt;br /&gt;
::: ''for CLP'', not used.&lt;br /&gt;
::: ''for GUI'', used in balloon help for the frame containing the parameter group.&lt;br /&gt;
;;; &amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;; &amp;lt;integer&amp;gt; | &amp;lt;float&amp;gt; | &amp;lt;double&amp;gt; | &amp;lt;boolean&amp;gt; | &amp;lt;string&amp;gt; | &amp;lt;integer-vector&amp;gt; | &amp;lt;float-vector&amp;gt; | &amp;lt;double-vector&amp;gt; | &amp;lt;string-vector&amp;gt; | &amp;lt;integer-enumeration&amp;gt; | &amp;lt;float-enumeration&amp;gt; | &amp;lt;double-enumeration&amp;gt; | &amp;lt;string-enumeration&amp;gt; | &amp;lt;file&amp;gt; | &amp;lt;directory&amp;gt; | &amp;lt;image [type=&amp;quot;''scalar''|''label''|''tensor''|''diffusion-weighted''|''vector''|''model''&amp;quot;] [reference=&amp;quot;...&amp;quot;] &amp;gt; | &amp;lt;geometry [type=&amp;quot;''fiberbundle''|''model''&amp;quot;] [reference=&amp;quot;...&amp;quot;]&amp;gt; | &amp;lt;point [multiple=&amp;quot;''true''|''false''&amp;quot;] [coordinateSystem=&amp;quot;''lps''|''ras''&amp;quot;]&amp;gt; | &amp;lt;pointfile [multiple=&amp;quot;''true''|''false''&amp;quot;] [coordinateSystem=&amp;quot;''lps''|''ras''&amp;quot;]&amp;gt; | &amp;lt;region [multiple=&amp;quot;''true''|''false''&amp;quot;] [coordinateSystem=&amp;quot;''lps''|''ras''&amp;quot;]&amp;gt; | &amp;amp;lt;table [type=&amp;quot;''color''&amp;quot;] [fileExtensions=&amp;quot;''.tsv''|''.csv''|''.txt''|''.ctbl''&amp;quot;]&amp;gt; | &amp;lt;transform [type=&amp;quot;''linear''|''nonlinear''|''bspline''&amp;quot;] [reference=&amp;quot;...&amp;quot;] fileExtensions=&amp;quot;.tfm,.h5,.hdf5,.mat,.txt&amp;quot;&amp;gt;&lt;br /&gt;
::: The type of the parameter. &lt;br /&gt;
:::: The scalar types ('''integer''', '''float''', etc.) correspond to the usual programming language types. &lt;br /&gt;
:::: The '''-vector''' types are represented by comma separated values of the scalar type. &lt;br /&gt;
:::: The '''-enumeration''' types use the '''&amp;lt;element&amp;gt;''' tag to enumerate choices of the scalar type. &lt;br /&gt;
:::: '''&amp;lt;image&amp;gt;''' is a special type that indicates that the parameter is a file name that specifies images.&lt;br /&gt;
:::: The &amp;lt;region&amp;gt; parameter can be used to specify rectangular ROIs. The command-line syntax is --region X_center,Y_center,Z_center,X_radius,Y_Radius,Z_Radius.&lt;br /&gt;
:::: If the attribute ''multiple'' is &amp;quot;true&amp;quot;, multiple arguments are allowed for '''scalar''', '''file''', '''directory''', '''image''', '''geometry''', '''point''', '''pointfile''' and '''region''' parameters. BUG: the automatically built GUI will not support selecting multiple volumes for the '''image''' argument, but they can be passed on the command line. If the parameter has a ''flag'' or ''longflag'', then the flag may be specified multiple times on the command line. The resulting C++ variable will be a std::vector of the scalar type. If the multiple parameter does not have a flag, then multiple arguments can appear on the command line. However, a multiple parameter with no flags must be the last parameter specified.&lt;br /&gt;
:::: The attribute ''coordinateSystem'' is allowed for the parameters '''point''', '''pointfile''' and '''region'''. &lt;br /&gt;
:::: The attribute ''fileExtensions'' is allowed for '''file''', '''pointfile''', '''image''', '''transform''' and '''geometry'''. fileExtensions can contain a list of comma separated file extensions for optional use by the GUI.&lt;br /&gt;
:::: Transform types: If not specified then any transform is accepted (linear, non-linar, composite, ...). By specifying a type, accepted transforms can be limited to 'linear' = any linear transform; 'non-linear' = grid, displacement field; 'bspline' = b-spline transform.&lt;br /&gt;
:::: The attribute ''reference'' can mean different things based on the parameter type. If  the parameter is a transform and the reference is transformable, then the transform hierarchy of the reference is manipulated such that the reference is under the transform. If the parameter is an image or a model, then the parameter is placed in subject hierarchy at the same level as the reference (note: not available in Slicer3). If the parameter is an image, reference will be used to initialize lookup table of the output image (note: not available in Slicer4).&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;name&amp;gt; (required if longflag is not specified)&lt;br /&gt;
:::: The name of a command line argument. If name is not specified, longflag will be used (e.g. conductance, numberOfIterations). The name must be usable as a C++ variable. For example, it CANNOT have spaces or special characters and must start with a letter.&lt;br /&gt;
:::: ''for CLP'', the name of the C++ variable.&lt;br /&gt;
:::: ''for GUI'', used internally.&lt;br /&gt;
;;;; &amp;lt;/name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;description&amp;gt; (required)&lt;br /&gt;
:::: A brief description of the parameter. Any double quotes will be converted to single quotes.&lt;br /&gt;
:::: ''for CLP'', describes the parameter for --usage and --help.&lt;br /&gt;
:::: ''for GUI'', describes the parameter when the cursor is placed over the widget for the parameter (balloon help).&lt;br /&gt;
;;;; &amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;label&amp;gt; (required)&lt;br /&gt;
:::: A label for parameter (e.g. Dicom Directory, Conductance).&lt;br /&gt;
:::: ''for'' CLP, not used.&lt;br /&gt;
:::: ''for'' GUI, the label for the parameter widget.&lt;br /&gt;
;;;; &amp;lt;/label&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;default&amp;gt;&lt;br /&gt;
:::: A default value for the parameter. The default must be a type that is compatible with the parameter type. The vector parameters are specified as comma separated values of the atomic parameter type.&lt;br /&gt;
:::: ''for CLP'', contains the default for the parameter unless the parameter is a ''boolean''. The default for ''boolean'' parameters is always set to ''false''.&lt;br /&gt;
:::: ''for GUI'', contains the default for the parameter.&lt;br /&gt;
;;;; &amp;lt;/default&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;flag [alias=&amp;quot;a,b&amp;quot;] [deprecatedalias=&amp;quot;c,d&amp;quot;]&amp;gt; (not required if longflag is present)&lt;br /&gt;
:::: A single character command line flag (e.g. s, W). Can provide &amp;quot;alias&amp;quot;'s (comma separated) if different flags can be used to activate the same parameter.  Can provide &amp;quot;deprecatedalias&amp;quot;'s (comma separated) if different flags can be used to set the same parameter but the user should be notified of which &amp;quot;updated&amp;quot; flag to use. Parameters with flags are considered &amp;quot;optional&amp;quot; and do not have be specified or assigned.  Parameters with flags allow one to override a default behavior.&lt;br /&gt;
:::: ''for CLP'', used as the short flag on the command line.&lt;br /&gt;
:::: ''for GUI'', used when running the module.&lt;br /&gt;
;;;; &amp;lt;/flag&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;longflag [alias=&amp;quot;foo,bar&amp;quot;] [deprecatedalias=&amp;quot;garf&amp;quot;]&amp;gt; (not required if flag is present)&lt;br /&gt;
:::: A command line flag (e.g. spacing, Watcher). Can provide &amp;quot;alias&amp;quot;'s (comma separated) if different long flags can be used to activate the same parameter.  Can provide &amp;quot;deprecatedalias&amp;quot;'s (comma separated) if different long flags can be used to set the same parameter but the user should be notified of which &amp;quot;updated&amp;quot; long flag to use. Parameters with flags are considered &amp;quot;optional&amp;quot; and do not have be specified or assigned.  Parameters with flags allow one to override a default behavior.&lt;br /&gt;
:::: Note: apparently you can't use hyphens in the longflag, so things like --my-option are not allows.  -gcs&lt;br /&gt;
:::: ''for CLP'', used as the long flag on the command line.&lt;br /&gt;
:::: ''for GUI'', used when running the module.&lt;br /&gt;
;;;; &amp;lt;/longflag&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;constraints&amp;gt;&lt;br /&gt;
:::: Encloses constraints on the value of a non-vector, non-enumerated parameter.&lt;br /&gt;
:::: ''for CLP'', not used.&lt;br /&gt;
:::: ''for GUI'', if present, a slider will be created using the minimum, maximum and step specified.&lt;br /&gt;
&lt;br /&gt;
;;;;; &amp;lt;minimum&amp;gt;&lt;br /&gt;
::::: The minimum allowed value for the parameter. If not specified, the minimum is the smallest possible value for the parameter type.&lt;br /&gt;
;;;;; &amp;lt;/minimum&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;;; &amp;lt;maximum&amp;gt;&lt;br /&gt;
::::: The maximum allowed value for the parameter. If not specified, the maximum is the largest possible value for the parameter type.&lt;br /&gt;
;;;;; &amp;lt;/maximum&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;;; &amp;lt;step&amp;gt;&lt;br /&gt;
::::: The increment for the parameter.&lt;br /&gt;
;;;;; &amp;lt;/step&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;/constraints&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;channel&amp;gt; (required for file, pointfile, directory and image parameters)&lt;br /&gt;
:::: Specifies whether the parameter is an input or output parameter.&lt;br /&gt;
:::: ''for CLP'', not used.&lt;br /&gt;
:::: ''for GUI'', selects the proper widget for file handling.&lt;br /&gt;
;;;; &amp;lt;/channel&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;index&amp;gt; (required if there are no flags specified)&lt;br /&gt;
:::: An integer starting at 0, that specifies a command line argument that has no flags.&lt;br /&gt;
:::: Note: if you use index for, say, an image, the user must enter some input value into the GUI.  If the user does not fill in a value, the plugin is not run at all.  However, slicer will &amp;quot;seem&amp;quot; to run it, and no error message is given.  -gcs&lt;br /&gt;
:::: ''for CLP'', specifies the order of an argument that has no flags.&lt;br /&gt;
:::: ''for GUI'', used when running the module.&lt;br /&gt;
;;;; &amp;lt;/index&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;enumeration&amp;gt; (required for enumeration parameters)&lt;br /&gt;
:::: Encloses elements for the parameter. The parameter is restricted one and only one element.&lt;br /&gt;
:::: ''for CLP'', not used.&lt;br /&gt;
:::: ''for GUI'', defines a radio button with choices.&lt;br /&gt;
&lt;br /&gt;
;;;;; &amp;lt;element&amp;gt;&lt;br /&gt;
::::: Defines the choice. Must be of the proper type for a parameter.&lt;br /&gt;
::::: ''for CLP'', not used.&lt;br /&gt;
::::: ''for GUI'', used as the label for the radio button.&lt;br /&gt;
;;;;; &amp;lt;/element&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;/enumeration&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;reference [role=&amp;quot;foo&amp;quot;] [parameter=&amp;quot;bar&amp;quot;]/&amp;gt;&lt;br /&gt;
:::: A forward reference from the parameter to another parameter &amp;quot;bar&amp;quot; with the reference role &amp;quot;foo&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
;;; &amp;lt;/integer&amp;gt; | &amp;lt;/float&amp;gt; | &amp;lt;/double&amp;gt; | &amp;lt;/boolean&amp;gt; | &amp;lt;/string&amp;gt; | &amp;lt;/integer-vector&amp;gt; | &amp;lt;/float-vector&amp;gt; | &amp;lt;/double-vector&amp;gt; | &amp;lt;/string-vector&amp;gt; | &amp;lt;/integer-enumeration&amp;gt; | &amp;lt;/float-enumeration&amp;gt; | &amp;lt;/double-enumeration&amp;gt; | &amp;lt;/string-enumeration&amp;gt; | &amp;lt;/file&amp;gt; | &amp;lt;/directory&amp;gt; | &amp;lt;/image&amp;gt; | &amp;lt;/geometry&amp;gt; | &amp;lt;/point&amp;gt; | &amp;lt;/pointfile&amp;gt; | &amp;lt;/region&amp;gt; | &amp;amp;lt;/table&amp;gt; | &amp;lt;/transform&amp;gt;&lt;br /&gt;
;; &amp;lt;/parameters&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;/executable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameter References ===&lt;br /&gt;
&lt;br /&gt;
There are two types of references between parameters:&lt;br /&gt;
&lt;br /&gt;
* '''Attribute of image/geometry/transform parameter [reference=&amp;quot;...&amp;quot;]''': The specialized attribute reference can mean different things based on the parameter type. If the parameter is a transform and the reference is transformable, then the transform hierarchy of the reference is manipulated such that the reference is under the transform. If the parameter is an image or a model, then the parameter is placed in subject hierarchy at the same level as the reference.&lt;br /&gt;
&lt;br /&gt;
* '''Element under a parameter &amp;lt;reference [role=&amp;quot;foo&amp;quot;] [parameter=&amp;quot;bar&amp;quot;]/&amp;gt;''': This a generic reference called &amp;quot;forward reference&amp;quot;, point from the parameter to another parameter with name &amp;quot;bar&amp;quot; with the reference role &amp;quot;foo&amp;quot;. If both parameters are represented in Slicer as a MRML node, then the node associated to the parameter containing the reference will be added a node reference to the node associated to &amp;quot;bar&amp;quot; with the role &amp;quot;foo&amp;quot;. These references can be useful for the application to identify other nodes that are in some way related to the node. For example: 1) get the moving and fixed images/landmarks from a transform that were inputs of the registration step creating it, 2) identify the source image of a processed image to know its provenance, 3) identify another node from which certain properties need to be propagated (e.g. color table)&lt;br /&gt;
&lt;br /&gt;
== Slicer GUI Generation ==&lt;br /&gt;
&lt;br /&gt;
Slicer generates GUI's for each executable discovered during the startup process. Slicer searches directories stored in the Slicer Module Path. This path is set from the Slicer application in View-&amp;gt;Application Settings-&amp;gt;Modules-&amp;gt;Additional module paths. Slicer attempts to run every executable in the prescribed directories and look for a valid XML file in response to a &amp;quot;--xml&amp;quot; command line.&lt;br /&gt;
&lt;br /&gt;
Here are a few representative examples.&lt;br /&gt;
&lt;br /&gt;
=== A tour of the Execution Model XML ===&lt;br /&gt;
&lt;br /&gt;
This example is a sampler of the parameters available in the Execution Model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;floatright&amp;quot;&amp;gt;&amp;lt;span&amp;gt;[[Image:ExectionModelTourGUI.png|[[Image:ExectionModelTourGUI.png]]]]&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;executable&amp;gt;&lt;br /&gt;
   &amp;lt;category&amp;gt;Tours&amp;lt;/category&amp;gt;&lt;br /&gt;
   &amp;lt;title&amp;gt;Execution Model Tour&amp;lt;/title&amp;gt;&lt;br /&gt;
   &amp;lt;description&amp;gt;&lt;br /&gt;
   Shows one of each type of parameter.&lt;br /&gt;
   &amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;
   &amp;lt;documentation-url&amp;gt;&amp;lt;/documentation-url&amp;gt;&lt;br /&gt;
   &amp;lt;license&amp;gt;&amp;lt;/license&amp;gt;&lt;br /&gt;
   &amp;lt;contributor&amp;gt;Daniel Blezek&amp;lt;/contributor&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Scalar Parameters&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;&lt;br /&gt;
     Variations on scalar parameters&lt;br /&gt;
     &amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;integer&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;integerVariable&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;flag&amp;gt;i&amp;lt;/flag&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;integer&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;&lt;br /&gt;
       An integer without constraints&lt;br /&gt;
       &amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Integer Parameter&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;30&amp;lt;/default&amp;gt;&lt;br /&gt;
     &amp;lt;/integer&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Scalar Parameters With Constraints&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Variations on scalar parameters&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;double&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;doubleVariable&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;flag&amp;gt;d&amp;lt;/flag&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;double&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;An double with constraints&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Double Parameter&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;30&amp;lt;/default&amp;gt;&lt;br /&gt;
       &amp;lt;constraints&amp;gt;&lt;br /&gt;
         &amp;lt;minimum&amp;gt;0&amp;lt;/minimum&amp;gt;&lt;br /&gt;
         &amp;lt;maximum&amp;gt;1.e3&amp;lt;/maximum&amp;gt;&lt;br /&gt;
         &amp;lt;step&amp;gt;0&amp;lt;/step&amp;gt;&lt;br /&gt;
       &amp;lt;/constraints&amp;gt;&lt;br /&gt;
     &amp;lt;/double&amp;gt;&lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Vector Parameters&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Variations on vector parameters&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;float-vector&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;floatVector&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;flag&amp;gt;f&amp;lt;/flag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;A vector of floats&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Float Vector Parameter&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;1.3,2,-14&amp;lt;/default&amp;gt;&lt;br /&gt;
     &amp;lt;/float-vector&amp;gt;&lt;br /&gt;
     &amp;lt;string-vector&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;stringVector&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;string_vector&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;A vector of strings&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;String Vector Parameter&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;&amp;quot;foo&amp;quot;,bar,&amp;quot;foobar&amp;quot;&amp;lt;/default&amp;gt;&lt;br /&gt;
     &amp;lt;/string-vector&amp;gt;&lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Enumeration Parameters&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Variations on enumeration parameters&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;string-enumeration&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;stringChoice&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;flag&amp;gt;e&amp;lt;/flag&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;enumeration&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;An enumeration of strings&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;String Enumeration Parameter&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;foo&amp;lt;/default&amp;gt;&lt;br /&gt;
       &amp;lt;element&amp;gt;foo&amp;lt;/element&amp;gt;&lt;br /&gt;
       &amp;lt;element&amp;gt;&amp;quot;foobar&amp;quot;&amp;lt;/element&amp;gt;&lt;br /&gt;
       &amp;lt;element&amp;gt;foofoo&amp;lt;/element&amp;gt;&lt;br /&gt;
     &amp;lt;/string-enumeration&amp;gt;&lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &amp;lt;/executable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Module with an integer-vector, one input image and one output image ===&lt;br /&gt;
&lt;br /&gt;
Here is the XML that describes the MedianImageFilter. The image on the right shows the generated Slicer 3 GUI. The help frame has been expanded by the user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;floatright&amp;quot;&amp;gt;&amp;lt;span&amp;gt;[[Image:MedianFilterGUI.png|[[Image:MedianFilterGUI.png]]]]&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;executable&amp;gt;&lt;br /&gt;
  &amp;lt;category&amp;gt;&lt;br /&gt;
  Filtering.Denoising&lt;br /&gt;
  &amp;lt;/category&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;&lt;br /&gt;
  Median Filter&lt;br /&gt;
  &amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;description&amp;gt;&lt;br /&gt;
The MedianImageFilter is commonly used as a robust approach for&lt;br /&gt;
noise reduction. This filter is particularly efficient against&lt;br /&gt;
&amp;quot;salt-and-pepper&amp;quot; noise. In other words, it is robust to the presence&lt;br /&gt;
of gray-level outliers. MedianImageFilter computes the value of each output&lt;br /&gt;
pixel as the statistical median of the neighborhood of values around the&lt;br /&gt;
corresponding input pixel.&lt;br /&gt;
  &amp;lt;/description&amp;gt;&lt;br /&gt;
  &amp;lt;version&amp;gt;0.1.0.$Revision: 2085 $(alpha)&amp;lt;/version&amp;gt;&lt;br /&gt;
  &amp;lt;documentation-url&amp;gt;&amp;lt;/documentation-url&amp;gt;&lt;br /&gt;
  &amp;lt;license&amp;gt;&amp;lt;/license&amp;gt;&lt;br /&gt;
  &amp;lt;contributor&amp;gt;Bill Lorensen&amp;lt;/contributor&amp;gt;&lt;br /&gt;
  &amp;lt;acknowledgements&amp;gt;This command module was derived from&lt;br /&gt;
Insight/Examples/Filtering/MedianImageFilter (copyright) Insight Software Consortium&lt;br /&gt;
  &amp;lt;/acknowledgements&amp;gt;&lt;br /&gt;
  &amp;lt;parameters&amp;gt;&lt;br /&gt;
    &amp;lt;label&amp;gt;Median Filter Parameters&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;description&amp;gt;Parameters for the median filter&amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;integer-vector&amp;gt;&lt;br /&gt;
      &amp;lt;name&amp;gt;neighborhood&amp;lt;/name&amp;gt;&lt;br /&gt;
      &amp;lt;longflag&amp;gt;--neighborhood&amp;lt;/longflag&amp;gt;&lt;br /&gt;
      &amp;lt;description&amp;gt;The size of the neighborhood in each dimension&amp;lt;/description&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Neighborhood Size&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;1,1,1&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/integer-vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/parameters&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;parameters&amp;gt;&lt;br /&gt;
    &amp;lt;label&amp;gt;IO&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;description&amp;gt;Input/output parameters&amp;lt;/description&amp;gt;&lt;br /&gt;
    &amp;lt;image&amp;gt;&lt;br /&gt;
      &amp;lt;name&amp;gt;inputVolume&amp;lt;/name&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Input Volume&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;channel&amp;gt;input&amp;lt;/channel&amp;gt;&lt;br /&gt;
      &amp;lt;index&amp;gt;0&amp;lt;/index&amp;gt;&lt;br /&gt;
      &amp;lt;description&amp;gt;Input volume to be filtered&amp;lt;/description&amp;gt;&lt;br /&gt;
    &amp;lt;/image&amp;gt;&lt;br /&gt;
    &amp;lt;image&amp;gt;&lt;br /&gt;
      &amp;lt;name&amp;gt;outputVolume&amp;lt;/name&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Output Volume&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
      &amp;lt;index&amp;gt;1&amp;lt;/index&amp;gt;&lt;br /&gt;
      &amp;lt;description&amp;gt;Output filtered&amp;lt;/description&amp;gt;&lt;br /&gt;
      &amp;lt;reference role=&amp;quot;source&amp;quot; parameter=&amp;quot;inputVolume&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/image&amp;gt;&lt;br /&gt;
  &amp;lt;/parameters&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/executable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Module with a multiple scalars, one Input image and one output image ===&lt;br /&gt;
&lt;br /&gt;
A module with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;floatright&amp;quot;&amp;gt;&amp;lt;span&amp;gt;[[Image:AnisotropicDiffusionFilterGUI.png|[[Image:AnisotropicDiffusionFilterGUI.png]]]]&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;executable&amp;gt;&lt;br /&gt;
   &amp;lt;category&amp;gt;filtering&amp;lt;/category&amp;gt;&lt;br /&gt;
   &amp;lt;title&amp;gt;Anisotropic Diffusion&amp;lt;/title&amp;gt;&lt;br /&gt;
   &amp;lt;description&amp;gt;&lt;br /&gt;
   Runs anisotropic diffusion on a volume&lt;br /&gt;
   &amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;
   &amp;lt;documentation-url&amp;gt;&amp;lt;/documentation-url&amp;gt;&lt;br /&gt;
   &amp;lt;license&amp;gt;&amp;lt;/license&amp;gt;&lt;br /&gt;
   &amp;lt;contributor&amp;gt;Bill Lorensen&amp;lt;/contributor&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;&lt;br /&gt;
     Anisotropic Diffusion Parameters&lt;br /&gt;
     &amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;&lt;br /&gt;
     Parameters for the anisotropic&lt;br /&gt;
     diffusion algorithm&lt;br /&gt;
     &amp;lt;/description&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;double&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;conductance&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;conductance&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;Conductance&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Conductance&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;1&amp;lt;/default&amp;gt;&lt;br /&gt;
       &amp;lt;constraints&amp;gt;&lt;br /&gt;
         &amp;lt;minimum&amp;gt;0&amp;lt;/minimum&amp;gt;&lt;br /&gt;
         &amp;lt;maximum&amp;gt;10&amp;lt;/maximum&amp;gt;&lt;br /&gt;
         &amp;lt;step&amp;gt;.01&amp;lt;/step&amp;gt;&lt;br /&gt;
       &amp;lt;/constraints&amp;gt;&lt;br /&gt;
     &amp;lt;/double&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;double&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;timeStep&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;timeStep&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;Time Step&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Time Step&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;0.0625&amp;lt;/default&amp;gt;&lt;br /&gt;
       &amp;lt;constraints&amp;gt;&lt;br /&gt;
         &amp;lt;minimum&amp;gt;.001&amp;lt;/minimum&amp;gt;&lt;br /&gt;
         &amp;lt;maximum&amp;gt;1&amp;lt;/maximum&amp;gt;&lt;br /&gt;
         &amp;lt;step&amp;gt;.001&amp;lt;/step&amp;gt;&lt;br /&gt;
       &amp;lt;/constraints&amp;gt;&lt;br /&gt;
     &amp;lt;/double&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;integer&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;numberOfIterations&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;iterations&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;Number of iterations&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Iterations&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;1&amp;lt;/default&amp;gt;&lt;br /&gt;
       &amp;lt;constraints&amp;gt;&lt;br /&gt;
         &amp;lt;minimum&amp;gt;1&amp;lt;/minimum&amp;gt;&lt;br /&gt;
         &amp;lt;maximum&amp;gt;30&amp;lt;/maximum&amp;gt;&lt;br /&gt;
         &amp;lt;step&amp;gt;1&amp;lt;/step&amp;gt;&lt;br /&gt;
       &amp;lt;/constraints&amp;gt;&lt;br /&gt;
     &amp;lt;/integer&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;IO&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Input/output parameters&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;image&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;inputVolume&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Input Volume&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;channel&amp;gt;input&amp;lt;/channel&amp;gt;&lt;br /&gt;
       &amp;lt;index&amp;gt;0&amp;lt;/index&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;Input volume to be filtered&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;/image&amp;gt;&lt;br /&gt;
     &amp;lt;image&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;outputVolume&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Output Volume&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
       &amp;lt;index&amp;gt;1&amp;lt;/index&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;Output filtered&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;/image&amp;gt;&lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/executable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Module with output text presented in GUI ===&lt;br /&gt;
&lt;br /&gt;
Slicer auto generates GUI to display output from the command line module after execution is complete.&lt;br /&gt;
The flag [--returnparameterfile &amp;lt;file name&amp;gt;] is used to provide a name of a file that the module uses to store key=value pairs that are displayed in the Slicer GUI. The keys are described in the command line module xml schema using the output channel.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates a portion of an XML schema containing  1 string-enumeration input and 7 string outputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;floatright&amp;quot;&amp;gt;&amp;lt;span&amp;gt;[[Image:RadnosticsBetaOsteoporosisAnalysisGUI.png|[[Image:RadnosticsBetaOsteoporosisAnalysisGUI.png]]]]&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;parameters&amp;gt;&lt;br /&gt;
   &amp;lt;label&amp;gt;Radnostics Beta Osteoporosis Analysis&amp;lt;/label&amp;gt;&lt;br /&gt;
   &amp;lt;string-enumeration&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;Osteoporosis&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;longflag&amp;gt;--osteoporosis&amp;lt;/longflag&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;After Segmentation Perform Osteoporosis Analysis&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Osteoporosis Analysis will provide a Radnostics Osteoporosis score for the patient.&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;default&amp;gt;yes&amp;lt;/default&amp;gt;&lt;br /&gt;
     &amp;lt;element&amp;gt;yes&amp;lt;/element&amp;gt;&lt;br /&gt;
     &amp;lt;element&amp;gt;no&amp;lt;/element&amp;gt;&lt;br /&gt;
   &amp;lt;/string-enumeration&amp;gt;&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;PatientGender&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Gender&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Patient Gender&amp;lt;/description&amp;gt;		  &lt;br /&gt;
     &amp;lt;default&amp;gt;na&amp;lt;/default&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;		&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;PatientAge&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Age&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Patient Age&amp;lt;/description&amp;gt;		  &lt;br /&gt;
     &amp;lt;default&amp;gt;na&amp;lt;/default&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;		&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;RadnosticsOsteoporosisScore&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Radnostics Osteoporosis Score&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Radnostics Osteoporosis Score&amp;lt;/description&amp;gt;		  &lt;br /&gt;
     &amp;lt;default&amp;gt;na&amp;lt;/default&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;		&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;OsteoporosisComment1&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;*&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Comment 1&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;OsteoporosisComment2&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;*&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Comment 2&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;OsteoporosisComment3&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;*&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Comment 3&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;OsteoporosisComment4&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;*&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Comment 4&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;&lt;br /&gt;
 &amp;lt;/parameters&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 The command line module outputs key=value pairs to the file supplied by –-returnparameterfile as shown below:&lt;br /&gt;
    PatientGender = F &lt;br /&gt;
    PatientAge = 059Y&lt;br /&gt;
    RadnosticsOsteoporosisScore = 8 (high)&lt;br /&gt;
    OsteoporosisComment1 = vertebra label 58 has biconcave fracture&lt;br /&gt;
    OsteoporosisComment2 = vertebra label 56 has mean density of 120 HU&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Command Line Parsing ==&lt;br /&gt;
&lt;br /&gt;
The Slicer Execution Model has support for parsing executable command lines. The C++ code to parse the command line arguments is generated automatically from the same XML description that generates the GUI. ''GenerateCLP,'' located in ''SlicerExecutionModel/GenerateCLP'' reads the XML Module Description and creates an include file ''&amp;quot;Executable&amp;quot;CLP.h'' in the build tree. The executable includes this header file and accesses the code with the macro PARSE_ARGS.&lt;br /&gt;
&lt;br /&gt;
GenerateCLP provides the following to the executable:&lt;br /&gt;
&lt;br /&gt;
# A brief usage command if required arguments are missing&lt;br /&gt;
# A full help command if ''-h'' or ''--help'' is specified on the command line&lt;br /&gt;
# A copy of the xml description if ''--xml'' is specified on the command line&lt;br /&gt;
# An echo of the command line parameters and their values if ''--echo'' is specified&lt;br /&gt;
&lt;br /&gt;
GenerateCLP provides the following source code:&lt;br /&gt;
&lt;br /&gt;
# A C++ declaration of the proper type for each parameter assigning the default value if specified by the XML&lt;br /&gt;
# For ''-vector'' parameters, a ''std::vector'' containing the proper C++ type fo the parameter. The generated code parses the comma separated strings to generate the ''std::vector''&lt;br /&gt;
&lt;br /&gt;
=== Using GenerateCLP ===&lt;br /&gt;
&lt;br /&gt;
GenerateCLP is normally used via CMake where it is implemented as a CUSTOM_COMMAND. To use GenerateCLP from CMake, you must first include the GenerateCLP package from your CMakeLists.txt file, which will make some macros available to you:&lt;br /&gt;
&lt;br /&gt;
  find_package(SlicerExecutionModel REQUIRED)&lt;br /&gt;
  include(${SlicerExecutionModel_USE_FILE})&lt;br /&gt;
&lt;br /&gt;
Note that the HelloSlicer command line module example provides a good starting point and can be used as a skeleton to build your own. It can be found in the [http://na-mic.org/ViewVC/index.cgi/trunk/Modules/CommandLineModule/Testing/HelloSlicer/?sortby=file#dirlist Modules/CommandLineModule/Testing/HelloSlicer] subdirectory.&lt;br /&gt;
&lt;br /&gt;
For each executable, include the following, replacing '''MyFilter''' with the name of your C++ source:&lt;br /&gt;
&lt;br /&gt;
  set('''MyFilter'''_SOURCE '''MyFilter'''.cxx)&lt;br /&gt;
  GENERATECLP('''MyFilter'''_SOURCE '''MyFilter'''.xml)&lt;br /&gt;
&lt;br /&gt;
To generate a stand-alone executable add the lines:&lt;br /&gt;
&lt;br /&gt;
  add_executable('''MyFilter''' ${'''MyFilter'''_SOURCE})&lt;br /&gt;
  target_link_libraries('''MyFilter''' ${ITK_LIBRARIES})&lt;br /&gt;
&lt;br /&gt;
Slicer expects modules and plugins to be stored in a specific subdirectory, so that they can be discovered and loaded at run-time. To make sure your CLP module is built in said subdirectory, add the line:&lt;br /&gt;
&lt;br /&gt;
  SEMMacroBuildCLI(&lt;br /&gt;
    NAME '''MyFilter'''&lt;br /&gt;
    LOGO_HEADER ${Slicer_SOURCE_DIR}/Resources/NAMICLogo.h&lt;br /&gt;
    ADDITIONAL_SRCS&lt;br /&gt;
      '''MyFilter'''.cxx&lt;br /&gt;
    TARGET_LIBRARIES ModuleDescriptionParser ${ITK_LIBRARIES} vtkTeem MRMLCore SlicerBaseCLI ${VTK_LIBRARIES}&lt;br /&gt;
    INCLUDE_DIRECTORIES&lt;br /&gt;
      ${vtkTeem_INCLUDE_DIRS}&lt;br /&gt;
      ${MRMLCore_INCLUDE_DIRS}&lt;br /&gt;
      ${vtkITK_INCLUDE_DIRS}&lt;br /&gt;
      ${SlicerBaseCLI_SOURCE_DIR} ${SlicerBaseCLI_BINARY_DIR}&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
The add_executable target creates a stand-alone executable that can be run from a command line. The add_library target creates a shared library that is discovered at Slicer 3 startup.&lt;br /&gt;
&lt;br /&gt;
Although this example linked to ITK libraries, other libraries can be specified.&lt;br /&gt;
&lt;br /&gt;
=== Short Example ===&lt;br /&gt;
&lt;br /&gt;
This example uses the XML for the [http://www.slicer.org/slicerWiki/index.php/Slicer3:Execution_Model_Documentation#Module_with_an_integer-vector.2C_one_input_image_and_one_output_image|Median Image Filter example].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Note:''' The program '''MUST NOT''' write anything to stdout before the ''PARSE_ARGS'' statement. If something is written, the plugin discovery mechanism will not recognize the program as a plugin.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;quot;MedianImageFilterCLP.h&amp;quot;&lt;br /&gt;
 int main (int argc, char * argv[])&lt;br /&gt;
  {&lt;br /&gt;
  PARSE_ARGS;&lt;br /&gt;
  std::cout &amp;lt;&amp;lt; &amp;quot;The size of the neighborhood is: &amp;quot; &amp;lt;&amp;lt; neighborhood.size()&lt;br /&gt;
    &amp;lt;&amp;lt; &amp;quot; and the first element of the neighborhood is: &amp;quot; &amp;lt;&amp;lt; neighborhood[0]&lt;br /&gt;
    &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
  std::cout &amp;lt;&amp;lt; &amp;quot;The input volume is: &amp;quot; &amp;lt;&amp;lt; inputVolume &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
  std::cout &amp;lt;&amp;lt; &amp;quot;The output volume is: &amp;quot; &amp;lt;&amp;lt; outputVolume &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
  return EXIT_SUCCESS;&lt;br /&gt;
  }&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is the output --help:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
USAGE: &lt;br /&gt;
&lt;br /&gt;
   ./MedianImageFilter  [--processinformationaddress &amp;lt;std::string&amp;gt;] [--xml]&lt;br /&gt;
                        [--echo] [--neighborhood &amp;lt;std::vector&amp;lt;int&amp;gt;&amp;gt;] [--]&lt;br /&gt;
                        [--version] [-h] &amp;lt;std::string&amp;gt; &amp;lt;std::string&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Where: &lt;br /&gt;
&lt;br /&gt;
   --processinformationaddress &amp;lt;std::string&amp;gt;&lt;br /&gt;
     Address of a structure to store process information (progress, abort,&lt;br /&gt;
     etc.). (default: 0)&lt;br /&gt;
&lt;br /&gt;
   --xml&lt;br /&gt;
     Produce xml description of command line arguments (default: 0)&lt;br /&gt;
&lt;br /&gt;
   --echo&lt;br /&gt;
     Echo the command line arguments (default: 0)&lt;br /&gt;
&lt;br /&gt;
   --neighborhood &amp;lt;std::vector&amp;lt;int&amp;gt;&amp;gt;&lt;br /&gt;
     The size of the neighborhood in each dimension (default: 1,1,1)&lt;br /&gt;
&lt;br /&gt;
   --,  --ignore_rest&lt;br /&gt;
     Ignores the rest of the labeled arguments following this flag.&lt;br /&gt;
&lt;br /&gt;
   --version&lt;br /&gt;
     Displays version information and exits.&lt;br /&gt;
&lt;br /&gt;
   -h,  --help&lt;br /&gt;
     Displays usage information and exits.&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;std::string&amp;gt;&lt;br /&gt;
     (required)  Input volume to be filtered&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;std::string&amp;gt;&lt;br /&gt;
     (required)  Output filtered&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   The MedianImageFilter is commonly used as a robust approach for noise&lt;br /&gt;
   reduction. This filter is particularly efficient against&lt;br /&gt;
   'salt-and-pepper' noise. In other words, it is robust to the presence of&lt;br /&gt;
   gray-level outliers. MedianImageFilter computes the value of each output&lt;br /&gt;
   pixel as the statistical median of the neighborhood of values around the&lt;br /&gt;
   corresponding input pixel.&lt;br /&gt;
&lt;br /&gt;
   Author(s): Bill Lorensen&lt;br /&gt;
&lt;br /&gt;
   Acknowledgements: This command module was derived from&lt;br /&gt;
   Insight/Examples/Filtering/MedianImageFilter (copyright) Insight&lt;br /&gt;
   Software Consortium&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters and C++ code ===&lt;br /&gt;
&lt;br /&gt;
This table shows how parameters are defined in the C++ code and how they are specified on the command line.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
! XML&lt;br /&gt;
! C++ Declaration&lt;br /&gt;
! Command Line&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;integer&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;count&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;flag&amp;gt;c&amp;lt;/flag&amp;gt; &amp;lt;/integer&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
int count;&lt;br /&gt;
|&lt;br /&gt;
''prog'' -c 10&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;float&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;stepSize&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;default&amp;gt;.0625&amp;lt;/default&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;longflag&amp;gt;stepSize&amp;lt;/longflag&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/float&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
float stepSize=.0625;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --stepSize .003&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;integer multiple=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;iterations&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;flag&amp;gt;i&amp;lt;/flag&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;default&amp;gt;100&amp;lt;/default&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/integer&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::vector&amp;lt;int&amp;gt; iterations;&amp;lt;br /&amp;gt; iterations.push_back(100);&amp;lt;br /&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
''prog'' -i 20 -i 30 -i 100&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;float-vector&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;variation&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;flag&amp;gt;v&amp;lt;/flag&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;default&amp;gt;1,2,3&amp;lt;/default&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/float-vector&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::vector&amp;lt;float&amp;gt; variation; iterations.push_back(1);&amp;lt;br /&amp;gt; iterations.push_back(2);&amp;lt;br /&amp;gt; iterations.push_back(3);&amp;lt;br /&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
''prog'' -v 10,20,3&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;string-vector&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;sites&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;longflag&amp;gt;sites&amp;lt;/longflag&amp;gt; &amp;lt;/string-vector&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::vector&amp;lt;std::string&amp;gt; sites;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --sites BWH,GE,Kitware,UNC,MIT,UTAH,GT&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;string-enumeration&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;leaders&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;default&amp;gt;Bill&amp;lt;/default&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;element&amp;gt;Ron&amp;lt;/element&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;element&amp;gt;Bill&amp;lt;/element&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;element&amp;gt;Steve&amp;lt;/element&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/string-enumeration&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::string leaders = &amp;quot;Bill&amp;quot;;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --leaders Ron&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;boolean&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;debugSwitch&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;flag&amp;gt;d&amp;lt;/flag&amp;gt; &amp;lt;default&amp;gt;true&amp;lt;/default&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/boolean&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
bool debugSwitch = true;&lt;br /&gt;
|&lt;br /&gt;
''prog'' -d&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;file&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;longflag&amp;gt;file1&amp;lt;/longflag&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;file&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::string file1;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --file1 mytext.txt&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;image&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;image&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;index&amp;gt;0&amp;lt;/index&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/image&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::string image;&lt;br /&gt;
|&lt;br /&gt;
''prog'' c:/lorensen/Data/ct.nrrd&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;file multiple=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;args&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;index&amp;gt;1&amp;lt;/index&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/file&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::vector&amp;lt;std::string&amp;gt; args;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --otherFlags file1 file2 ... filen&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;point multiple=&amp;quot;true&amp;quot; coordinateSystem=&amp;quot;ras&amp;quot;&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;seed&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;longflag&amp;gt;--seed&amp;lt;/longflag&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::vector&amp;lt;std::vector&amp;lt;float&amp;gt; &amp;gt; seed;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --seed 10,100,23 --seed 5,240,17&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Accessing Module Information at Runtime ==&lt;br /&gt;
&lt;br /&gt;
All of the information contained in the XML description of a module can be accessed at run-time by the command line program. The ''ModuleDescriptionParser'' class library can parse an XML module description and populate a ''ModuleDescription'' instance.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Module Description Parser Class Library&lt;br /&gt;
#include &amp;quot;ModuleDescriptionParser.h&amp;quot;&lt;br /&gt;
#include &amp;quot;ModuleDescription.h&amp;quot;&lt;br /&gt;
#include &amp;quot;ModuleParameterGroup.h&amp;quot;&lt;br /&gt;
#include &amp;quot;ModuleParameter.h&amp;quot;&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
// Create a module and a parser&lt;br /&gt;
    ModuleDescription module;&lt;br /&gt;
    ModuleDescriptionParser parser;&lt;br /&gt;
// Parse the XML&lt;br /&gt;
    if (parser.Parse(GetXMLModuleDescription(), module))&lt;br /&gt;
      {&lt;br /&gt;
      std::cerr &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &amp;quot;: One or more XML errors detected.&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
      return EXIT_FAILURE;&lt;br /&gt;
      }&lt;br /&gt;
// Access the module description information&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Module Description Information&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tCategory is: &amp;quot; &amp;lt;&amp;lt; module.GetCategory() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tTitle is: &amp;quot; &amp;lt;&amp;lt; module.GetTitle() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tDescription is: &amp;quot; &amp;lt;&amp;lt; module.GetDescription() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tVersion is: &amp;quot; &amp;lt;&amp;lt; module.GetVersion() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tDocumentationURL is: &amp;quot; &amp;lt;&amp;lt; module.GetDocumentationURL() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tLicense is: &amp;quot; &amp;lt;&amp;lt; module.GetLicense() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tContributor is: &amp;quot; &amp;lt;&amp;lt; module.GetContributor() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''GetXMLModuleDescription'' is automatically generated by ''GenerateCLP''. Information about parameter groups and parameters is also available [[Accessing_Module_Information_at_Runtime|here]].&lt;br /&gt;
&lt;br /&gt;
The ''CMakeLists.txt'' file that creates the command line module should point to the ''ModuleDescriptionParser'' library.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
target_link_libraries(${CLP}&lt;br /&gt;
    ModuleDescriptionParser&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Error Handling ==&lt;br /&gt;
&lt;br /&gt;
GenerateCLP attempts to do error checking so that the generated C++ code will compile. These errors will show up as custom command errors during the build process.&lt;br /&gt;
&lt;br /&gt;
* XML Errors&lt;br /&gt;
** ''mismatched tag at line xx'' : The closing tag (a tag with &amp;lt;/ &amp;gt;) does not have a matching opening tag.&lt;br /&gt;
** ''not well-formed (invalid token) at line xx'' : Probably a blank in the token name.&lt;br /&gt;
* ModuleDescriptionParser Errors&lt;br /&gt;
** ''&amp;lt;executable&amp;gt; must be the outer most tag''&lt;br /&gt;
** ''&amp;lt;executable&amp;gt; was found inside another tag''&lt;br /&gt;
** ''&amp;lt;parameters&amp;gt; can only be inside &amp;lt;executable&amp;gt;''&lt;br /&gt;
** ''&amp;lt;xxx&amp;gt; can only be used inside &amp;lt;parameters&amp;gt;''&lt;br /&gt;
** ''&amp;lt;flag&amp;gt; can only contain one character''&lt;br /&gt;
** ''&amp;lt;longname&amp;gt; can only contain letters, numbers and underscores and must start with an _ or letter''&lt;br /&gt;
** ''&amp;lt;name&amp;gt; can only contain letters, numbers and underscores and must start with an _ or letter''&lt;br /&gt;
&lt;br /&gt;
* ModuleDescriptionParser Warnings&lt;br /&gt;
** ''&amp;lt;xxx&amp;gt; is an unknown parameter tag'' : Probably a misspelled parameter type.&lt;br /&gt;
&lt;br /&gt;
* Compiler Errors&lt;br /&gt;
** The generated C++ code may have syntax errors if invalid defaults are specified. These will show up during the C++ compilation.&lt;br /&gt;
&lt;br /&gt;
== Interfacing Legacy Executables ==&lt;br /&gt;
&lt;br /&gt;
GenerateCLP is only provided as a convenience. Users can use the same XML Module Description to interface C++, shell scripts, tcl programs and even Matlab.&lt;br /&gt;
&lt;br /&gt;
Example: [http://www.slicer.org/slicerWiki/index.php/Slicer3:FiberTrackingIntegration FiberTracking Integration]&lt;br /&gt;
&lt;br /&gt;
== Showing Progress in an Application ==&lt;br /&gt;
&lt;br /&gt;
Programs can communicate progress to the user in two ways. If the program is running an a stand-alone executable, it communicates with a simple XML syntax. If the program is loaded at run-time as a plugin library, it communicates through a C structure.&lt;br /&gt;
&lt;br /&gt;
The XML syntax is:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;filter-start&amp;gt;&lt;br /&gt;
  &amp;lt;filter-name&amp;gt;&lt;br /&gt;
  ''name of program section or algorithm''&lt;br /&gt;
  &amp;lt;/filter-name&amp;gt;&lt;br /&gt;
  &amp;lt;filter-comment&amp;gt;&lt;br /&gt;
  ''description of program section or algorithm''&lt;br /&gt;
  &amp;lt;/filter-comment&amp;gt;&lt;br /&gt;
 &amp;lt;/filter-start&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;filter-progress&amp;gt;&lt;br /&gt;
 ''floating number from 0 to 1''&lt;br /&gt;
 &amp;lt;/filter-progress&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;filter-end&amp;gt;&lt;br /&gt;
  &amp;lt;filter-name&amp;gt;&lt;br /&gt;
  ''name of program section or algorithm''&lt;br /&gt;
  &amp;lt;/filter-name&amp;gt;&lt;br /&gt;
  &amp;lt;filter-time&amp;gt;&lt;br /&gt;
  ''execution time''&lt;br /&gt;
  &amp;lt;/filter-time&amp;gt;&lt;br /&gt;
 &amp;lt;/filter-end&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The C structure that library plugins use is:&lt;br /&gt;
&lt;br /&gt;
 extern &amp;quot;C&amp;quot; {&lt;br /&gt;
  struct ModuleProcessInformation&lt;br /&gt;
  {&lt;br /&gt;
    /** Inputs from calling application to the module **/&lt;br /&gt;
    unsigned char Abort;&lt;br /&gt;
    /** Outputs from the module to the calling application **/&lt;br /&gt;
    float Progress;&lt;br /&gt;
    char  ProgressMessage[1024];&lt;br /&gt;
    void (*ProgressCallbackFunction)(void *);&lt;br /&gt;
    void *ProgressCallbackClientData;&lt;br /&gt;
    double ElapsedTime;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Details on how to use this mechanism are illustrated in [https://github.com/Slicer/Slicer/blob/master/Base/CLI/itkPluginFilterWatcher.h itkPluginFilterWatcher.h].&lt;br /&gt;
&lt;br /&gt;
For vtk and itk execution model programs, two classes are available that make it simple to add progress. The classes, ''vtkPluginFilterWatcher'' and ''itk::PluginFilterWatcher'' use the vtk and itk command/observer mechanism to report progress.&lt;br /&gt;
&lt;br /&gt;
vtkPluginFilterWatcher (vtkAlgorithm *'''filter''', const char* '''comment''', ModuleProcessInformation *'''inf''', double '''fraction''', double '''start''') &amp;lt;br /&amp;gt; itk::PluginFilterWatcher (itk::ProcessObject '''filter''', const char* '''comment''', ModuleProcessInformation *'''inf''', double '''fraction''', double '''start''')&lt;br /&gt;
&lt;br /&gt;
: where:&lt;br /&gt;
;; filter &lt;br /&gt;
:: is the vtkAlgorithm or itk::ProcessObject to be watched.&lt;br /&gt;
;; comment &lt;br /&gt;
:: is a string that describes the algorithm.&lt;br /&gt;
;; inf &lt;br /&gt;
:: is an optional pointer to a structure that is used to communicate with the invoking program when the called program is used as a library plugin. If the pointer is 0, this prgram will not report progress if it is run as a library plugin. Default is 0.&lt;br /&gt;
;; fraction &lt;br /&gt;
:: is the fraction (0-1) of progress that will be reported by this watcher. This is used when multiple filters are run and each filter represents a proportion of the total progress. Default is 1.&lt;br /&gt;
;; start &lt;br /&gt;
:: is the offset (0-1) of the progress for this filter. This is added to the progress of the filter. The reported progress of the watched filter is ''start + fraction * filter_progress''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt; The following example produces progress for a simple vtk program. The variable CLPProcessInformation is automatically declared and set in the program's ''program''CLP.h file.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;quot;vtkPluginFilterWatcher.h&amp;quot;&lt;br /&gt;
 ...&lt;br /&gt;
  vtkMarchingCubes *cubes = vtkMarchingCubes::New();&lt;br /&gt;
    cubes-&amp;gt;SetInput(reader-&amp;gt;GetOutput());&lt;br /&gt;
  vtkPluginFilterWatcher watchCubes(cubes, &amp;quot;Generate Isosurface&amp;quot;, CLPProcessInformation, .5, 0.0);&lt;br /&gt;
  vtkDecimatePro *decimate = vtkDecimatePro::New();&lt;br /&gt;
    decimate-&amp;gt;SetInput(cubes-&amp;gt;GetOutput());&lt;br /&gt;
  vtkPluginFilterWatcher watchDecimate(decimate, &amp;quot;Reduce Triangle Count&amp;quot;, CLPProcessInformation, .5, 0.5);&lt;br /&gt;
  decimate-&amp;gt;Update();&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example produces progress for a simple itk program:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;quot;itkPluginFilterWatcher.h&lt;br /&gt;
 ...&lt;br /&gt;
 typedef itk::MedianImageFilter&amp;lt;ImageType,ImageType&amp;gt; FilterType;&lt;br /&gt;
 FilterType::Pointer median  = FilterType::New();&lt;br /&gt;
 itk::PluginFilterWatcher watchMedian(median, &amp;quot;Denoise Image&amp;quot;, CLPProcessInformation);&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Adding Module Logos to Slicer ==&lt;br /&gt;
Slicer plugins, both libraries and executables, can specify plugin-specific logos. These appear in Slicer when a module is selected. The logos are specified in a .h header file. The KWWidget utility, KWConvertImageToHeader, converts a .png file into a .h header file containing the encoded image and additional information such as width, height and pixel size. [[Documentation-3.5#Requirements_for_Modules|See here for additional information.]]&lt;br /&gt;
&lt;br /&gt;
For Slicer, execution model plugin logos are stored in Modules/CLI/Resources. The corresponding image in .png format should be stored in Modules/CLI/ImageData. Othere plugins, created outside the Slicer tree, should store the logo and image in a similar location.&lt;br /&gt;
&lt;br /&gt;
To add a logo to a plugin:&lt;br /&gt;
* Create a png image of the logo. The height of the logo should not exceed 40 pixels.&lt;br /&gt;
* Convert the logo to the KWWidget icon format as follows. '''NOTE:''' the prefix of the image and header file must be the same for a plugin logo.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd Modules/CLI&lt;br /&gt;
KWConvertImageToHeader --base64 --zlib Resources/ITKLogo.h ImageData/ITKLogo.png&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Add the logo to the SEMMacroBuildCLImacro in the CMakeLists.txt file for the plugin using LOGO_HEADER parameter.&lt;br /&gt;
&lt;br /&gt;
=== Runtime specification of filter types ===&lt;br /&gt;
&lt;br /&gt;
ITK filters are templated over the images they process. The following code snippet shows how an execution model program can select the image types for filters based on the input images.&lt;br /&gt;
&lt;br /&gt;
First, include the utilites for plugin's:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;itkPluginUtilities.h&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, turn your main program into a templated procedure called ''DoIt'':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
template&amp;lt;class T&amp;gt; int DoIt( int argc, char * argv[], T )&lt;br /&gt;
{&lt;br /&gt;
  PARSE_ARGS;&lt;br /&gt;
&lt;br /&gt;
  typedef itk::Image&amp;lt; T, 3 &amp;gt;   InputImageType;&lt;br /&gt;
  typedef itk::Image&amp;lt; T, 3 &amp;gt;   OutputImageType;&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Then, create a main program that gets the native component type from one of the input file. Here that input file is ''inputVolume'':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int main( int argc, char * argv[] )&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  PARSE_ARGS;&lt;br /&gt;
&lt;br /&gt;
  itk::ImageIOBase::IOPixelType pixelType;&lt;br /&gt;
  itk::ImageIOBase::IOComponentType componentType;&lt;br /&gt;
&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
    itk::GetImageType (inputVolume, pixelType, componentType);&lt;br /&gt;
&lt;br /&gt;
    // This filter handles all types&lt;br /&gt;
    &lt;br /&gt;
    switch (componentType)&lt;br /&gt;
      {&lt;br /&gt;
      case itk::ImageIOBase::UCHAR:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;unsigned char&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::CHAR:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;char&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::USHORT:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;unsigned short&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::SHORT:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;short&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::UINT:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;unsigned int&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::INT:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;int&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::ULONG:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;unsigned long&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::LONG:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;long&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::FLOAT:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;float&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::DOUBLE:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;double&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::UNKNOWNCOMPONENTTYPE:&lt;br /&gt;
      default:&lt;br /&gt;
        std::cout &amp;lt;&amp;lt; &amp;quot;unknown component type&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  catch( itk::ExceptionObject &amp;amp;excep)&lt;br /&gt;
    {&lt;br /&gt;
    std::cerr &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &amp;quot;: exception caught !&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cerr &amp;lt;&amp;lt; excep &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    return EXIT_FAILURE;&lt;br /&gt;
    }&lt;br /&gt;
  return EXIT_SUCCESS;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Behind the Scenes ==&lt;br /&gt;
&lt;br /&gt;
A primary goal of the execution model is to relieve developers from developing GUI code and command line parsing code. This section describes the major components of the execution model implementation.&lt;br /&gt;
&lt;br /&gt;
=== Command Line Processing ===&lt;br /&gt;
&lt;br /&gt;
Command line processing parses command line arguments and populates internal program variables. Every Unix (and windows) program can receive an argument list through its main entry point. All C and C++ programmers are familiar with the ''int main (int argc, char *[] argv)'' entry point in their programs. Most computer languages including scripting languages provide a similar mechanism to retrieve command line arguments. Simple command line processing directly accesses the strings defined in argv.&lt;br /&gt;
&lt;br /&gt;
This snippet shows simple commmand line processing:&lt;br /&gt;
&lt;br /&gt;
 int main (int argc, char *argv[])&lt;br /&gt;
 {&lt;br /&gt;
   if (argc &amp;lt; 2)&lt;br /&gt;
     {&lt;br /&gt;
     std::cout &amp;lt;&amp;lt; &amp;quot;Usage: &amp;quot; &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &amp;quot; filename&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
     return -1;&lt;br /&gt;
     }&lt;br /&gt;
   std::cout &amp;lt;&amp;lt; &amp;quot;The File is &amp;quot; &amp;lt;&amp;lt; argv[1] &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The simple approach works great for a small number of arguments. But larger numbers of arguments of varying types quickly make the processing code more complex and subject to error, both in coding and usage.&lt;br /&gt;
&lt;br /&gt;
 int main (int argc, char *argv[])&lt;br /&gt;
 {&lt;br /&gt;
   if (argc &amp;lt; 5)&lt;br /&gt;
     {&lt;br /&gt;
     std::cout &amp;lt;&amp;lt; &amp;quot;Usage: &amp;quot; &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &amp;quot; iterations epsilon inputfile outputfile &amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
     return -1;&lt;br /&gt;
     }&lt;br /&gt;
   std::string inputfile(argv[3]);&lt;br /&gt;
   std::string outputfile(argv[4]);&lt;br /&gt;
   unsigned int iterations = atoi(argv[1]);&lt;br /&gt;
   float epsilon = atof(argv[2]);&lt;br /&gt;
 ...&lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Adding flags (or options) to the command line makes the program easier to use but places a larger burden on the program developer. Each developer must ''invent'' a command line argument syntax and implement code to parse the command line. Even a simple example of this is too long to include in this description. This code snippet looks for just two command line arguments.&lt;br /&gt;
&lt;br /&gt;
 int main (int argc, char *argv[])&lt;br /&gt;
 {&lt;br /&gt;
   if (argc &amp;lt; 3)&lt;br /&gt;
     {&lt;br /&gt;
     std::cout &amp;lt;&amp;lt; &amp;quot;Usage: &amp;quot; &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &amp;quot; [-i iterations] [-e epsilon] inputfile outputfile &amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
     return -1;&lt;br /&gt;
     }&lt;br /&gt;
   std::string inputfile;&lt;br /&gt;
   std::string outputfile;&lt;br /&gt;
   unsigned int iterations = 10; /* a default */&lt;br /&gt;
   float epsilon = .001; /* a defualt */&lt;br /&gt;
   ++argc; /* skip program name */&lt;br /&gt;
   while (argc &amp;gt; 0)&lt;br /&gt;
     {&lt;br /&gt;
     if (strcmp(argv[argc], &amp;quot;-i&amp;quot;)&lt;br /&gt;
      {&lt;br /&gt;
      iterations = atoi(argv[argc+1]);&lt;br /&gt;
      argc+=2;&lt;br /&gt;
      continue;&lt;br /&gt;
 &lt;br /&gt;
    else if (strcmp(argv[argc], &amp;quot;-e&amp;quot;)&lt;br /&gt;
      {&lt;br /&gt;
      epsilon = atof(argv[argc+1]);&lt;br /&gt;
      argc+=2;&lt;br /&gt;
      continue;&lt;br /&gt;
    ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The code gets longer and longer as more options are added and must be rewritten every time a new programs is open.&lt;br /&gt;
&lt;br /&gt;
To solve this complexity issue, people have developed command line argument libraries. There are dozens, if not hundreds, of command line processing tools. For Slicer3 we looked at argument processors in vxl, nrrd, meta, kwsys and tclap. Each has its strengths and weaknesses. We chose [http://tclap.sourceforge.net/ The Templatized C++ Command Line Parser Library], '''TCLAP'''. '''TCLAP''' is implemented in ''include'' files and does not require a separate library build. As you will see later, the particular command line processing tool is, for the most part, transparent to the Slicer3 developer or user.&lt;br /&gt;
&lt;br /&gt;
But even these libraries require some work to use.&lt;br /&gt;
&lt;br /&gt;
==== TCLAP ====&lt;br /&gt;
&lt;br /&gt;
This example uses '''TCLAP''' to process a command line with 10 possible entries:&lt;br /&gt;
&lt;br /&gt;
 int main ( int argc, char* argv[] ) {&lt;br /&gt;
  //&lt;br /&gt;
  // Define default values&lt;br /&gt;
  int HistogramBins      = 30;&lt;br /&gt;
  int RandomSeed         = 1234567;&lt;br /&gt;
  int SpatialSamples     = 10000;&lt;br /&gt;
  float TranslationScale = 100.0;&lt;br /&gt;
  int Iterations         = 200;&lt;br /&gt;
  int SplineOrder        = 3;&lt;br /&gt;
  double MinimumStepSize = 0.00001;&lt;br /&gt;
  double MaximumStepSize = 0.005;&lt;br /&gt;
  bool PrintTransform    = false;&lt;br /&gt;
  string fixedImageFileName;&lt;br /&gt;
  string movingImageFileName;&lt;br /&gt;
  string resampledImageFileName;&lt;br /&gt;
  //&lt;br /&gt;
  // Setup command line parsing&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
    TCLAP::CmdLine cl ( &amp;quot;Register2d&amp;quot;, ' ', &amp;quot;$Revision: 1.1 $&amp;quot; );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;int&amp;gt;    HistogramBinsArg    ( &amp;quot;b&amp;quot;, &amp;quot;histogrambins&amp;quot;,    &amp;quot;Number of histogram bins&amp;quot;, false, 30, &amp;quot;integer&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;int&amp;gt;    IterationsArg       ( &amp;quot;i&amp;quot;, &amp;quot;iterations&amp;quot;,       &amp;quot;Number of Iterations&amp;quot;, false, Iterations, &amp;quot;int&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;double&amp;gt; MinimumStepSizeArg  ( &amp;quot;m&amp;quot;, &amp;quot;minstepsize&amp;quot;,      &amp;quot;Minimum Step Size&amp;quot;, false, MinimumStepSize, &amp;quot;double&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;double&amp;gt; MaximumStepSizeArg  ( &amp;quot;x&amp;quot;, &amp;quot;maxstepsize&amp;quot;,      &amp;quot;Maximum Step Size&amp;quot;, false, MaximumStepSize, &amp;quot;double&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;int&amp;gt;    RandomSeedArg       ( &amp;quot;r&amp;quot;, &amp;quot;randomseed&amp;quot;,       &amp;quot;Random Seed&amp;quot;, false, RandomSeed, &amp;quot;int&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;int&amp;gt;    SpatialSamplesArg   ( &amp;quot;s&amp;quot;, &amp;quot;spatialsamples&amp;quot;,   &amp;quot;Number of spatial samples&amp;quot;, false, SpatialSamples, &amp;quot;int&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;int&amp;gt;    SplineOrderArg      ( &amp;quot;o&amp;quot;, &amp;quot;splineorder&amp;quot;,      &amp;quot;Order of spline for registration&amp;quot;, false, SplineOrder, &amp;quot;int&amp;quot;, cl );&lt;br /&gt;
    TCLAP::SwitchArg        PrintTransformArg   ( &amp;quot;p&amp;quot;, &amp;quot;printtransform&amp;quot;,   &amp;quot;Print the final transform&amp;quot;, PrintTransform, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;float&amp;gt;  TranslationScaleArg ( &amp;quot;t&amp;quot;, &amp;quot;translationscale&amp;quot;, &amp;quot;Translation scale&amp;quot;, false, TranslationScale, &amp;quot;float&amp;quot;, cl );&lt;br /&gt;
    TCLAP::UnlabeledValueArg&amp;lt;string&amp;gt; FixedImageArg ( &amp;quot;fixed&amp;quot;, &amp;quot;Fixed image filename&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;string&amp;quot;, cl );&lt;br /&gt;
    TCLAP::UnlabeledValueArg&amp;lt;string&amp;gt; MovingImageArg ( &amp;quot;moving&amp;quot;, &amp;quot;Moving image filename&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;string&amp;quot;, cl );&lt;br /&gt;
    TCLAP::UnlabeledValueArg&amp;lt;string&amp;gt; ResampledImageArg ( &amp;quot;resampled&amp;quot;, &amp;quot;Resampled image filename&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;string&amp;quot;, cl );&lt;br /&gt;
    //&lt;br /&gt;
    // Parse the command line&lt;br /&gt;
    cl.parse ( argc, argv );&lt;br /&gt;
    //&lt;br /&gt;
    // Access the variables&lt;br /&gt;
    HistogramBins          = HistogramBinsArg.getValue();&lt;br /&gt;
    Iterations             = IterationsArg.getValue();&lt;br /&gt;
    MinimumStepSize        = MinimumStepSizeArg.getValue();&lt;br /&gt;
    MaximumStepSize        = MaximumStepSizeArg.getValue();&lt;br /&gt;
    RandomSeed             = RandomSeedArg.getValue();&lt;br /&gt;
    SpatialSamples         = SpatialSamplesArg.getValue();&lt;br /&gt;
    TranslationScale       = TranslationScaleArg.getValue();&lt;br /&gt;
    PrintTransform         = PrintTransformArg.getValue();&lt;br /&gt;
    fixedImageFileName     = FixedImageArg.getValue();&lt;br /&gt;
    movingImageFileName    = MovingImageArg.getValue();&lt;br /&gt;
    resampledImageFileName = ResampledImageArg.getValue();&lt;br /&gt;
    }&lt;br /&gt;
  catch ( ArgException e )&lt;br /&gt;
    {&lt;br /&gt;
    cerr &amp;lt;&amp;lt; &amp;quot;error: &amp;quot; &amp;lt;&amp;lt; e.error() &amp;lt;&amp;lt; &amp;quot; for arg &amp;quot; &amp;lt;&amp;lt; e.argId() &amp;lt;&amp;lt; endl;&lt;br /&gt;
    exit ( EXIT_FAILURE );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
You do get a lot for your investment here. Good error handling and help.&lt;br /&gt;
&lt;br /&gt;
=== Module Description Parser ===&lt;br /&gt;
The XML parsing is done by the [https://github.com/Slicer/SlicerExecutionModel/tree/master/ModuleDescriptionParser ModuleDescriptionParser] class library. ''GenerateCLP'' and Slicer3 use this class library to parse the module XML descriptions. The class ''ModuleDescriptionParser'' has one method, '''Parse''', that converts the XML description into an object model. The resulting object model has one ''ModuleDescription'', one or more ''ModuleParameterGroup'' each of which has one or more ''ModuleParameter''. Each instance has access methods to retrieve information from the XML.&lt;br /&gt;
* '''ModuleDescriptionParser''' - parser for command line module XML description.&lt;br /&gt;
*: ''Parse(std::string xml, ModuleDescription module)'' - parse an xml string and populate a ModuleDescription.&lt;br /&gt;
* '''ModuleDescription''' - contains information about a module &lt;br /&gt;
*: const std::string ''GetCategory()'' : returns the contents of '''&amp;lt;category&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetTitle()'' : returns the contents of '''&amp;lt;title&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetDescription()'' : returns the contents of '''&amp;lt;description&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetVersion()'' : returns the contents of '''&amp;lt;version&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetDocumentationURL()'' : returns the contents of '''&amp;lt;documentationURL&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetLicense()'' : returns the contents of '''&amp;lt;license&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetContributor()'' : returns the contents of '''&amp;lt;contributor&amp;gt;'''.&lt;br /&gt;
*: const std::vector&amp;lt;ModuleParameterGroup&amp;gt;&amp;amp; ''GetParameterGroups()'' : returns a vector of parameter groups.&lt;br /&gt;
* '''ModuleParameterGroup''' - contains ModuleParameters for each parameter group.&lt;br /&gt;
*: const std::string ''GetLabel'' - returns the contents of '''&amp;lt;label&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetDescription()'' - returns the contents of the parameter group's '''&amp;lt;description&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetAdvanced()'' - returns advanced attribute. Either &amp;quot;true&amp;quot; of &amp;quot;false&amp;quot;.&lt;br /&gt;
* '''ModuleParameter''' - contains information for a parameter.&lt;br /&gt;
*:GetTag() - returns the parameter's tag, e.g. '''&amp;lt;integer&amp;gt;, &amp;lt;image&amp;gt;''', etc.&lt;br /&gt;
*:GetName() - returns the parameter's '''&amp;lt;name&amp;gt;'''.&lt;br /&gt;
*:GetLongFlag() -  returns the parameter's '''&amp;lt;longflag&amp;gt;'''.&lt;br /&gt;
*:GetLabel() -  returns the parameter's '''&amp;lt;label&amp;gt;'''.&lt;br /&gt;
*:GetMaximum() -  returns the parameter's '''&amp;lt;maximum&amp;gt;''' constraint.&lt;br /&gt;
*:GetMinimum() -  returns the parameter's '''&amp;lt;minimum&amp;gt;''' constraint.&lt;br /&gt;
*:GetStep() -  returns the parameter's '''&amp;lt;step&amp;gt;'''.&lt;br /&gt;
*:GetDescription() -  returns the parameter's '''&amp;lt;description&amp;gt;'''.&lt;br /&gt;
*:GetChannel() -  returns the parameter's '''&amp;lt;channel&amp;gt;'''.&lt;br /&gt;
*:GetIndex() -  returns the parameter's '''&amp;lt;index&amp;gt;'''.&lt;br /&gt;
*:GetDefault() -  returns the parameter's '''&amp;lt;default&amp;gt;'''.&lt;br /&gt;
*:GetFlag() -  returns the parameter's '''&amp;lt;flag&amp;gt;'''.&lt;br /&gt;
*:GetMultiple() -  returns the parameter's multiple attribute, either &amp;quot;true&amp;quot; or &amp;quot;false&amp;quot;.&lt;br /&gt;
*:GetCoordinateSystem() -  returns the parameter's coordinate system attribute, one of &amp;quot;lps&amp;quot;, &amp;quot;ras&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
= Adding a new parameter type =&lt;br /&gt;
&lt;br /&gt;
Adding a ''new parameter type'' to the execution model involves several modifications:&lt;br /&gt;
&lt;br /&gt;
# A new XML tag needs to be defined to represent the new parameter type.&lt;br /&gt;
# ModuleDescriptionParser needs to be modified to parse the new parameter tag type and specify how the command line processing code generation is going to represent the parameter type&lt;br /&gt;
# CommandLineModuleGUI needs to be modified to construct the appropriate GUI element for the parameter type&lt;br /&gt;
# CommandLineModuleLogic needs to be modified to put the parameter type onto the command line and request outputs parameter types be loaded back into Slicer and the MRML tree.&lt;br /&gt;
# SlicerApplicationLogic needs to be modified to ingest any output parameter types back into Slicer and the MRML tree.&lt;br /&gt;
# Additional modification are needed if the parameter is to be passed directly from the MRML tree without using the filesystem.&lt;br /&gt;
# Updating the documentation.&lt;br /&gt;
&lt;br /&gt;
Simple parameter types can be passed directly on the command line.  For instance, scalars, small lists, positions, etc. Complicated parameter types are passed to the module via '''abstract files'''. In some cases, these parameters are actually passed as files, where Slicer reads/write the data to the filesystem.  In other cases, the parameters are passed as '''abstract files''' which are really references to within the Slicer memory model but appear to the Command Line Module as being a file.  The Command Line Module is written using standard ITK ImageFileReader/ImageFileWriter classes but the ITK ImageIO factory mechanism is used to direct the ImageFileReader/ImageFileWriter to talk directly to the Slicer MRML tree instead of to the filesystem.&lt;br /&gt;
&lt;br /&gt;
== XML tag ==&lt;br /&gt;
&lt;br /&gt;
This is by far the easiest of the tasks involved in adding a new parameter type but it should not approached hastily. The XML description of a module is designed to be application agnostic. As such, parameter types should be described abstractly or generically.  For instance, '''&amp;lt;geometry&amp;gt;''' tag corresponds to the Slicer model node, the '''&amp;lt;point&amp;gt;''' tag corresponds to the Slicer fiducial node, etc.&lt;br /&gt;
&lt;br /&gt;
Once the tag name is defined, you need to decide whether the parameter type could or should support the attributes '''multiple''', '''coordinateSystem''', or '''fileExtensions''' or perhaps a new attribute type.&lt;br /&gt;
&lt;br /&gt;
== Modifying ModuleDescriptionParser ==&lt;br /&gt;
&lt;br /&gt;
SlicerExecutionModel/ModuleDescriptionParser/ModuleDescriptionParser.cxx contains the code to parse the XML description of a module and represent that module description in C++ data structures.  To add a new parameter type, this code needs to be modified.&lt;br /&gt;
&lt;br /&gt;
Two routines need to be modified in ModuleDescriptionParser, ''startElement()'' and ''endElement()''. For ''startElement()'', a new case block needs to be added for the parameter type.  You can start by copying the case block for a similar parameter type. This case block is responsible for processing all the attributes for the tag and managing and reporting any errors. The case block may define the '''CPPType''', the ''ArgType''', and the '''StringToType''' needed for the code generation of the command line parsing. The '''CPPType''' is used by in the generated command line processing code to represent the parameter.  This may be a simple C++ type or an STL container. The '''ArgType''' is the canonical type of each component of the parameter. The '''StringToType''' is the name of the method to use to convert the ASCII command line parameter to the final '''ArgType'''. The ''endElement()'' method merely needs a new case block to add the parameter to the description.&lt;br /&gt;
&lt;br /&gt;
ModuleDescriptionParser is fairly general, handling scalars, lists of scalars, and file types as parameter types. A parameter which does not fit these models will require considerable alterations to the ModuleDescriptionParser as well as the GenerateCLP.&lt;br /&gt;
&lt;br /&gt;
== Constructing a GUI for a new parameter type ==&lt;br /&gt;
&lt;br /&gt;
To have a GUI element appear in the module GUI for a new parameter type, Base\QTCLI\qSlicerCLIModuleUIHelper.cxx and Base\QTCLI\vtkSlicerCLIModuleLogic.cxx have to be modified. A new case block needs to be added to the '''BuildGUI()''' method for the new parameter type.  This case block is triggered off the XML tag for the parameter type. The case block is responsible for the constructing the appropriate GUI element for the parameter, complete with specifying the label and help text. The design is very simple.  A single widget is used for each parameter.  If a more complicated GUI is needed with multiple widgets, then perhaps a new widget is needed to encapsulated a set of widgets or a naming convention can be added to manage all the widgets associated with a parameter. The widgets for the parameters are stored in a map, indexed by the '''name''' of the parameter.&lt;br /&gt;
&lt;br /&gt;
The vtkCommandLineModuleGUI (and vtkCommandLineModuleLogic) are designed to operate very generically with sets of parameters. The aforementioned map of widgets indexed by parameter '''name''' is one such example.  The implementation of several of the methods in the vtkCommandLineModuleGUI (and vtkCommandLineModuleLogic) generically iterate over the widget map or over the parameter list. It is important to keep this in mind as new parameters are added.  The design goal is to minimize the number of ''special cases'' in the code.&lt;br /&gt;
&lt;br /&gt;
Note that there may be separate case blocks for '''input''' and '''output''' parameter types.&lt;br /&gt;
&lt;br /&gt;
== Communicating the new parameter to the Command Line Module ==&lt;br /&gt;
&lt;br /&gt;
To communicate the new parameter type to and from a Command Line Module, the '''ApplyTask()''' method Slicer3/Modules/CommandLineModule/vtkCommandLineModuleLogic.cxx needs to be modified. &lt;br /&gt;
&lt;br /&gt;
If the parameter type is communicated to the command line module as a file (as opposed to directly on the command line as a number or srting), then there are several blocks of code to construct a temporary file name, keep track of whether that node needs to be written to the filesystem before execution, read from the filesystem after the execution, and deleted after execution completes. These blocks may need to be modified based on your new parameter type.&lt;br /&gt;
&lt;br /&gt;
The command line is constructed in two passes.  First, a pass is made over the parameter list, building the portion of the command line for any parameters that have flags.  Note that whether a parameter has a flag or not is up to the discretion of the module author and is not defined by the parameter type.  Second, a pass is made to construction the portion of the command  line for the parameters that do not have flags. These parameters are ordered appropriately, then placed on the command line. For parameters with flags, this code emits the flag and the parameter value.  For the parameters without flags, this code emits just the parameter value.  You will need to edit both of these passes to emit your parameter type.  In most cases, this is simply a matter of grabbing the parameter value from the parameter and pushing it onto the command line.  But some parameter types do require translation to a string appropriate for the command line.&lt;br /&gt;
&lt;br /&gt;
== Output parameters from the Command Line Modules ==&lt;br /&gt;
&lt;br /&gt;
Any outputs from a Command Line Module that are communicated via files are queued to be read by the main application thread. Command Line Modules run in a separate execution thread from the main GUI.  This thread is not allowed to modify the Slicer GUI, so any results from the module that need to be read back into Slicer and displayed are queued for the main thread.&lt;br /&gt;
&lt;br /&gt;
The '''ProcessReadData()''' method of Slicer3/Base/Logic/vtkSlicerApplicationLogic.cxx pulls data from the queue to load back into Slicer and display. You may need to a case block for your new parameter type to construct the appropriate storage node and display node.&lt;br /&gt;
&lt;br /&gt;
== Communicating directly with the MRML tree ==&lt;br /&gt;
&lt;br /&gt;
Currently scalar image types can sent as parameters to shared object command line modules without going through the filesystem.  Slicer provides a new ITK ImageIO factory that can communicated directly with the Slicer MRML tree. This ImageIO factory is in Slicer/Libs/MRMLIDImageIO. This approach can be extended for other image types such as vector or tensor volumes.&lt;br /&gt;
&lt;br /&gt;
For other constructs such as models and transforms, we'll need to see if an existing factory mechanism can be leverage to communicate directly with the Slicer MRML tree. An alternative may be to construct bridges specific to interfacing from a command line module to the Slicer MRML tree.&lt;br /&gt;
&lt;br /&gt;
== Adding new image types ==&lt;br /&gt;
&lt;br /&gt;
The Command Line Module support scalar, vector, tensor, and diffusion weighted images. Adding a new image type to the Command Line Module requires modify the sections of the code outlined above to manage GUI for the module, to construct temporary file names, to write image to disk, and load them back into the MRML tree.  These blocks are easy to identify as case blocks on vtkMRMLScalarVolumeNode, vtkMRMLDiffusionTensorVolumeNode, etc. Note that the '''&amp;lt;image&amp;gt;''' tag supports a '''type''' attribute that can scalar, label, vector, tensor, or diffusion-weighted.  The case block for '''image''' in the '''startElement()''' method of ModuleDescriptionParser would need to be extended to recognize a new type of image.&lt;br /&gt;
&lt;br /&gt;
=FAQ=&lt;br /&gt;
&lt;br /&gt;
==What facilities are available for third party software to interface with the NA-MIC Kit?==&lt;br /&gt;
&lt;br /&gt;
NA-MIC has committed to developing and supporting a generic batch processing interface.  This is the Slicer3 Command Line Interface (CLI). The application programming interface (API) for CLI was worked out based on interactions with the community including input from those familiar with LONI, ITK, Python and Matlab software development practices.&lt;br /&gt;
&lt;br /&gt;
We believe this API already supports all the features required by to implement batch processing with BatchMake, the LONI Pipeline, and any other systems that we may want to work with in the future.  The [[Slicer3:Execution_Model_Documentation|Slicer3 Execution Model]] provides a simple XML-based descriptor for command line arguments for input/output volumes and related parameters.&lt;br /&gt;
&lt;br /&gt;
==Which Third Party software has currently been interfaced to the NA-MIC Kit using the CLI?==&lt;br /&gt;
&lt;br /&gt;
*Batchmake (Kitware)&lt;br /&gt;
*Python&lt;br /&gt;
*Matlab&lt;br /&gt;
&lt;br /&gt;
== How do I debug my command line module? ==&lt;br /&gt;
&lt;br /&gt;
See [http://www.slicer.org/slicerWiki/index.php/Slicer3:Execution_Model_Documentation:Debugging Debugging]&lt;br /&gt;
&lt;br /&gt;
== How do I specify a Logo? ==&lt;br /&gt;
&lt;br /&gt;
You need to create a logo.h file (embedding the zipped pixel data as base64 strings in a C source code).  There is a utility bundled with kwwidgets that accomplishes this.  From a Slicer3 build directory you can do something like this:&lt;br /&gt;
&lt;br /&gt;
 ./Slicer3 --launch ../Slicer3-lib/KWWidgets-build/bin/KWConvertImageToHeader --base64 --zlib ~/Desktop/bioimagesuite_logo_www.h ~/Desktop/bioimagesuite_logo_www.png&lt;br /&gt;
&lt;br /&gt;
The resulting .h header file can then be used as an argument to the 'generateclp' cmake macro like this:&lt;br /&gt;
&lt;br /&gt;
 generateclp(${CLP}_SOURCE ${CLP}.xml ${Slicer3_SOURCE_DIR}/Resources/bioimagesuite_logo_www.h)&lt;br /&gt;
&lt;br /&gt;
''Note: logos are limited in size: if your .h file contains a symbol like 'image_bioimagesuite_logo_www' it will work.  But if it has several symbols like 'image_bioimagesuite_logo_www_1' 'image_bioimagesuite_logo_www_2' etc then the logo was too large and needs to be downsampled for use.''&lt;br /&gt;
&lt;br /&gt;
== What do I do if I want to use the CLI outside of slicer? ==&lt;br /&gt;
&lt;br /&gt;
In general CLI executables will depend on shared libraries provided by Slicer (such as ITKCommon, etc).  To be sure your run-time environment resolves to the correct versions, you should always use a form like:&lt;br /&gt;
 ./Slicer3 --launch &amp;lt;CLI&amp;gt;&lt;br /&gt;
or, you can start a shell from which you can run multiple CLI modules.  Something like:&lt;br /&gt;
 ./Slicer3 --launch xterm &amp;amp;&lt;br /&gt;
&lt;br /&gt;
We do not suggest hard-coding the runtime paths into, for example, your .bashrc since this may interfere with other programs and can make it hard to use multiple versions of slicer on the same account.&lt;br /&gt;
&lt;br /&gt;
= Laundry List =&lt;br /&gt;
&lt;br /&gt;
Use this section to describe any features that are missing, not documented, or require additional work.&lt;br /&gt;
&lt;br /&gt;
* Comments from Hans Johnson, June 4, 2010:&lt;br /&gt;
** Enumerated types can only have about 3 characters in them, otherwise they don’t render in the slicer wizard at all.&lt;br /&gt;
** There is no way to unset an enumerated type, and the values are cached even after leaving the module.  If the default enumerated type is to be blank, and you select it, then you must restart slicer in order to make the blank option available again.&lt;br /&gt;
** There is no way to have conditional options.  For example if one flag is used, then other flag can not be used, so it should be disabled.&lt;br /&gt;
* Multiple images, transforms, etc. cannot be selected in the module user interface shown in Slicer (https://issues.slicer.org/view.php?id=4299)&lt;br /&gt;
* Documenting your module:&lt;br /&gt;
** a convenience script has been developed by Hans Johnson, which creates a wiki page describing the command line module by extracting the information from the xml description [[SEMToMediaWiki.py]]. TODO: extract the default values for the parameters to be included in the documentation&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/SlicerExecutionModel&amp;diff=60932</id>
		<title>Documentation/Nightly/Developers/SlicerExecutionModel</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/SlicerExecutionModel&amp;diff=60932"/>
		<updated>2019-03-20T16:47:08Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add forward reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The Slicer Execution Model is designed to improve the acceptance and productivity of Slicer application developers. The Execution Model provides a simple mechanism for incorporating command line programs as Slicer modules. These command line modules are self-describing, emitting an XML description of its command line arguments. Slicer uses this XML description to construct a GUI for the module.&lt;br /&gt;
&lt;br /&gt;
=== Types of Slicer Plugins ===&lt;br /&gt;
&lt;br /&gt;
There are various types of plugins that Slicer supports as command line modules. This variety allows a breadth of integration choices to balance performance and flexibility.&lt;br /&gt;
&lt;br /&gt;
==== Shared object plugins (dll, so) with global symbols ====&lt;br /&gt;
&lt;br /&gt;
Shared object plugins with global symbols integrate into Slicer tighter than the Executable plugins.  Shared object plugins with global symbols can transfer data directly to/from a MRML scene using standard itk::ImageFileReader and itk::ImageFileWriter (and the ImageIO class provided with Slicer, itk::MRMLIDImageIO).  Communicating directly with the MRML scene avoids the overhead of reading and writing images to disk.  Slicer looks for a standard entry point to execute the module called ModuleEntryPoint defined as&lt;br /&gt;
&lt;br /&gt;
 int ModuleEntryPoint(int argc, char* argv[]);&lt;br /&gt;
&lt;br /&gt;
Slicer also looks for the global symbols XMLModuleDescription, ModuleLogoImage, ModuleLogoWidth, ModuleLogoHeight, ModuleLogoPixelSize, and ModuleLogoLength.  These global symbols provide the xml module description and data for the module logo. The data types for these symbols are&lt;br /&gt;
&lt;br /&gt;
          char *XMLModuleDescription;&lt;br /&gt;
 unsigned char *ModuleLogoImage;&lt;br /&gt;
           int  ModuleLogoWidth;&lt;br /&gt;
           int  ModuleLogoHeight;&lt;br /&gt;
           int  ModuleLogoPixelSize;&lt;br /&gt;
 unsigned long  ModuleLogoLength;&lt;br /&gt;
&lt;br /&gt;
These global symbols are accessed during module discovery. The ModuleLogoImage, ModuleLogoWidth, ModuleLogoHeight, ModuleLogoPixelSize, and ModuleLogoLength are optional.&lt;br /&gt;
&lt;br /&gt;
=====Controlling what symbols are exported from a shared library module=====&lt;br /&gt;
&lt;br /&gt;
Shared Object Modules are loaded into Slicer using standard &amp;quot;dlopen&amp;quot; style calls. The ModuleEntryPoint is located within the shared library and cached for later use. The ModuleEntryPoint, however, may not be the only function accessible to Slicer within the shared library. To protect against symbol clash at runtime, all functions and variables accessible within file scope of the shared library should be put in an anonymous namespace.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Use an anonymous namespace to keep class types and function names&lt;br /&gt;
// from colliding when module is used as shared object module.  Every&lt;br /&gt;
// thing should be in an anonymous namespace except for the module&lt;br /&gt;
// entry point, e.g. main() or ModuleEntryPoint()&lt;br /&gt;
//&lt;br /&gt;
namespace {&lt;br /&gt;
    // functions like DoIt() should be put in the anonymous namespace&lt;br /&gt;
    template&amp;lt;class T&amp;gt; int DoIt( int argc, char * argv[], const T&amp;amp; targ)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
} // end of anonymous namespace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[] )&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Shared object plugins (dll, so) with entry points ====&lt;br /&gt;
&lt;br /&gt;
Shared object plugins with entry points integrate into Slicer tighter than the Executable plugins. Shared object plugins with entry points can transfer data directly to/from a MRML scene using standard itk::ImageFileReader and itk::ImageFileWriter (and the ImageIO class provided with Slicer, itk::MRMLIDImageIO). Communicating directly with the MRML scene avoids the overhead of reading and writing images to disk. Slicer looks for standard entry points for executing the module as well as for querying the module for its xml description and logos. The entry points are defined as&lt;br /&gt;
&lt;br /&gt;
           int  ModuleEntryPoint(int argc, char* argv[]);&lt;br /&gt;
          char *GetXMLModuleDescription();&lt;br /&gt;
 unsigned char *GetModuleLogo()(int *width, int *height, int *pixel_size, unsigned long *bufferLength);&lt;br /&gt;
&lt;br /&gt;
GetXMLModuleDescription() and GetModuleLogo() are accessed during module discovery. GetModuleLogo() is optional.&lt;br /&gt;
&lt;br /&gt;
==== Executable plugins with global symbols ====&lt;br /&gt;
&lt;br /&gt;
Executable plugins with global symbols allow for a single executable to be developed that can be integrated into Slicer 3 or run standalone on a cluster. Plugins of this type are opened but not executed at module discovery time.  Slicer 3 looks for the global symbols XMLModuleDescription, ModuleLogoImage, ModuleLogoWidth, ModuleLogoHeight, ModuleLogoPixelSize, and ModuleLogoLength.  The data types for these symbols are&lt;br /&gt;
 &lt;br /&gt;
          char *XMLModuleDescription;&lt;br /&gt;
 unsigned char *ModuleLogoImage;&lt;br /&gt;
           int  ModuleLogoWidth;&lt;br /&gt;
           int  ModuleLogoHeight;&lt;br /&gt;
           int  ModuleLogoPixelSize;&lt;br /&gt;
 unsigned long  ModuleLogoLength;&lt;br /&gt;
&lt;br /&gt;
These global symbols are access during module discovery. ModuleLogoImage, ModuleLogoWidth, ModuleLogoHeight, ModuleLogoPixelSize, ModuleLogoLength are optional.&lt;br /&gt;
&lt;br /&gt;
==== Executable plugins (exe) with command line options ====&lt;br /&gt;
&lt;br /&gt;
Executable plugins with command line options are the most flexible type of plugin. This approach allows for legacy applications to be integrated into Slicer using a wrapper around the legacy application.  Plugins of this type are executed at module discovery time, passing in the command line argument &amp;quot;--xml&amp;quot;. The plugin responds to the &amp;quot;--xml&amp;quot; query by emitting the xml description of the module. The plugin is also executed at module discovery time with a &amp;quot;--logo&amp;quot; command line argument. The plugin responds to the &amp;quot;--logo&amp;quot; query by emitting a logo description. &lt;br /&gt;
&lt;br /&gt;
This type of plugin allows for legacy applications to be integrated into Slicer. A developer can provide Slicer with a small executable or shell script that responds to the &amp;quot;--xml&amp;quot; and &amp;quot;--logo&amp;quot; command line arguments needed for Slicer 3 integration and otherwise spawns the legacy executable passing down any command line arguments.&lt;br /&gt;
&lt;br /&gt;
 &amp;gt; module.exe --xml&lt;br /&gt;
 &amp;gt; module.exe --logo&lt;br /&gt;
&lt;br /&gt;
==== Script plugins with Python ====&lt;br /&gt;
&lt;br /&gt;
Python scripts are found using the discovery mechanisms for the other plugins. Since Python plugins are fundamentally different from the shared and executable plugins, they are documented on their own [[Documentation/Nightly/Developers/SlicerExecutionModel/Python|page]].&lt;br /&gt;
&lt;br /&gt;
=== Calling Command Line Modules from Other Code ===&lt;br /&gt;
&lt;br /&gt;
In addition to the automated GUI that shows up in the Slicer user interface, the Execution Model can be used to encapsulate functionality that is invoked by other parts of the program.  For instance, the Editor Module can invoke the Model Maker Module to build models.  By invoking a command line module in this way, you get the advantage of background processing with progress reporting.  See [[Documentation/Nightly/Developers/SlicerExecutionModel/Programmatic Invocation|this page]] for more details.&lt;br /&gt;
&lt;br /&gt;
=== Architecture === &lt;br /&gt;
[[Image:ExecutionModelPlugins.png|600px|Plugin architecture]]&lt;br /&gt;
[[Image:CommandLineModule.png|400px|Module architecture]]&lt;br /&gt;
[[Image:ModuleFactory.png|400px|Module factory ]]&lt;br /&gt;
[[Image:Class_parser_state_coll_graph.png|400px|Module description]]&lt;br /&gt;
&lt;br /&gt;
== Module Description ==&lt;br /&gt;
&lt;br /&gt;
Modules are described using XML. The XML is used to generate the C++ command line code and the GUI for the application.&lt;br /&gt;
&lt;br /&gt;
=== XML Schema ===&lt;br /&gt;
&lt;br /&gt;
At a minimum, each module description must contain:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;executable&amp;gt;&lt;br /&gt;
 &amp;lt;title&amp;gt;A title&amp;lt;/title&amp;gt;&lt;br /&gt;
 &amp;lt;description&amp;gt;A description&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
   At least one parameter&lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &amp;lt;/executable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the following descriptions of each XML tag, CLP means command line processing and GUI means graphical user interface. Unless otherwise specified, tags are optional.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;executable&amp;gt; (required)&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;category&amp;gt;&lt;br /&gt;
:: Classifies the executable (e.g. Filtering, Segmentation). Category can be a ''dot'' separated string. Multiple categories can be given and should be separated by a ''semicolon''.&lt;br /&gt;
:: ''for CLP'', not used.&lt;br /&gt;
:: ''for GUI'', used on the menu selector to group executables. ''Dot'' separated strings can be used to generate sub-menus. ''Semicolon'' separated strings can be used to create multiple categories.&lt;br /&gt;
;; &amp;lt;/category&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;title&amp;gt; (required)&lt;br /&gt;
:: A word or two describing the executable (e.g. Median Filter, Anisotropic Diffusion&lt;br /&gt;
:: ''for CLP'', not used.&lt;br /&gt;
:: ''for GUI'', used to label the frame containing the GUI for the executable. Also, GUI names for volumes use this label as a prefix.&lt;br /&gt;
;; &amp;lt;/title&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;description&amp;gt; (required)&lt;br /&gt;
:: A long description of the executable. Any double quotes will be converted to single quotes.&lt;br /&gt;
:: ''for CLP'', appears at the end of the --help.&lt;br /&gt;
:: ''for GUI'', appears in the help frame.&lt;br /&gt;
;; &amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;version&amp;gt;&lt;br /&gt;
:: The version of the command line executable. A suggested format is:&lt;br /&gt;
::: ''major''.''minor''.''patch''.''build''.''status''&lt;br /&gt;
::: where status is&lt;br /&gt;
:::: vc: version controlled (pre-alpha), build can be a serial revision number, if any (like svn might have).&lt;br /&gt;
:::: a: alpha&lt;br /&gt;
:::: b: beta&lt;br /&gt;
:::: rc: release candidate&lt;br /&gt;
:::: fcs: first customer ship&lt;br /&gt;
:: ''for CLP'', reported in response to --version.&lt;br /&gt;
:: ''for GUI'', not used.&lt;br /&gt;
;; &amp;lt;/version&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;documentation-url&amp;gt;&lt;br /&gt;
:: The location of extended documentation for the executable, (e.g. http://www.na-mic.org/foo.html).&lt;br /&gt;
;; &amp;lt;/documentation-url&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;license&amp;gt;&lt;br /&gt;
:: The type of license or a url containing the license, (e.g. Berkeley, Apache, http://www.slicer.org/copyright/copyright.txt).&lt;br /&gt;
:: ''for CLP'', not used.&lt;br /&gt;
:: ''for GUI'', may show up in the Help or About section.&lt;br /&gt;
;; &amp;lt;/license&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;contributor&amp;gt;&lt;br /&gt;
:: The author(s) of the command line executable (e.g. Pieper, Jim Miller).&lt;br /&gt;
:: for ''CLP'', appears as part of --help&lt;br /&gt;
:: for ''GUI'', may show up in the Help or About section.&lt;br /&gt;
;; &amp;lt;/contributor&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;acknowledgements&amp;gt;&lt;br /&gt;
:: Acknowledgements for funding agency, employer, colleague, (e.g. This work is part of the National Alliance for Medical Image Computing NAMIC), funded by the National Institutes of Health through the NIH Roadmap for Medical Research, Grant U54 EB005149).&lt;br /&gt;
:: for ''CLP'', appears as part of --help&lt;br /&gt;
:: for ''GUI'', may show up in the Help of About section.&lt;br /&gt;
;; &amp;lt;/acknowledgements&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;; &amp;lt;parameters [advanced=&amp;quot;true|''false''&amp;quot;]&amp;gt; (required for each group of parameters)&lt;br /&gt;
:: Starts a group of parameters.&lt;br /&gt;
:: for ''CLP'', not used.&lt;br /&gt;
:: for ''GUI'', defines a widget (in tk, a frame) that contains other widgets. If ''advanced'' is true, the frame will be closed initially.&lt;br /&gt;
&lt;br /&gt;
;;; &amp;lt;label&amp;gt; (required)&lt;br /&gt;
::: A short string that summarizes a parameter group, (e.g. I/O, Diffusion)&lt;br /&gt;
::: for ''CLP'', not used.&lt;br /&gt;
::: for ''GUI'', used to label the frame.&lt;br /&gt;
;;; &amp;lt;/label&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;; &amp;lt;description&amp;gt; (required)&lt;br /&gt;
::: A short description of the parameter group, (e.g. Input/Output Parameters, Anitostropic Diffusion Parameters). Any double quotes will be converted to single quotes.&lt;br /&gt;
::: ''for CLP'', not used.&lt;br /&gt;
::: ''for GUI'', used in balloon help for the frame containing the parameter group.&lt;br /&gt;
;;; &amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;; &amp;lt;integer&amp;gt; | &amp;lt;float&amp;gt; | &amp;lt;double&amp;gt; | &amp;lt;boolean&amp;gt; | &amp;lt;string&amp;gt; | &amp;lt;integer-vector&amp;gt; | &amp;lt;float-vector&amp;gt; | &amp;lt;double-vector&amp;gt; | &amp;lt;string-vector&amp;gt; | &amp;lt;integer-enumeration&amp;gt; | &amp;lt;float-enumeration&amp;gt; | &amp;lt;double-enumeration&amp;gt; | &amp;lt;string-enumeration&amp;gt; | &amp;lt;file&amp;gt; | &amp;lt;directory&amp;gt; | &amp;lt;image [type=&amp;quot;''scalar''|''label''|''tensor''|''diffusion-weighted''|''vector''|''model''&amp;quot;] [reference=&amp;quot;...&amp;quot;] &amp;gt; | &amp;lt;geometry [type=&amp;quot;''fiberbundle''|''model''&amp;quot;] [reference=&amp;quot;...&amp;quot;]&amp;gt; | &amp;lt;point [multiple=&amp;quot;''true''|''false''&amp;quot;] [coordinateSystem=&amp;quot;''lps''|''ras''&amp;quot;]&amp;gt; | &amp;lt;pointfile [multiple=&amp;quot;''true''|''false''&amp;quot;] [coordinateSystem=&amp;quot;''lps''|''ras''&amp;quot;]&amp;gt; | &amp;lt;region [multiple=&amp;quot;''true''|''false''&amp;quot;] [coordinateSystem=&amp;quot;''lps''|''ras''&amp;quot;]&amp;gt; | &amp;amp;lt;table [type=&amp;quot;''color''&amp;quot;] [fileExtensions=&amp;quot;''.tsv''|''.csv''|''.txt''|''.ctbl''&amp;quot;]&amp;gt; | &amp;lt;transform [type=&amp;quot;''linear''|''nonlinear''|''bspline''&amp;quot;] [reference=&amp;quot;...&amp;quot;] fileExtensions=&amp;quot;.tfm,.h5,.hdf5,.mat,.txt&amp;quot;&amp;gt;&lt;br /&gt;
::: The type of the parameter. &lt;br /&gt;
:::: The scalar types ('''integer''', '''float''', etc.) correspond to the usual programming language types. &lt;br /&gt;
:::: The '''-vector''' types are represented by comma separated values of the scalar type. &lt;br /&gt;
:::: The '''-enumeration''' types use the '''&amp;lt;element&amp;gt;''' tag to enumerate choices of the scalar type. &lt;br /&gt;
:::: '''&amp;lt;image&amp;gt;''' is a special type that indicates that the parameter is a file name that specifies images.&lt;br /&gt;
:::: The &amp;lt;region&amp;gt; parameter can be used to specify rectangular ROIs. The command-line syntax is --region X_center,Y_center,Z_center,X_radius,Y_Radius,Z_Radius.&lt;br /&gt;
:::: If the attribute ''multiple'' is &amp;quot;true&amp;quot;, multiple arguments are allowed for '''scalar''', '''file''', '''directory''', '''image''', '''geometry''', '''point''', '''pointfile''' and '''region''' parameters. BUG: the automatically built GUI will not support selecting multiple volumes for the '''image''' argument, but they can be passed on the command line. If the parameter has a ''flag'' or ''longflag'', then the flag may be specified multiple times on the command line. The resulting C++ variable will be a std::vector of the scalar type. If the multiple parameter does not have a flag, then multiple arguments can appear on the command line. However, a multiple parameter with no flags must be the last parameter specified.&lt;br /&gt;
:::: The attribute ''coordinateSystem'' is allowed for the parameters '''point''', '''pointfile''' and '''region'''. &lt;br /&gt;
:::: The attribute ''fileExtensions'' is allowed for '''file''', '''pointfile''', '''image''', '''transform''' and '''geometry'''. fileExtensions can contain a list of comma separated file extensions for optional use by the GUI.&lt;br /&gt;
:::: Transform types: If not specified then any transform is accepted (linear, non-linar, composite, ...). By specifying a type, accepted transforms can be limited to 'linear' = any linear transform; 'non-linear' = grid, displacement field; 'bspline' = b-spline transform.&lt;br /&gt;
:::: The attribute ''reference'' can mean different things based on the parameter type. If  the parameter is a transform and the reference is transformable, then the transform hierarchy of the reference is manipulated such that the reference is under the transform. If the parameter is an image or a model, then the parameter is placed in subject hierarchy at the same level as the reference. If the parameter is an image, reference will be used to initialize lookup table of the output image.&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;name&amp;gt; (required if longflag is not specified)&lt;br /&gt;
:::: The name of a command line argument. If name is not specified, longflag will be used (e.g. conductance, numberOfIterations). The name must be usable as a C++ variable. For example, it CANNOT have spaces or special characters and must start with a letter.&lt;br /&gt;
:::: ''for CLP'', the name of the C++ variable.&lt;br /&gt;
:::: ''for GUI'', used internally.&lt;br /&gt;
;;;; &amp;lt;/name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;description&amp;gt; (required)&lt;br /&gt;
:::: A brief description of the parameter. Any double quotes will be converted to single quotes.&lt;br /&gt;
:::: ''for CLP'', describes the parameter for --usage and --help.&lt;br /&gt;
:::: ''for GUI'', describes the parameter when the cursor is placed over the widget for the parameter (balloon help).&lt;br /&gt;
;;;; &amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;label&amp;gt; (required)&lt;br /&gt;
:::: A label for parameter (e.g. Dicom Directory, Conductance).&lt;br /&gt;
:::: ''for'' CLP, not used.&lt;br /&gt;
:::: ''for'' GUI, the label for the parameter widget.&lt;br /&gt;
;;;; &amp;lt;/label&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;default&amp;gt;&lt;br /&gt;
:::: A default value for the parameter. The default must be a type that is compatible with the parameter type. The vector parameters are specified as comma separated values of the atomic parameter type.&lt;br /&gt;
:::: ''for CLP'', contains the default for the parameter unless the parameter is a ''boolean''. The default for ''boolean'' parameters is always set to ''false''.&lt;br /&gt;
:::: ''for GUI'', contains the default for the parameter.&lt;br /&gt;
;;;; &amp;lt;/default&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;flag [alias=&amp;quot;a,b&amp;quot;] [deprecatedalias=&amp;quot;c,d&amp;quot;]&amp;gt; (not required if longflag is present)&lt;br /&gt;
:::: A single character command line flag (e.g. s, W). Can provide &amp;quot;alias&amp;quot;'s (comma separated) if different flags can be used to activate the same parameter.  Can provide &amp;quot;deprecatedalias&amp;quot;'s (comma separated) if different flags can be used to set the same parameter but the user should be notified of which &amp;quot;updated&amp;quot; flag to use. Parameters with flags are considered &amp;quot;optional&amp;quot; and do not have be specified or assigned.  Parameters with flags allow one to override a default behavior.&lt;br /&gt;
:::: ''for CLP'', used as the short flag on the command line.&lt;br /&gt;
:::: ''for GUI'', used when running the module.&lt;br /&gt;
;;;; &amp;lt;/flag&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;longflag [alias=&amp;quot;foo,bar&amp;quot;] [deprecatedalias=&amp;quot;garf&amp;quot;]&amp;gt; (not required if flag is present)&lt;br /&gt;
:::: A command line flag (e.g. spacing, Watcher). Can provide &amp;quot;alias&amp;quot;'s (comma separated) if different long flags can be used to activate the same parameter.  Can provide &amp;quot;deprecatedalias&amp;quot;'s (comma separated) if different long flags can be used to set the same parameter but the user should be notified of which &amp;quot;updated&amp;quot; long flag to use. Parameters with flags are considered &amp;quot;optional&amp;quot; and do not have be specified or assigned.  Parameters with flags allow one to override a default behavior.&lt;br /&gt;
:::: Note: apparently you can't use hyphens in the longflag, so things like --my-option are not allows.  -gcs&lt;br /&gt;
:::: ''for CLP'', used as the long flag on the command line.&lt;br /&gt;
:::: ''for GUI'', used when running the module.&lt;br /&gt;
;;;; &amp;lt;/longflag&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;constraints&amp;gt;&lt;br /&gt;
:::: Encloses constraints on the value of a non-vector, non-enumerated parameter.&lt;br /&gt;
:::: ''for CLP'', not used.&lt;br /&gt;
:::: ''for GUI'', if present, a slider will be created using the minimum, maximum and step specified.&lt;br /&gt;
&lt;br /&gt;
;;;;; &amp;lt;minimum&amp;gt;&lt;br /&gt;
::::: The minimum allowed value for the parameter. If not specified, the minimum is the smallest possible value for the parameter type.&lt;br /&gt;
;;;;; &amp;lt;/minimum&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;;; &amp;lt;maximum&amp;gt;&lt;br /&gt;
::::: The maximum allowed value for the parameter. If not specified, the maximum is the largest possible value for the parameter type.&lt;br /&gt;
;;;;; &amp;lt;/maximum&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;;; &amp;lt;step&amp;gt;&lt;br /&gt;
::::: The increment for the parameter.&lt;br /&gt;
;;;;; &amp;lt;/step&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;/constraints&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;channel&amp;gt; (required for file, pointfile, directory and image parameters)&lt;br /&gt;
:::: Specifies whether the parameter is an input or output parameter.&lt;br /&gt;
:::: ''for CLP'', not used.&lt;br /&gt;
:::: ''for GUI'', selects the proper widget for file handling.&lt;br /&gt;
;;;; &amp;lt;/channel&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;index&amp;gt; (required if there are no flags specified)&lt;br /&gt;
:::: An integer starting at 0, that specifies a command line argument that has no flags.&lt;br /&gt;
:::: Note: if you use index for, say, an image, the user must enter some input value into the GUI.  If the user does not fill in a value, the plugin is not run at all.  However, slicer will &amp;quot;seem&amp;quot; to run it, and no error message is given.  -gcs&lt;br /&gt;
:::: ''for CLP'', specifies the order of an argument that has no flags.&lt;br /&gt;
:::: ''for GUI'', used when running the module.&lt;br /&gt;
;;;; &amp;lt;/index&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;enumeration&amp;gt; (required for enumeration parameters)&lt;br /&gt;
:::: Encloses elements for the parameter. The parameter is restricted one and only one element.&lt;br /&gt;
:::: ''for CLP'', not used.&lt;br /&gt;
:::: ''for GUI'', defines a radio button with choices.&lt;br /&gt;
&lt;br /&gt;
;;;;; &amp;lt;element&amp;gt;&lt;br /&gt;
::::: Defines the choice. Must be of the proper type for a parameter.&lt;br /&gt;
::::: ''for CLP'', not used.&lt;br /&gt;
::::: ''for GUI'', used as the label for the radio button.&lt;br /&gt;
;;;;; &amp;lt;/element&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;/enumeration&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;;;; &amp;lt;reference [role=&amp;quot;foo&amp;quot;] [parameter=&amp;quot;bar&amp;quot;]/&amp;gt;&lt;br /&gt;
:::: A forward reference from the parameter to another parameter &amp;quot;bar&amp;quot; with the reference role &amp;quot;foo&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
;;; &amp;lt;/integer&amp;gt; | &amp;lt;/float&amp;gt; | &amp;lt;/double&amp;gt; | &amp;lt;/boolean&amp;gt; | &amp;lt;/string&amp;gt; | &amp;lt;/integer-vector&amp;gt; | &amp;lt;/float-vector&amp;gt; | &amp;lt;/double-vector&amp;gt; | &amp;lt;/string-vector&amp;gt; | &amp;lt;/integer-enumeration&amp;gt; | &amp;lt;/float-enumeration&amp;gt; | &amp;lt;/double-enumeration&amp;gt; | &amp;lt;/string-enumeration&amp;gt; | &amp;lt;/file&amp;gt; | &amp;lt;/directory&amp;gt; | &amp;lt;/image&amp;gt; | &amp;lt;/geometry&amp;gt; | &amp;lt;/point&amp;gt; | &amp;lt;/pointfile&amp;gt; | &amp;lt;/region&amp;gt; | &amp;amp;lt;/table&amp;gt; | &amp;lt;/transform&amp;gt;&lt;br /&gt;
;; &amp;lt;/parameters&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;/executable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Slicer GUI Generation ==&lt;br /&gt;
&lt;br /&gt;
Slicer generates GUI's for each executable discovered during the startup process. Slicer searches directories stored in the Slicer Module Path. This path is set from the Slicer application in View-&amp;gt;Application Settings-&amp;gt;Modules-&amp;gt;Additional module paths. Slicer attempts to run every executable in the prescribed directories and look for a valid XML file in response to a &amp;quot;--xml&amp;quot; command line.&lt;br /&gt;
&lt;br /&gt;
Here are a few representative examples.&lt;br /&gt;
&lt;br /&gt;
=== A tour of the Execution Model XML ===&lt;br /&gt;
&lt;br /&gt;
This example is a sampler of the parameters available in the Execution Model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;floatright&amp;quot;&amp;gt;&amp;lt;span&amp;gt;[[Image:ExectionModelTourGUI.png|[[Image:ExectionModelTourGUI.png]]]]&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;executable&amp;gt;&lt;br /&gt;
   &amp;lt;category&amp;gt;Tours&amp;lt;/category&amp;gt;&lt;br /&gt;
   &amp;lt;title&amp;gt;Execution Model Tour&amp;lt;/title&amp;gt;&lt;br /&gt;
   &amp;lt;description&amp;gt;&lt;br /&gt;
   Shows one of each type of parameter.&lt;br /&gt;
   &amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;
   &amp;lt;documentation-url&amp;gt;&amp;lt;/documentation-url&amp;gt;&lt;br /&gt;
   &amp;lt;license&amp;gt;&amp;lt;/license&amp;gt;&lt;br /&gt;
   &amp;lt;contributor&amp;gt;Daniel Blezek&amp;lt;/contributor&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Scalar Parameters&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;&lt;br /&gt;
     Variations on scalar parameters&lt;br /&gt;
     &amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;integer&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;integerVariable&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;flag&amp;gt;i&amp;lt;/flag&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;integer&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;&lt;br /&gt;
       An integer without constraints&lt;br /&gt;
       &amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Integer Parameter&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;30&amp;lt;/default&amp;gt;&lt;br /&gt;
     &amp;lt;/integer&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Scalar Parameters With Constraints&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Variations on scalar parameters&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;double&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;doubleVariable&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;flag&amp;gt;d&amp;lt;/flag&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;double&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;An double with constraints&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Double Parameter&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;30&amp;lt;/default&amp;gt;&lt;br /&gt;
       &amp;lt;constraints&amp;gt;&lt;br /&gt;
         &amp;lt;minimum&amp;gt;0&amp;lt;/minimum&amp;gt;&lt;br /&gt;
         &amp;lt;maximum&amp;gt;1.e3&amp;lt;/maximum&amp;gt;&lt;br /&gt;
         &amp;lt;step&amp;gt;0&amp;lt;/step&amp;gt;&lt;br /&gt;
       &amp;lt;/constraints&amp;gt;&lt;br /&gt;
     &amp;lt;/double&amp;gt;&lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Vector Parameters&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Variations on vector parameters&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;float-vector&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;floatVector&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;flag&amp;gt;f&amp;lt;/flag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;A vector of floats&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Float Vector Parameter&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;1.3,2,-14&amp;lt;/default&amp;gt;&lt;br /&gt;
     &amp;lt;/float-vector&amp;gt;&lt;br /&gt;
     &amp;lt;string-vector&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;stringVector&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;string_vector&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;A vector of strings&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;String Vector Parameter&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;&amp;quot;foo&amp;quot;,bar,&amp;quot;foobar&amp;quot;&amp;lt;/default&amp;gt;&lt;br /&gt;
     &amp;lt;/string-vector&amp;gt;&lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Enumeration Parameters&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Variations on enumeration parameters&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;string-enumeration&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;stringChoice&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;flag&amp;gt;e&amp;lt;/flag&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;enumeration&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;An enumeration of strings&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;String Enumeration Parameter&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;foo&amp;lt;/default&amp;gt;&lt;br /&gt;
       &amp;lt;element&amp;gt;foo&amp;lt;/element&amp;gt;&lt;br /&gt;
       &amp;lt;element&amp;gt;&amp;quot;foobar&amp;quot;&amp;lt;/element&amp;gt;&lt;br /&gt;
       &amp;lt;element&amp;gt;foofoo&amp;lt;/element&amp;gt;&lt;br /&gt;
     &amp;lt;/string-enumeration&amp;gt;&lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &amp;lt;/executable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Module with an integer-vector, one input image and one output image ===&lt;br /&gt;
&lt;br /&gt;
Here is the XML that describes the MedianImageFilter. The image on the right shows the generated Slicer 3 GUI. The help frame has been expanded by the user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;floatright&amp;quot;&amp;gt;&amp;lt;span&amp;gt;[[Image:MedianFilterGUI.png|[[Image:MedianFilterGUI.png]]]]&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;executable&amp;gt;&lt;br /&gt;
  &amp;lt;category&amp;gt;&lt;br /&gt;
  Filtering.Denoising&lt;br /&gt;
  &amp;lt;/category&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;&lt;br /&gt;
  Median Filter&lt;br /&gt;
  &amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;description&amp;gt;&lt;br /&gt;
The MedianImageFilter is commonly used as a robust approach for&lt;br /&gt;
noise reduction. This filter is particularly efficient against&lt;br /&gt;
&amp;quot;salt-and-pepper&amp;quot; noise. In other words, it is robust to the presence&lt;br /&gt;
of gray-level outliers. MedianImageFilter computes the value of each output&lt;br /&gt;
pixel as the statistical median of the neighborhood of values around the&lt;br /&gt;
corresponding input pixel.&lt;br /&gt;
  &amp;lt;/description&amp;gt;&lt;br /&gt;
  &amp;lt;version&amp;gt;0.1.0.$Revision: 2085 $(alpha)&amp;lt;/version&amp;gt;&lt;br /&gt;
  &amp;lt;documentation-url&amp;gt;&amp;lt;/documentation-url&amp;gt;&lt;br /&gt;
  &amp;lt;license&amp;gt;&amp;lt;/license&amp;gt;&lt;br /&gt;
  &amp;lt;contributor&amp;gt;Bill Lorensen&amp;lt;/contributor&amp;gt;&lt;br /&gt;
  &amp;lt;acknowledgements&amp;gt;This command module was derived from&lt;br /&gt;
Insight/Examples/Filtering/MedianImageFilter (copyright) Insight Software Consortium&lt;br /&gt;
  &amp;lt;/acknowledgements&amp;gt;&lt;br /&gt;
  &amp;lt;parameters&amp;gt;&lt;br /&gt;
    &amp;lt;label&amp;gt;Median Filter Parameters&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;description&amp;gt;Parameters for the median filter&amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;integer-vector&amp;gt;&lt;br /&gt;
      &amp;lt;name&amp;gt;neighborhood&amp;lt;/name&amp;gt;&lt;br /&gt;
      &amp;lt;longflag&amp;gt;--neighborhood&amp;lt;/longflag&amp;gt;&lt;br /&gt;
      &amp;lt;description&amp;gt;The size of the neighborhood in each dimension&amp;lt;/description&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Neighborhood Size&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;1,1,1&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/integer-vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/parameters&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;parameters&amp;gt;&lt;br /&gt;
    &amp;lt;label&amp;gt;IO&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;description&amp;gt;Input/output parameters&amp;lt;/description&amp;gt;&lt;br /&gt;
    &amp;lt;image&amp;gt;&lt;br /&gt;
      &amp;lt;name&amp;gt;inputVolume&amp;lt;/name&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Input Volume&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;channel&amp;gt;input&amp;lt;/channel&amp;gt;&lt;br /&gt;
      &amp;lt;index&amp;gt;0&amp;lt;/index&amp;gt;&lt;br /&gt;
      &amp;lt;description&amp;gt;Input volume to be filtered&amp;lt;/description&amp;gt;&lt;br /&gt;
    &amp;lt;/image&amp;gt;&lt;br /&gt;
    &amp;lt;image&amp;gt;&lt;br /&gt;
      &amp;lt;name&amp;gt;outputVolume&amp;lt;/name&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Output Volume&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
      &amp;lt;index&amp;gt;1&amp;lt;/index&amp;gt;&lt;br /&gt;
      &amp;lt;description&amp;gt;Output filtered&amp;lt;/description&amp;gt;&lt;br /&gt;
      &amp;lt;reference role=&amp;quot;source&amp;quot; parameter=&amp;quot;inputVolume&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/image&amp;gt;&lt;br /&gt;
  &amp;lt;/parameters&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/executable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Module with a multiple scalars, one Input image and one output image ===&lt;br /&gt;
&lt;br /&gt;
A module with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;floatright&amp;quot;&amp;gt;&amp;lt;span&amp;gt;[[Image:AnisotropicDiffusionFilterGUI.png|[[Image:AnisotropicDiffusionFilterGUI.png]]]]&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;executable&amp;gt;&lt;br /&gt;
   &amp;lt;category&amp;gt;filtering&amp;lt;/category&amp;gt;&lt;br /&gt;
   &amp;lt;title&amp;gt;Anisotropic Diffusion&amp;lt;/title&amp;gt;&lt;br /&gt;
   &amp;lt;description&amp;gt;&lt;br /&gt;
   Runs anisotropic diffusion on a volume&lt;br /&gt;
   &amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;
   &amp;lt;documentation-url&amp;gt;&amp;lt;/documentation-url&amp;gt;&lt;br /&gt;
   &amp;lt;license&amp;gt;&amp;lt;/license&amp;gt;&lt;br /&gt;
   &amp;lt;contributor&amp;gt;Bill Lorensen&amp;lt;/contributor&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;&lt;br /&gt;
     Anisotropic Diffusion Parameters&lt;br /&gt;
     &amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;&lt;br /&gt;
     Parameters for the anisotropic&lt;br /&gt;
     diffusion algorithm&lt;br /&gt;
     &amp;lt;/description&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;double&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;conductance&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;conductance&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;Conductance&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Conductance&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;1&amp;lt;/default&amp;gt;&lt;br /&gt;
       &amp;lt;constraints&amp;gt;&lt;br /&gt;
         &amp;lt;minimum&amp;gt;0&amp;lt;/minimum&amp;gt;&lt;br /&gt;
         &amp;lt;maximum&amp;gt;10&amp;lt;/maximum&amp;gt;&lt;br /&gt;
         &amp;lt;step&amp;gt;.01&amp;lt;/step&amp;gt;&lt;br /&gt;
       &amp;lt;/constraints&amp;gt;&lt;br /&gt;
     &amp;lt;/double&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;double&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;timeStep&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;timeStep&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;Time Step&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Time Step&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;0.0625&amp;lt;/default&amp;gt;&lt;br /&gt;
       &amp;lt;constraints&amp;gt;&lt;br /&gt;
         &amp;lt;minimum&amp;gt;.001&amp;lt;/minimum&amp;gt;&lt;br /&gt;
         &amp;lt;maximum&amp;gt;1&amp;lt;/maximum&amp;gt;&lt;br /&gt;
         &amp;lt;step&amp;gt;.001&amp;lt;/step&amp;gt;&lt;br /&gt;
       &amp;lt;/constraints&amp;gt;&lt;br /&gt;
     &amp;lt;/double&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;integer&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;numberOfIterations&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;longflag&amp;gt;iterations&amp;lt;/longflag&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;Number of iterations&amp;lt;/description&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Iterations&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;default&amp;gt;1&amp;lt;/default&amp;gt;&lt;br /&gt;
       &amp;lt;constraints&amp;gt;&lt;br /&gt;
         &amp;lt;minimum&amp;gt;1&amp;lt;/minimum&amp;gt;&lt;br /&gt;
         &amp;lt;maximum&amp;gt;30&amp;lt;/maximum&amp;gt;&lt;br /&gt;
         &amp;lt;step&amp;gt;1&amp;lt;/step&amp;gt;&lt;br /&gt;
       &amp;lt;/constraints&amp;gt;&lt;br /&gt;
     &amp;lt;/integer&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   &amp;lt;parameters&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;IO&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Input/output parameters&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;image&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;inputVolume&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Input Volume&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;channel&amp;gt;input&amp;lt;/channel&amp;gt;&lt;br /&gt;
       &amp;lt;index&amp;gt;0&amp;lt;/index&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;Input volume to be filtered&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;/image&amp;gt;&lt;br /&gt;
     &amp;lt;image&amp;gt;&lt;br /&gt;
       &amp;lt;name&amp;gt;outputVolume&amp;lt;/name&amp;gt;&lt;br /&gt;
       &amp;lt;label&amp;gt;Output Volume&amp;lt;/label&amp;gt;&lt;br /&gt;
       &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
       &amp;lt;index&amp;gt;1&amp;lt;/index&amp;gt;&lt;br /&gt;
       &amp;lt;description&amp;gt;Output filtered&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;/image&amp;gt;&lt;br /&gt;
   &amp;lt;/parameters&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/executable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Module with output text presented in GUI ===&lt;br /&gt;
&lt;br /&gt;
Slicer auto generates GUI to display output from the command line module after execution is complete.&lt;br /&gt;
The flag [--returnparameterfile &amp;lt;file name&amp;gt;] is used to provide a name of a file that the module uses to store key=value pairs that are displayed in the Slicer GUI. The keys are described in the command line module xml schema using the output channel.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates a portion of an XML schema containing  1 string-enumeration input and 7 string outputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;floatright&amp;quot;&amp;gt;&amp;lt;span&amp;gt;[[Image:RadnosticsBetaOsteoporosisAnalysisGUI.png|[[Image:RadnosticsBetaOsteoporosisAnalysisGUI.png]]]]&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;parameters&amp;gt;&lt;br /&gt;
   &amp;lt;label&amp;gt;Radnostics Beta Osteoporosis Analysis&amp;lt;/label&amp;gt;&lt;br /&gt;
   &amp;lt;string-enumeration&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;Osteoporosis&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;longflag&amp;gt;--osteoporosis&amp;lt;/longflag&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;After Segmentation Perform Osteoporosis Analysis&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Osteoporosis Analysis will provide a Radnostics Osteoporosis score for the patient.&amp;lt;/description&amp;gt;&lt;br /&gt;
     &amp;lt;default&amp;gt;yes&amp;lt;/default&amp;gt;&lt;br /&gt;
     &amp;lt;element&amp;gt;yes&amp;lt;/element&amp;gt;&lt;br /&gt;
     &amp;lt;element&amp;gt;no&amp;lt;/element&amp;gt;&lt;br /&gt;
   &amp;lt;/string-enumeration&amp;gt;&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;PatientGender&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Gender&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Patient Gender&amp;lt;/description&amp;gt;		  &lt;br /&gt;
     &amp;lt;default&amp;gt;na&amp;lt;/default&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;		&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;PatientAge&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Age&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Patient Age&amp;lt;/description&amp;gt;		  &lt;br /&gt;
     &amp;lt;default&amp;gt;na&amp;lt;/default&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;		&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;RadnosticsOsteoporosisScore&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Radnostics Osteoporosis Score&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Radnostics Osteoporosis Score&amp;lt;/description&amp;gt;		  &lt;br /&gt;
     &amp;lt;default&amp;gt;na&amp;lt;/default&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;		&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;OsteoporosisComment1&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;*&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Comment 1&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;OsteoporosisComment2&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;*&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Comment 2&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;OsteoporosisComment3&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;*&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Comment 3&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;&lt;br /&gt;
   &amp;lt;string&amp;gt;&lt;br /&gt;
     &amp;lt;name&amp;gt;OsteoporosisComment4&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;channel&amp;gt;output&amp;lt;/channel&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;*&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;description&amp;gt;Comment 4&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;/string&amp;gt;&lt;br /&gt;
 &amp;lt;/parameters&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 The command line module outputs key=value pairs to the file supplied by –-returnparameterfile as shown below:&lt;br /&gt;
    PatientGender = F &lt;br /&gt;
    PatientAge = 059Y&lt;br /&gt;
    RadnosticsOsteoporosisScore = 8 (high)&lt;br /&gt;
    OsteoporosisComment1 = vertebra label 58 has biconcave fracture&lt;br /&gt;
    OsteoporosisComment2 = vertebra label 56 has mean density of 120 HU&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Command Line Parsing ==&lt;br /&gt;
&lt;br /&gt;
The Slicer Execution Model has support for parsing executable command lines. The C++ code to parse the command line arguments is generated automatically from the same XML description that generates the GUI. ''GenerateCLP,'' located in ''SlicerExecutionModel/GenerateCLP'' reads the XML Module Description and creates an include file ''&amp;quot;Executable&amp;quot;CLP.h'' in the build tree. The executable includes this header file and accesses the code with the macro PARSE_ARGS.&lt;br /&gt;
&lt;br /&gt;
GenerateCLP provides the following to the executable:&lt;br /&gt;
&lt;br /&gt;
# A brief usage command if required arguments are missing&lt;br /&gt;
# A full help command if ''-h'' or ''--help'' is specified on the command line&lt;br /&gt;
# A copy of the xml description if ''--xml'' is specified on the command line&lt;br /&gt;
# An echo of the command line parameters and their values if ''--echo'' is specified&lt;br /&gt;
&lt;br /&gt;
GenerateCLP provides the following source code:&lt;br /&gt;
&lt;br /&gt;
# A C++ declaration of the proper type for each parameter assigning the default value if specified by the XML&lt;br /&gt;
# For ''-vector'' parameters, a ''std::vector'' containing the proper C++ type fo the parameter. The generated code parses the comma separated strings to generate the ''std::vector''&lt;br /&gt;
&lt;br /&gt;
=== Using GenerateCLP ===&lt;br /&gt;
&lt;br /&gt;
GenerateCLP is normally used via CMake where it is implemented as a CUSTOM_COMMAND. To use GenerateCLP from CMake, you must first include the GenerateCLP package from your CMakeLists.txt file, which will make some macros available to you:&lt;br /&gt;
&lt;br /&gt;
  find_package(SlicerExecutionModel REQUIRED)&lt;br /&gt;
  include(${SlicerExecutionModel_USE_FILE})&lt;br /&gt;
&lt;br /&gt;
Note that the HelloSlicer command line module example provides a good starting point and can be used as a skeleton to build your own. It can be found in the [http://na-mic.org/ViewVC/index.cgi/trunk/Modules/CommandLineModule/Testing/HelloSlicer/?sortby=file#dirlist Modules/CommandLineModule/Testing/HelloSlicer] subdirectory.&lt;br /&gt;
&lt;br /&gt;
For each executable, include the following, replacing '''MyFilter''' with the name of your C++ source:&lt;br /&gt;
&lt;br /&gt;
  set('''MyFilter'''_SOURCE '''MyFilter'''.cxx)&lt;br /&gt;
  GENERATECLP('''MyFilter'''_SOURCE '''MyFilter'''.xml)&lt;br /&gt;
&lt;br /&gt;
To generate a stand-alone executable add the lines:&lt;br /&gt;
&lt;br /&gt;
  add_executable('''MyFilter''' ${'''MyFilter'''_SOURCE})&lt;br /&gt;
  target_link_libraries('''MyFilter''' ${ITK_LIBRARIES})&lt;br /&gt;
&lt;br /&gt;
Slicer expects modules and plugins to be stored in a specific subdirectory, so that they can be discovered and loaded at run-time. To make sure your CLP module is built in said subdirectory, add the line:&lt;br /&gt;
&lt;br /&gt;
  SEMMacroBuildCLI(&lt;br /&gt;
    NAME '''MyFilter'''&lt;br /&gt;
    LOGO_HEADER ${Slicer_SOURCE_DIR}/Resources/NAMICLogo.h&lt;br /&gt;
    ADDITIONAL_SRCS&lt;br /&gt;
      '''MyFilter'''.cxx&lt;br /&gt;
    TARGET_LIBRARIES ModuleDescriptionParser ${ITK_LIBRARIES} vtkTeem MRMLCore SlicerBaseCLI ${VTK_LIBRARIES}&lt;br /&gt;
    INCLUDE_DIRECTORIES&lt;br /&gt;
      ${vtkTeem_INCLUDE_DIRS}&lt;br /&gt;
      ${MRMLCore_INCLUDE_DIRS}&lt;br /&gt;
      ${vtkITK_INCLUDE_DIRS}&lt;br /&gt;
      ${SlicerBaseCLI_SOURCE_DIR} ${SlicerBaseCLI_BINARY_DIR}&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
The add_executable target creates a stand-alone executable that can be run from a command line. The add_library target creates a shared library that is discovered at Slicer 3 startup.&lt;br /&gt;
&lt;br /&gt;
Although this example linked to ITK libraries, other libraries can be specified.&lt;br /&gt;
&lt;br /&gt;
=== Short Example ===&lt;br /&gt;
&lt;br /&gt;
This example uses the XML for the [http://www.slicer.org/slicerWiki/index.php/Slicer3:Execution_Model_Documentation#Module_with_an_integer-vector.2C_one_input_image_and_one_output_image|Median Image Filter example].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Note:''' The program '''MUST NOT''' write anything to stdout before the ''PARSE_ARGS'' statement. If something is written, the plugin discovery mechanism will not recognize the program as a plugin.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;quot;MedianImageFilterCLP.h&amp;quot;&lt;br /&gt;
 int main (int argc, char * argv[])&lt;br /&gt;
  {&lt;br /&gt;
  PARSE_ARGS;&lt;br /&gt;
  std::cout &amp;lt;&amp;lt; &amp;quot;The size of the neighborhood is: &amp;quot; &amp;lt;&amp;lt; neighborhood.size()&lt;br /&gt;
    &amp;lt;&amp;lt; &amp;quot; and the first element of the neighborhood is: &amp;quot; &amp;lt;&amp;lt; neighborhood[0]&lt;br /&gt;
    &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
  std::cout &amp;lt;&amp;lt; &amp;quot;The input volume is: &amp;quot; &amp;lt;&amp;lt; inputVolume &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
  std::cout &amp;lt;&amp;lt; &amp;quot;The output volume is: &amp;quot; &amp;lt;&amp;lt; outputVolume &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
  return EXIT_SUCCESS;&lt;br /&gt;
  }&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is the output --help:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
USAGE: &lt;br /&gt;
&lt;br /&gt;
   ./MedianImageFilter  [--processinformationaddress &amp;lt;std::string&amp;gt;] [--xml]&lt;br /&gt;
                        [--echo] [--neighborhood &amp;lt;std::vector&amp;lt;int&amp;gt;&amp;gt;] [--]&lt;br /&gt;
                        [--version] [-h] &amp;lt;std::string&amp;gt; &amp;lt;std::string&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Where: &lt;br /&gt;
&lt;br /&gt;
   --processinformationaddress &amp;lt;std::string&amp;gt;&lt;br /&gt;
     Address of a structure to store process information (progress, abort,&lt;br /&gt;
     etc.). (default: 0)&lt;br /&gt;
&lt;br /&gt;
   --xml&lt;br /&gt;
     Produce xml description of command line arguments (default: 0)&lt;br /&gt;
&lt;br /&gt;
   --echo&lt;br /&gt;
     Echo the command line arguments (default: 0)&lt;br /&gt;
&lt;br /&gt;
   --neighborhood &amp;lt;std::vector&amp;lt;int&amp;gt;&amp;gt;&lt;br /&gt;
     The size of the neighborhood in each dimension (default: 1,1,1)&lt;br /&gt;
&lt;br /&gt;
   --,  --ignore_rest&lt;br /&gt;
     Ignores the rest of the labeled arguments following this flag.&lt;br /&gt;
&lt;br /&gt;
   --version&lt;br /&gt;
     Displays version information and exits.&lt;br /&gt;
&lt;br /&gt;
   -h,  --help&lt;br /&gt;
     Displays usage information and exits.&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;std::string&amp;gt;&lt;br /&gt;
     (required)  Input volume to be filtered&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;std::string&amp;gt;&lt;br /&gt;
     (required)  Output filtered&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   The MedianImageFilter is commonly used as a robust approach for noise&lt;br /&gt;
   reduction. This filter is particularly efficient against&lt;br /&gt;
   'salt-and-pepper' noise. In other words, it is robust to the presence of&lt;br /&gt;
   gray-level outliers. MedianImageFilter computes the value of each output&lt;br /&gt;
   pixel as the statistical median of the neighborhood of values around the&lt;br /&gt;
   corresponding input pixel.&lt;br /&gt;
&lt;br /&gt;
   Author(s): Bill Lorensen&lt;br /&gt;
&lt;br /&gt;
   Acknowledgements: This command module was derived from&lt;br /&gt;
   Insight/Examples/Filtering/MedianImageFilter (copyright) Insight&lt;br /&gt;
   Software Consortium&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters and C++ code ===&lt;br /&gt;
&lt;br /&gt;
This table shows how parameters are defined in the C++ code and how they are specified on the command line.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
! XML&lt;br /&gt;
! C++ Declaration&lt;br /&gt;
! Command Line&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;integer&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;count&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;flag&amp;gt;c&amp;lt;/flag&amp;gt; &amp;lt;/integer&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
int count;&lt;br /&gt;
|&lt;br /&gt;
''prog'' -c 10&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;float&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;stepSize&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;default&amp;gt;.0625&amp;lt;/default&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;longflag&amp;gt;stepSize&amp;lt;/longflag&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/float&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
float stepSize=.0625;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --stepSize .003&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;integer multiple=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;iterations&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;flag&amp;gt;i&amp;lt;/flag&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;default&amp;gt;100&amp;lt;/default&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/integer&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::vector&amp;lt;int&amp;gt; iterations;&amp;lt;br /&amp;gt; iterations.push_back(100);&amp;lt;br /&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
''prog'' -i 20 -i 30 -i 100&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;float-vector&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;variation&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;flag&amp;gt;v&amp;lt;/flag&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;default&amp;gt;1,2,3&amp;lt;/default&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/float-vector&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::vector&amp;lt;float&amp;gt; variation; iterations.push_back(1);&amp;lt;br /&amp;gt; iterations.push_back(2);&amp;lt;br /&amp;gt; iterations.push_back(3);&amp;lt;br /&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
''prog'' -v 10,20,3&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;string-vector&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;sites&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;longflag&amp;gt;sites&amp;lt;/longflag&amp;gt; &amp;lt;/string-vector&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::vector&amp;lt;std::string&amp;gt; sites;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --sites BWH,GE,Kitware,UNC,MIT,UTAH,GT&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;string-enumeration&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;leaders&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;default&amp;gt;Bill&amp;lt;/default&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;element&amp;gt;Ron&amp;lt;/element&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;element&amp;gt;Bill&amp;lt;/element&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;element&amp;gt;Steve&amp;lt;/element&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/string-enumeration&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::string leaders = &amp;quot;Bill&amp;quot;;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --leaders Ron&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;boolean&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;debugSwitch&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;flag&amp;gt;d&amp;lt;/flag&amp;gt; &amp;lt;default&amp;gt;true&amp;lt;/default&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/boolean&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
bool debugSwitch = true;&lt;br /&gt;
|&lt;br /&gt;
''prog'' -d&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;file&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;longflag&amp;gt;file1&amp;lt;/longflag&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;file&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::string file1;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --file1 mytext.txt&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;image&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;image&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;index&amp;gt;0&amp;lt;/index&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/image&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::string image;&lt;br /&gt;
|&lt;br /&gt;
''prog'' c:/lorensen/Data/ct.nrrd&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;file multiple=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;args&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;index&amp;gt;1&amp;lt;/index&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/file&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::vector&amp;lt;std::string&amp;gt; args;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --otherFlags file1 file2 ... filen&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;point multiple=&amp;quot;true&amp;quot; coordinateSystem=&amp;quot;ras&amp;quot;&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;name&amp;gt;seed&amp;lt;/name&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;longflag&amp;gt;--seed&amp;lt;/longflag&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
std::vector&amp;lt;std::vector&amp;lt;float&amp;gt; &amp;gt; seed;&lt;br /&gt;
|&lt;br /&gt;
''prog'' --seed 10,100,23 --seed 5,240,17&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Accessing Module Information at Runtime ==&lt;br /&gt;
&lt;br /&gt;
All of the information contained in the XML description of a module can be accessed at run-time by the command line program. The ''ModuleDescriptionParser'' class library can parse an XML module description and populate a ''ModuleDescription'' instance.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Module Description Parser Class Library&lt;br /&gt;
#include &amp;quot;ModuleDescriptionParser.h&amp;quot;&lt;br /&gt;
#include &amp;quot;ModuleDescription.h&amp;quot;&lt;br /&gt;
#include &amp;quot;ModuleParameterGroup.h&amp;quot;&lt;br /&gt;
#include &amp;quot;ModuleParameter.h&amp;quot;&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
// Create a module and a parser&lt;br /&gt;
    ModuleDescription module;&lt;br /&gt;
    ModuleDescriptionParser parser;&lt;br /&gt;
// Parse the XML&lt;br /&gt;
    if (parser.Parse(GetXMLModuleDescription(), module))&lt;br /&gt;
      {&lt;br /&gt;
      std::cerr &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &amp;quot;: One or more XML errors detected.&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
      return EXIT_FAILURE;&lt;br /&gt;
      }&lt;br /&gt;
// Access the module description information&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Module Description Information&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tCategory is: &amp;quot; &amp;lt;&amp;lt; module.GetCategory() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tTitle is: &amp;quot; &amp;lt;&amp;lt; module.GetTitle() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tDescription is: &amp;quot; &amp;lt;&amp;lt; module.GetDescription() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tVersion is: &amp;quot; &amp;lt;&amp;lt; module.GetVersion() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tDocumentationURL is: &amp;quot; &amp;lt;&amp;lt; module.GetDocumentationURL() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tLicense is: &amp;quot; &amp;lt;&amp;lt; module.GetLicense() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\tContributor is: &amp;quot; &amp;lt;&amp;lt; module.GetContributor() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''GetXMLModuleDescription'' is automatically generated by ''GenerateCLP''. Information about parameter groups and parameters is also available [[Accessing_Module_Information_at_Runtime|here]].&lt;br /&gt;
&lt;br /&gt;
The ''CMakeLists.txt'' file that creates the command line module should point to the ''ModuleDescriptionParser'' library.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
target_link_libraries(${CLP}&lt;br /&gt;
    ModuleDescriptionParser&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Error Handling ==&lt;br /&gt;
&lt;br /&gt;
GenerateCLP attempts to do error checking so that the generated C++ code will compile. These errors will show up as custom command errors during the build process.&lt;br /&gt;
&lt;br /&gt;
* XML Errors&lt;br /&gt;
** ''mismatched tag at line xx'' : The closing tag (a tag with &amp;lt;/ &amp;gt;) does not have a matching opening tag.&lt;br /&gt;
** ''not well-formed (invalid token) at line xx'' : Probably a blank in the token name.&lt;br /&gt;
* ModuleDescriptionParser Errors&lt;br /&gt;
** ''&amp;lt;executable&amp;gt; must be the outer most tag''&lt;br /&gt;
** ''&amp;lt;executable&amp;gt; was found inside another tag''&lt;br /&gt;
** ''&amp;lt;parameters&amp;gt; can only be inside &amp;lt;executable&amp;gt;''&lt;br /&gt;
** ''&amp;lt;xxx&amp;gt; can only be used inside &amp;lt;parameters&amp;gt;''&lt;br /&gt;
** ''&amp;lt;flag&amp;gt; can only contain one character''&lt;br /&gt;
** ''&amp;lt;longname&amp;gt; can only contain letters, numbers and underscores and must start with an _ or letter''&lt;br /&gt;
** ''&amp;lt;name&amp;gt; can only contain letters, numbers and underscores and must start with an _ or letter''&lt;br /&gt;
&lt;br /&gt;
* ModuleDescriptionParser Warnings&lt;br /&gt;
** ''&amp;lt;xxx&amp;gt; is an unknown parameter tag'' : Probably a misspelled parameter type.&lt;br /&gt;
&lt;br /&gt;
* Compiler Errors&lt;br /&gt;
** The generated C++ code may have syntax errors if invalid defaults are specified. These will show up during the C++ compilation.&lt;br /&gt;
&lt;br /&gt;
== Interfacing Legacy Executables ==&lt;br /&gt;
&lt;br /&gt;
GenerateCLP is only provided as a convenience. Users can use the same XML Module Description to interface C++, shell scripts, tcl programs and even Matlab.&lt;br /&gt;
&lt;br /&gt;
Example: [http://www.slicer.org/slicerWiki/index.php/Slicer3:FiberTrackingIntegration FiberTracking Integration]&lt;br /&gt;
&lt;br /&gt;
== Showing Progress in an Application ==&lt;br /&gt;
&lt;br /&gt;
Programs can communicate progress to the user in two ways. If the program is running an a stand-alone executable, it communicates with a simple XML syntax. If the program is loaded at run-time as a plugin library, it communicates through a C structure.&lt;br /&gt;
&lt;br /&gt;
The XML syntax is:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;filter-start&amp;gt;&lt;br /&gt;
  &amp;lt;filter-name&amp;gt;&lt;br /&gt;
  ''name of program section or algorithm''&lt;br /&gt;
  &amp;lt;/filter-name&amp;gt;&lt;br /&gt;
  &amp;lt;filter-comment&amp;gt;&lt;br /&gt;
  ''description of program section or algorithm''&lt;br /&gt;
  &amp;lt;/filter-comment&amp;gt;&lt;br /&gt;
 &amp;lt;/filter-start&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;filter-progress&amp;gt;&lt;br /&gt;
 ''floating number from 0 to 1''&lt;br /&gt;
 &amp;lt;/filter-progress&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;filter-end&amp;gt;&lt;br /&gt;
  &amp;lt;filter-name&amp;gt;&lt;br /&gt;
  ''name of program section or algorithm''&lt;br /&gt;
  &amp;lt;/filter-name&amp;gt;&lt;br /&gt;
  &amp;lt;filter-time&amp;gt;&lt;br /&gt;
  ''execution time''&lt;br /&gt;
  &amp;lt;/filter-time&amp;gt;&lt;br /&gt;
 &amp;lt;/filter-end&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The C structure that library plugins use is:&lt;br /&gt;
&lt;br /&gt;
 extern &amp;quot;C&amp;quot; {&lt;br /&gt;
  struct ModuleProcessInformation&lt;br /&gt;
  {&lt;br /&gt;
    /** Inputs from calling application to the module **/&lt;br /&gt;
    unsigned char Abort;&lt;br /&gt;
    /** Outputs from the module to the calling application **/&lt;br /&gt;
    float Progress;&lt;br /&gt;
    char  ProgressMessage[1024];&lt;br /&gt;
    void (*ProgressCallbackFunction)(void *);&lt;br /&gt;
    void *ProgressCallbackClientData;&lt;br /&gt;
    double ElapsedTime;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Details on how to use this mechanism are illustrated in [https://github.com/Slicer/Slicer/blob/master/Base/CLI/itkPluginFilterWatcher.h itkPluginFilterWatcher.h].&lt;br /&gt;
&lt;br /&gt;
For vtk and itk execution model programs, two classes are available that make it simple to add progress. The classes, ''vtkPluginFilterWatcher'' and ''itk::PluginFilterWatcher'' use the vtk and itk command/observer mechanism to report progress.&lt;br /&gt;
&lt;br /&gt;
vtkPluginFilterWatcher (vtkAlgorithm *'''filter''', const char* '''comment''', ModuleProcessInformation *'''inf''', double '''fraction''', double '''start''') &amp;lt;br /&amp;gt; itk::PluginFilterWatcher (itk::ProcessObject '''filter''', const char* '''comment''', ModuleProcessInformation *'''inf''', double '''fraction''', double '''start''')&lt;br /&gt;
&lt;br /&gt;
: where:&lt;br /&gt;
;; filter &lt;br /&gt;
:: is the vtkAlgorithm or itk::ProcessObject to be watched.&lt;br /&gt;
;; comment &lt;br /&gt;
:: is a string that describes the algorithm.&lt;br /&gt;
;; inf &lt;br /&gt;
:: is an optional pointer to a structure that is used to communicate with the invoking program when the called program is used as a library plugin. If the pointer is 0, this prgram will not report progress if it is run as a library plugin. Default is 0.&lt;br /&gt;
;; fraction &lt;br /&gt;
:: is the fraction (0-1) of progress that will be reported by this watcher. This is used when multiple filters are run and each filter represents a proportion of the total progress. Default is 1.&lt;br /&gt;
;; start &lt;br /&gt;
:: is the offset (0-1) of the progress for this filter. This is added to the progress of the filter. The reported progress of the watched filter is ''start + fraction * filter_progress''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt; The following example produces progress for a simple vtk program. The variable CLPProcessInformation is automatically declared and set in the program's ''program''CLP.h file.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;quot;vtkPluginFilterWatcher.h&amp;quot;&lt;br /&gt;
 ...&lt;br /&gt;
  vtkMarchingCubes *cubes = vtkMarchingCubes::New();&lt;br /&gt;
    cubes-&amp;gt;SetInput(reader-&amp;gt;GetOutput());&lt;br /&gt;
  vtkPluginFilterWatcher watchCubes(cubes, &amp;quot;Generate Isosurface&amp;quot;, CLPProcessInformation, .5, 0.0);&lt;br /&gt;
  vtkDecimatePro *decimate = vtkDecimatePro::New();&lt;br /&gt;
    decimate-&amp;gt;SetInput(cubes-&amp;gt;GetOutput());&lt;br /&gt;
  vtkPluginFilterWatcher watchDecimate(decimate, &amp;quot;Reduce Triangle Count&amp;quot;, CLPProcessInformation, .5, 0.5);&lt;br /&gt;
  decimate-&amp;gt;Update();&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example produces progress for a simple itk program:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;quot;itkPluginFilterWatcher.h&lt;br /&gt;
 ...&lt;br /&gt;
 typedef itk::MedianImageFilter&amp;lt;ImageType,ImageType&amp;gt; FilterType;&lt;br /&gt;
 FilterType::Pointer median  = FilterType::New();&lt;br /&gt;
 itk::PluginFilterWatcher watchMedian(median, &amp;quot;Denoise Image&amp;quot;, CLPProcessInformation);&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Adding Module Logos to Slicer ==&lt;br /&gt;
Slicer plugins, both libraries and executables, can specify plugin-specific logos. These appear in Slicer when a module is selected. The logos are specified in a .h header file. The KWWidget utility, KWConvertImageToHeader, converts a .png file into a .h header file containing the encoded image and additional information such as width, height and pixel size. [[Documentation-3.5#Requirements_for_Modules|See here for additional information.]]&lt;br /&gt;
&lt;br /&gt;
For Slicer, execution model plugin logos are stored in Modules/CLI/Resources. The corresponding image in .png format should be stored in Modules/CLI/ImageData. Othere plugins, created outside the Slicer tree, should store the logo and image in a similar location.&lt;br /&gt;
&lt;br /&gt;
To add a logo to a plugin:&lt;br /&gt;
* Create a png image of the logo. The height of the logo should not exceed 40 pixels.&lt;br /&gt;
* Convert the logo to the KWWidget icon format as follows. '''NOTE:''' the prefix of the image and header file must be the same for a plugin logo.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd Modules/CLI&lt;br /&gt;
KWConvertImageToHeader --base64 --zlib Resources/ITKLogo.h ImageData/ITKLogo.png&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Add the logo to the SEMMacroBuildCLImacro in the CMakeLists.txt file for the plugin using LOGO_HEADER parameter.&lt;br /&gt;
&lt;br /&gt;
=== Runtime specification of filter types ===&lt;br /&gt;
&lt;br /&gt;
ITK filters are templated over the images they process. The following code snippet shows how an execution model program can select the image types for filters based on the input images.&lt;br /&gt;
&lt;br /&gt;
First, include the utilites for plugin's:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;itkPluginUtilities.h&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, turn your main program into a templated procedure called ''DoIt'':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
template&amp;lt;class T&amp;gt; int DoIt( int argc, char * argv[], T )&lt;br /&gt;
{&lt;br /&gt;
  PARSE_ARGS;&lt;br /&gt;
&lt;br /&gt;
  typedef itk::Image&amp;lt; T, 3 &amp;gt;   InputImageType;&lt;br /&gt;
  typedef itk::Image&amp;lt; T, 3 &amp;gt;   OutputImageType;&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Then, create a main program that gets the native component type from one of the input file. Here that input file is ''inputVolume'':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int main( int argc, char * argv[] )&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  PARSE_ARGS;&lt;br /&gt;
&lt;br /&gt;
  itk::ImageIOBase::IOPixelType pixelType;&lt;br /&gt;
  itk::ImageIOBase::IOComponentType componentType;&lt;br /&gt;
&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
    itk::GetImageType (inputVolume, pixelType, componentType);&lt;br /&gt;
&lt;br /&gt;
    // This filter handles all types&lt;br /&gt;
    &lt;br /&gt;
    switch (componentType)&lt;br /&gt;
      {&lt;br /&gt;
      case itk::ImageIOBase::UCHAR:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;unsigned char&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::CHAR:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;char&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::USHORT:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;unsigned short&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::SHORT:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;short&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::UINT:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;unsigned int&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::INT:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;int&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::ULONG:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;unsigned long&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::LONG:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;long&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::FLOAT:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;float&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::DOUBLE:&lt;br /&gt;
        return DoIt( argc, argv, static_cast&amp;lt;double&amp;gt;(0));&lt;br /&gt;
        break;&lt;br /&gt;
      case itk::ImageIOBase::UNKNOWNCOMPONENTTYPE:&lt;br /&gt;
      default:&lt;br /&gt;
        std::cout &amp;lt;&amp;lt; &amp;quot;unknown component type&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  catch( itk::ExceptionObject &amp;amp;excep)&lt;br /&gt;
    {&lt;br /&gt;
    std::cerr &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &amp;quot;: exception caught !&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cerr &amp;lt;&amp;lt; excep &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    return EXIT_FAILURE;&lt;br /&gt;
    }&lt;br /&gt;
  return EXIT_SUCCESS;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Behind the Scenes ==&lt;br /&gt;
&lt;br /&gt;
A primary goal of the execution model is to relieve developers from developing GUI code and command line parsing code. This section describes the major components of the execution model implementation.&lt;br /&gt;
&lt;br /&gt;
=== Command Line Processing ===&lt;br /&gt;
&lt;br /&gt;
Command line processing parses command line arguments and populates internal program variables. Every Unix (and windows) program can receive an argument list through its main entry point. All C and C++ programmers are familiar with the ''int main (int argc, char *[] argv)'' entry point in their programs. Most computer languages including scripting languages provide a similar mechanism to retrieve command line arguments. Simple command line processing directly accesses the strings defined in argv.&lt;br /&gt;
&lt;br /&gt;
This snippet shows simple commmand line processing:&lt;br /&gt;
&lt;br /&gt;
 int main (int argc, char *argv[])&lt;br /&gt;
 {&lt;br /&gt;
   if (argc &amp;lt; 2)&lt;br /&gt;
     {&lt;br /&gt;
     std::cout &amp;lt;&amp;lt; &amp;quot;Usage: &amp;quot; &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &amp;quot; filename&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
     return -1;&lt;br /&gt;
     }&lt;br /&gt;
   std::cout &amp;lt;&amp;lt; &amp;quot;The File is &amp;quot; &amp;lt;&amp;lt; argv[1] &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The simple approach works great for a small number of arguments. But larger numbers of arguments of varying types quickly make the processing code more complex and subject to error, both in coding and usage.&lt;br /&gt;
&lt;br /&gt;
 int main (int argc, char *argv[])&lt;br /&gt;
 {&lt;br /&gt;
   if (argc &amp;lt; 5)&lt;br /&gt;
     {&lt;br /&gt;
     std::cout &amp;lt;&amp;lt; &amp;quot;Usage: &amp;quot; &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &amp;quot; iterations epsilon inputfile outputfile &amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
     return -1;&lt;br /&gt;
     }&lt;br /&gt;
   std::string inputfile(argv[3]);&lt;br /&gt;
   std::string outputfile(argv[4]);&lt;br /&gt;
   unsigned int iterations = atoi(argv[1]);&lt;br /&gt;
   float epsilon = atof(argv[2]);&lt;br /&gt;
 ...&lt;br /&gt;
   return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Adding flags (or options) to the command line makes the program easier to use but places a larger burden on the program developer. Each developer must ''invent'' a command line argument syntax and implement code to parse the command line. Even a simple example of this is too long to include in this description. This code snippet looks for just two command line arguments.&lt;br /&gt;
&lt;br /&gt;
 int main (int argc, char *argv[])&lt;br /&gt;
 {&lt;br /&gt;
   if (argc &amp;lt; 3)&lt;br /&gt;
     {&lt;br /&gt;
     std::cout &amp;lt;&amp;lt; &amp;quot;Usage: &amp;quot; &amp;lt;&amp;lt; argv[0] &amp;lt;&amp;lt; &amp;quot; [-i iterations] [-e epsilon] inputfile outputfile &amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
     return -1;&lt;br /&gt;
     }&lt;br /&gt;
   std::string inputfile;&lt;br /&gt;
   std::string outputfile;&lt;br /&gt;
   unsigned int iterations = 10; /* a default */&lt;br /&gt;
   float epsilon = .001; /* a defualt */&lt;br /&gt;
   ++argc; /* skip program name */&lt;br /&gt;
   while (argc &amp;gt; 0)&lt;br /&gt;
     {&lt;br /&gt;
     if (strcmp(argv[argc], &amp;quot;-i&amp;quot;)&lt;br /&gt;
      {&lt;br /&gt;
      iterations = atoi(argv[argc+1]);&lt;br /&gt;
      argc+=2;&lt;br /&gt;
      continue;&lt;br /&gt;
 &lt;br /&gt;
    else if (strcmp(argv[argc], &amp;quot;-e&amp;quot;)&lt;br /&gt;
      {&lt;br /&gt;
      epsilon = atof(argv[argc+1]);&lt;br /&gt;
      argc+=2;&lt;br /&gt;
      continue;&lt;br /&gt;
    ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The code gets longer and longer as more options are added and must be rewritten every time a new programs is open.&lt;br /&gt;
&lt;br /&gt;
To solve this complexity issue, people have developed command line argument libraries. There are dozens, if not hundreds, of command line processing tools. For Slicer3 we looked at argument processors in vxl, nrrd, meta, kwsys and tclap. Each has its strengths and weaknesses. We chose [http://tclap.sourceforge.net/ The Templatized C++ Command Line Parser Library], '''TCLAP'''. '''TCLAP''' is implemented in ''include'' files and does not require a separate library build. As you will see later, the particular command line processing tool is, for the most part, transparent to the Slicer3 developer or user.&lt;br /&gt;
&lt;br /&gt;
But even these libraries require some work to use.&lt;br /&gt;
&lt;br /&gt;
==== TCLAP ====&lt;br /&gt;
&lt;br /&gt;
This example uses '''TCLAP''' to process a command line with 10 possible entries:&lt;br /&gt;
&lt;br /&gt;
 int main ( int argc, char* argv[] ) {&lt;br /&gt;
  //&lt;br /&gt;
  // Define default values&lt;br /&gt;
  int HistogramBins      = 30;&lt;br /&gt;
  int RandomSeed         = 1234567;&lt;br /&gt;
  int SpatialSamples     = 10000;&lt;br /&gt;
  float TranslationScale = 100.0;&lt;br /&gt;
  int Iterations         = 200;&lt;br /&gt;
  int SplineOrder        = 3;&lt;br /&gt;
  double MinimumStepSize = 0.00001;&lt;br /&gt;
  double MaximumStepSize = 0.005;&lt;br /&gt;
  bool PrintTransform    = false;&lt;br /&gt;
  string fixedImageFileName;&lt;br /&gt;
  string movingImageFileName;&lt;br /&gt;
  string resampledImageFileName;&lt;br /&gt;
  //&lt;br /&gt;
  // Setup command line parsing&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
    TCLAP::CmdLine cl ( &amp;quot;Register2d&amp;quot;, ' ', &amp;quot;$Revision: 1.1 $&amp;quot; );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;int&amp;gt;    HistogramBinsArg    ( &amp;quot;b&amp;quot;, &amp;quot;histogrambins&amp;quot;,    &amp;quot;Number of histogram bins&amp;quot;, false, 30, &amp;quot;integer&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;int&amp;gt;    IterationsArg       ( &amp;quot;i&amp;quot;, &amp;quot;iterations&amp;quot;,       &amp;quot;Number of Iterations&amp;quot;, false, Iterations, &amp;quot;int&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;double&amp;gt; MinimumStepSizeArg  ( &amp;quot;m&amp;quot;, &amp;quot;minstepsize&amp;quot;,      &amp;quot;Minimum Step Size&amp;quot;, false, MinimumStepSize, &amp;quot;double&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;double&amp;gt; MaximumStepSizeArg  ( &amp;quot;x&amp;quot;, &amp;quot;maxstepsize&amp;quot;,      &amp;quot;Maximum Step Size&amp;quot;, false, MaximumStepSize, &amp;quot;double&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;int&amp;gt;    RandomSeedArg       ( &amp;quot;r&amp;quot;, &amp;quot;randomseed&amp;quot;,       &amp;quot;Random Seed&amp;quot;, false, RandomSeed, &amp;quot;int&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;int&amp;gt;    SpatialSamplesArg   ( &amp;quot;s&amp;quot;, &amp;quot;spatialsamples&amp;quot;,   &amp;quot;Number of spatial samples&amp;quot;, false, SpatialSamples, &amp;quot;int&amp;quot;, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;int&amp;gt;    SplineOrderArg      ( &amp;quot;o&amp;quot;, &amp;quot;splineorder&amp;quot;,      &amp;quot;Order of spline for registration&amp;quot;, false, SplineOrder, &amp;quot;int&amp;quot;, cl );&lt;br /&gt;
    TCLAP::SwitchArg        PrintTransformArg   ( &amp;quot;p&amp;quot;, &amp;quot;printtransform&amp;quot;,   &amp;quot;Print the final transform&amp;quot;, PrintTransform, cl );&lt;br /&gt;
    TCLAP::ValueArg&amp;lt;float&amp;gt;  TranslationScaleArg ( &amp;quot;t&amp;quot;, &amp;quot;translationscale&amp;quot;, &amp;quot;Translation scale&amp;quot;, false, TranslationScale, &amp;quot;float&amp;quot;, cl );&lt;br /&gt;
    TCLAP::UnlabeledValueArg&amp;lt;string&amp;gt; FixedImageArg ( &amp;quot;fixed&amp;quot;, &amp;quot;Fixed image filename&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;string&amp;quot;, cl );&lt;br /&gt;
    TCLAP::UnlabeledValueArg&amp;lt;string&amp;gt; MovingImageArg ( &amp;quot;moving&amp;quot;, &amp;quot;Moving image filename&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;string&amp;quot;, cl );&lt;br /&gt;
    TCLAP::UnlabeledValueArg&amp;lt;string&amp;gt; ResampledImageArg ( &amp;quot;resampled&amp;quot;, &amp;quot;Resampled image filename&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;string&amp;quot;, cl );&lt;br /&gt;
    //&lt;br /&gt;
    // Parse the command line&lt;br /&gt;
    cl.parse ( argc, argv );&lt;br /&gt;
    //&lt;br /&gt;
    // Access the variables&lt;br /&gt;
    HistogramBins          = HistogramBinsArg.getValue();&lt;br /&gt;
    Iterations             = IterationsArg.getValue();&lt;br /&gt;
    MinimumStepSize        = MinimumStepSizeArg.getValue();&lt;br /&gt;
    MaximumStepSize        = MaximumStepSizeArg.getValue();&lt;br /&gt;
    RandomSeed             = RandomSeedArg.getValue();&lt;br /&gt;
    SpatialSamples         = SpatialSamplesArg.getValue();&lt;br /&gt;
    TranslationScale       = TranslationScaleArg.getValue();&lt;br /&gt;
    PrintTransform         = PrintTransformArg.getValue();&lt;br /&gt;
    fixedImageFileName     = FixedImageArg.getValue();&lt;br /&gt;
    movingImageFileName    = MovingImageArg.getValue();&lt;br /&gt;
    resampledImageFileName = ResampledImageArg.getValue();&lt;br /&gt;
    }&lt;br /&gt;
  catch ( ArgException e )&lt;br /&gt;
    {&lt;br /&gt;
    cerr &amp;lt;&amp;lt; &amp;quot;error: &amp;quot; &amp;lt;&amp;lt; e.error() &amp;lt;&amp;lt; &amp;quot; for arg &amp;quot; &amp;lt;&amp;lt; e.argId() &amp;lt;&amp;lt; endl;&lt;br /&gt;
    exit ( EXIT_FAILURE );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
You do get a lot for your investment here. Good error handling and help.&lt;br /&gt;
&lt;br /&gt;
=== Module Description Parser ===&lt;br /&gt;
The XML parsing is done by the [https://github.com/Slicer/SlicerExecutionModel/tree/master/ModuleDescriptionParser ModuleDescriptionParser] class library. ''GenerateCLP'' and Slicer3 use this class library to parse the module XML descriptions. The class ''ModuleDescriptionParser'' has one method, '''Parse''', that converts the XML description into an object model. The resulting object model has one ''ModuleDescription'', one or more ''ModuleParameterGroup'' each of which has one or more ''ModuleParameter''. Each instance has access methods to retrieve information from the XML.&lt;br /&gt;
* '''ModuleDescriptionParser''' - parser for command line module XML description.&lt;br /&gt;
*: ''Parse(std::string xml, ModuleDescription module)'' - parse an xml string and populate a ModuleDescription.&lt;br /&gt;
* '''ModuleDescription''' - contains information about a module &lt;br /&gt;
*: const std::string ''GetCategory()'' : returns the contents of '''&amp;lt;category&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetTitle()'' : returns the contents of '''&amp;lt;title&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetDescription()'' : returns the contents of '''&amp;lt;description&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetVersion()'' : returns the contents of '''&amp;lt;version&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetDocumentationURL()'' : returns the contents of '''&amp;lt;documentationURL&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetLicense()'' : returns the contents of '''&amp;lt;license&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetContributor()'' : returns the contents of '''&amp;lt;contributor&amp;gt;'''.&lt;br /&gt;
*: const std::vector&amp;lt;ModuleParameterGroup&amp;gt;&amp;amp; ''GetParameterGroups()'' : returns a vector of parameter groups.&lt;br /&gt;
* '''ModuleParameterGroup''' - contains ModuleParameters for each parameter group.&lt;br /&gt;
*: const std::string ''GetLabel'' - returns the contents of '''&amp;lt;label&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetDescription()'' - returns the contents of the parameter group's '''&amp;lt;description&amp;gt;'''.&lt;br /&gt;
*: const std::string ''GetAdvanced()'' - returns advanced attribute. Either &amp;quot;true&amp;quot; of &amp;quot;false&amp;quot;.&lt;br /&gt;
* '''ModuleParameter''' - contains information for a parameter.&lt;br /&gt;
*:GetTag() - returns the parameter's tag, e.g. '''&amp;lt;integer&amp;gt;, &amp;lt;image&amp;gt;''', etc.&lt;br /&gt;
*:GetName() - returns the parameter's '''&amp;lt;name&amp;gt;'''.&lt;br /&gt;
*:GetLongFlag() -  returns the parameter's '''&amp;lt;longflag&amp;gt;'''.&lt;br /&gt;
*:GetLabel() -  returns the parameter's '''&amp;lt;label&amp;gt;'''.&lt;br /&gt;
*:GetMaximum() -  returns the parameter's '''&amp;lt;maximum&amp;gt;''' constraint.&lt;br /&gt;
*:GetMinimum() -  returns the parameter's '''&amp;lt;minimum&amp;gt;''' constraint.&lt;br /&gt;
*:GetStep() -  returns the parameter's '''&amp;lt;step&amp;gt;'''.&lt;br /&gt;
*:GetDescription() -  returns the parameter's '''&amp;lt;description&amp;gt;'''.&lt;br /&gt;
*:GetChannel() -  returns the parameter's '''&amp;lt;channel&amp;gt;'''.&lt;br /&gt;
*:GetIndex() -  returns the parameter's '''&amp;lt;index&amp;gt;'''.&lt;br /&gt;
*:GetDefault() -  returns the parameter's '''&amp;lt;default&amp;gt;'''.&lt;br /&gt;
*:GetFlag() -  returns the parameter's '''&amp;lt;flag&amp;gt;'''.&lt;br /&gt;
*:GetMultiple() -  returns the parameter's multiple attribute, either &amp;quot;true&amp;quot; or &amp;quot;false&amp;quot;.&lt;br /&gt;
*:GetCoordinateSystem() -  returns the parameter's coordinate system attribute, one of &amp;quot;lps&amp;quot;, &amp;quot;ras&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
= Adding a new parameter type =&lt;br /&gt;
&lt;br /&gt;
Adding a ''new parameter type'' to the execution model involves several modifications:&lt;br /&gt;
&lt;br /&gt;
# A new XML tag needs to be defined to represent the new parameter type.&lt;br /&gt;
# ModuleDescriptionParser needs to be modified to parse the new parameter tag type and specify how the command line processing code generation is going to represent the parameter type&lt;br /&gt;
# CommandLineModuleGUI needs to be modified to construct the appropriate GUI element for the parameter type&lt;br /&gt;
# CommandLineModuleLogic needs to be modified to put the parameter type onto the command line and request outputs parameter types be loaded back into Slicer and the MRML tree.&lt;br /&gt;
# SlicerApplicationLogic needs to be modified to ingest any output parameter types back into Slicer and the MRML tree.&lt;br /&gt;
# Additional modification are needed if the parameter is to be passed directly from the MRML tree without using the filesystem.&lt;br /&gt;
# Updating the documentation.&lt;br /&gt;
&lt;br /&gt;
Simple parameter types can be passed directly on the command line.  For instance, scalars, small lists, positions, etc. Complicated parameter types are passed to the module via '''abstract files'''. In some cases, these parameters are actually passed as files, where Slicer reads/write the data to the filesystem.  In other cases, the parameters are passed as '''abstract files''' which are really references to within the Slicer memory model but appear to the Command Line Module as being a file.  The Command Line Module is written using standard ITK ImageFileReader/ImageFileWriter classes but the ITK ImageIO factory mechanism is used to direct the ImageFileReader/ImageFileWriter to talk directly to the Slicer MRML tree instead of to the filesystem.&lt;br /&gt;
&lt;br /&gt;
== XML tag ==&lt;br /&gt;
&lt;br /&gt;
This is by far the easiest of the tasks involved in adding a new parameter type but it should not approached hastily. The XML description of a module is designed to be application agnostic. As such, parameter types should be described abstractly or generically.  For instance, '''&amp;lt;geometry&amp;gt;''' tag corresponds to the Slicer model node, the '''&amp;lt;point&amp;gt;''' tag corresponds to the Slicer fiducial node, etc.&lt;br /&gt;
&lt;br /&gt;
Once the tag name is defined, you need to decide whether the parameter type could or should support the attributes '''multiple''', '''coordinateSystem''', or '''fileExtensions''' or perhaps a new attribute type.&lt;br /&gt;
&lt;br /&gt;
== Modifying ModuleDescriptionParser ==&lt;br /&gt;
&lt;br /&gt;
SlicerExecutionModel/ModuleDescriptionParser/ModuleDescriptionParser.cxx contains the code to parse the XML description of a module and represent that module description in C++ data structures.  To add a new parameter type, this code needs to be modified.&lt;br /&gt;
&lt;br /&gt;
Two routines need to be modified in ModuleDescriptionParser, ''startElement()'' and ''endElement()''. For ''startElement()'', a new case block needs to be added for the parameter type.  You can start by copying the case block for a similar parameter type. This case block is responsible for processing all the attributes for the tag and managing and reporting any errors. The case block may define the '''CPPType''', the ''ArgType''', and the '''StringToType''' needed for the code generation of the command line parsing. The '''CPPType''' is used by in the generated command line processing code to represent the parameter.  This may be a simple C++ type or an STL container. The '''ArgType''' is the canonical type of each component of the parameter. The '''StringToType''' is the name of the method to use to convert the ASCII command line parameter to the final '''ArgType'''. The ''endElement()'' method merely needs a new case block to add the parameter to the description.&lt;br /&gt;
&lt;br /&gt;
ModuleDescriptionParser is fairly general, handling scalars, lists of scalars, and file types as parameter types. A parameter which does not fit these models will require considerable alterations to the ModuleDescriptionParser as well as the GenerateCLP.&lt;br /&gt;
&lt;br /&gt;
== Constructing a GUI for a new parameter type ==&lt;br /&gt;
&lt;br /&gt;
To have a GUI element appear in the module GUI for a new parameter type, Base\QTCLI\qSlicerCLIModuleUIHelper.cxx and Base\QTCLI\vtkSlicerCLIModuleLogic.cxx have to be modified. A new case block needs to be added to the '''BuildGUI()''' method for the new parameter type.  This case block is triggered off the XML tag for the parameter type. The case block is responsible for the constructing the appropriate GUI element for the parameter, complete with specifying the label and help text. The design is very simple.  A single widget is used for each parameter.  If a more complicated GUI is needed with multiple widgets, then perhaps a new widget is needed to encapsulated a set of widgets or a naming convention can be added to manage all the widgets associated with a parameter. The widgets for the parameters are stored in a map, indexed by the '''name''' of the parameter.&lt;br /&gt;
&lt;br /&gt;
The vtkCommandLineModuleGUI (and vtkCommandLineModuleLogic) are designed to operate very generically with sets of parameters. The aforementioned map of widgets indexed by parameter '''name''' is one such example.  The implementation of several of the methods in the vtkCommandLineModuleGUI (and vtkCommandLineModuleLogic) generically iterate over the widget map or over the parameter list. It is important to keep this in mind as new parameters are added.  The design goal is to minimize the number of ''special cases'' in the code.&lt;br /&gt;
&lt;br /&gt;
Note that there may be separate case blocks for '''input''' and '''output''' parameter types.&lt;br /&gt;
&lt;br /&gt;
== Communicating the new parameter to the Command Line Module ==&lt;br /&gt;
&lt;br /&gt;
To communicate the new parameter type to and from a Command Line Module, the '''ApplyTask()''' method Slicer3/Modules/CommandLineModule/vtkCommandLineModuleLogic.cxx needs to be modified. &lt;br /&gt;
&lt;br /&gt;
If the parameter type is communicated to the command line module as a file (as opposed to directly on the command line as a number or srting), then there are several blocks of code to construct a temporary file name, keep track of whether that node needs to be written to the filesystem before execution, read from the filesystem after the execution, and deleted after execution completes. These blocks may need to be modified based on your new parameter type.&lt;br /&gt;
&lt;br /&gt;
The command line is constructed in two passes.  First, a pass is made over the parameter list, building the portion of the command line for any parameters that have flags.  Note that whether a parameter has a flag or not is up to the discretion of the module author and is not defined by the parameter type.  Second, a pass is made to construction the portion of the command  line for the parameters that do not have flags. These parameters are ordered appropriately, then placed on the command line. For parameters with flags, this code emits the flag and the parameter value.  For the parameters without flags, this code emits just the parameter value.  You will need to edit both of these passes to emit your parameter type.  In most cases, this is simply a matter of grabbing the parameter value from the parameter and pushing it onto the command line.  But some parameter types do require translation to a string appropriate for the command line.&lt;br /&gt;
&lt;br /&gt;
== Output parameters from the Command Line Modules ==&lt;br /&gt;
&lt;br /&gt;
Any outputs from a Command Line Module that are communicated via files are queued to be read by the main application thread. Command Line Modules run in a separate execution thread from the main GUI.  This thread is not allowed to modify the Slicer GUI, so any results from the module that need to be read back into Slicer and displayed are queued for the main thread.&lt;br /&gt;
&lt;br /&gt;
The '''ProcessReadData()''' method of Slicer3/Base/Logic/vtkSlicerApplicationLogic.cxx pulls data from the queue to load back into Slicer and display. You may need to a case block for your new parameter type to construct the appropriate storage node and display node.&lt;br /&gt;
&lt;br /&gt;
== Communicating directly with the MRML tree ==&lt;br /&gt;
&lt;br /&gt;
Currently scalar image types can sent as parameters to shared object command line modules without going through the filesystem.  Slicer provides a new ITK ImageIO factory that can communicated directly with the Slicer MRML tree. This ImageIO factory is in Slicer/Libs/MRMLIDImageIO. This approach can be extended for other image types such as vector or tensor volumes.&lt;br /&gt;
&lt;br /&gt;
For other constructs such as models and transforms, we'll need to see if an existing factory mechanism can be leverage to communicate directly with the Slicer MRML tree. An alternative may be to construct bridges specific to interfacing from a command line module to the Slicer MRML tree.&lt;br /&gt;
&lt;br /&gt;
== Adding new image types ==&lt;br /&gt;
&lt;br /&gt;
The Command Line Module support scalar, vector, tensor, and diffusion weighted images. Adding a new image type to the Command Line Module requires modify the sections of the code outlined above to manage GUI for the module, to construct temporary file names, to write image to disk, and load them back into the MRML tree.  These blocks are easy to identify as case blocks on vtkMRMLScalarVolumeNode, vtkMRMLDiffusionTensorVolumeNode, etc. Note that the '''&amp;lt;image&amp;gt;''' tag supports a '''type''' attribute that can scalar, label, vector, tensor, or diffusion-weighted.  The case block for '''image''' in the '''startElement()''' method of ModuleDescriptionParser would need to be extended to recognize a new type of image.&lt;br /&gt;
&lt;br /&gt;
=FAQ=&lt;br /&gt;
&lt;br /&gt;
==What facilities are available for third party software to interface with the NA-MIC Kit?==&lt;br /&gt;
&lt;br /&gt;
NA-MIC has committed to developing and supporting a generic batch processing interface.  This is the Slicer3 Command Line Interface (CLI). The application programming interface (API) for CLI was worked out based on interactions with the community including input from those familiar with LONI, ITK, Python and Matlab software development practices.&lt;br /&gt;
&lt;br /&gt;
We believe this API already supports all the features required by to implement batch processing with BatchMake, the LONI Pipeline, and any other systems that we may want to work with in the future.  The [[Slicer3:Execution_Model_Documentation|Slicer3 Execution Model]] provides a simple XML-based descriptor for command line arguments for input/output volumes and related parameters.&lt;br /&gt;
&lt;br /&gt;
==Which Third Party software has currently been interfaced to the NA-MIC Kit using the CLI?==&lt;br /&gt;
&lt;br /&gt;
*Batchmake (Kitware)&lt;br /&gt;
*Python&lt;br /&gt;
*Matlab&lt;br /&gt;
&lt;br /&gt;
== How do I debug my command line module? ==&lt;br /&gt;
&lt;br /&gt;
See [http://www.slicer.org/slicerWiki/index.php/Slicer3:Execution_Model_Documentation:Debugging Debugging]&lt;br /&gt;
&lt;br /&gt;
== How do I specify a Logo? ==&lt;br /&gt;
&lt;br /&gt;
You need to create a logo.h file (embedding the zipped pixel data as base64 strings in a C source code).  There is a utility bundled with kwwidgets that accomplishes this.  From a Slicer3 build directory you can do something like this:&lt;br /&gt;
&lt;br /&gt;
 ./Slicer3 --launch ../Slicer3-lib/KWWidgets-build/bin/KWConvertImageToHeader --base64 --zlib ~/Desktop/bioimagesuite_logo_www.h ~/Desktop/bioimagesuite_logo_www.png&lt;br /&gt;
&lt;br /&gt;
The resulting .h header file can then be used as an argument to the 'generateclp' cmake macro like this:&lt;br /&gt;
&lt;br /&gt;
 generateclp(${CLP}_SOURCE ${CLP}.xml ${Slicer3_SOURCE_DIR}/Resources/bioimagesuite_logo_www.h)&lt;br /&gt;
&lt;br /&gt;
''Note: logos are limited in size: if your .h file contains a symbol like 'image_bioimagesuite_logo_www' it will work.  But if it has several symbols like 'image_bioimagesuite_logo_www_1' 'image_bioimagesuite_logo_www_2' etc then the logo was too large and needs to be downsampled for use.''&lt;br /&gt;
&lt;br /&gt;
== What do I do if I want to use the CLI outside of slicer? ==&lt;br /&gt;
&lt;br /&gt;
In general CLI executables will depend on shared libraries provided by Slicer (such as ITKCommon, etc).  To be sure your run-time environment resolves to the correct versions, you should always use a form like:&lt;br /&gt;
 ./Slicer3 --launch &amp;lt;CLI&amp;gt;&lt;br /&gt;
or, you can start a shell from which you can run multiple CLI modules.  Something like:&lt;br /&gt;
 ./Slicer3 --launch xterm &amp;amp;&lt;br /&gt;
&lt;br /&gt;
We do not suggest hard-coding the runtime paths into, for example, your .bashrc since this may interfere with other programs and can make it hard to use multiple versions of slicer on the same account.&lt;br /&gt;
&lt;br /&gt;
= Laundry List =&lt;br /&gt;
&lt;br /&gt;
Use this section to describe any features that are missing, not documented, or require additional work.&lt;br /&gt;
&lt;br /&gt;
* Comments from Hans Johnson, June 4, 2010:&lt;br /&gt;
** Enumerated types can only have about 3 characters in them, otherwise they don’t render in the slicer wizard at all.&lt;br /&gt;
** There is no way to unset an enumerated type, and the values are cached even after leaving the module.  If the default enumerated type is to be blank, and you select it, then you must restart slicer in order to make the blank option available again.&lt;br /&gt;
** There is no way to have conditional options.  For example if one flag is used, then other flag can not be used, so it should be disabled.&lt;br /&gt;
* Multiple images, transforms, etc. cannot be selected in the module user interface shown in Slicer (https://issues.slicer.org/view.php?id=4299)&lt;br /&gt;
* Documenting your module:&lt;br /&gt;
** a convenience script has been developed by Hans Johnson, which creates a wiki page describing the command line module by extracting the information from the xml description [[SEMToMediaWiki.py]]. TODO: extract the default values for the parameters to be included in the documentation&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerVirtualReality&amp;diff=60782</id>
		<title>Documentation/Nightly/Extensions/SlicerVirtualReality</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Extensions/SlicerVirtualReality&amp;diff=60782"/>
		<updated>2019-02-04T20:07:56Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Change link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{documentation/banner&lt;br /&gt;
| text  = See [https://slicervr.org SlicerVirtualReality website.]&lt;br /&gt;
| background-color = 8FBC8F }}&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/Segmentations&amp;diff=60698</id>
		<title>Documentation/Nightly/Modules/Segmentations</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/Segmentations&amp;diff=60698"/>
		<updated>2019-01-15T14:31:44Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
This work is part of the SparKit project, funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health and Long-Term Care and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&amp;lt;br&amp;gt;&lt;br /&gt;
Author: Csaba Pinter (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contact: Csaba Pinter, &amp;lt;email&amp;gt;pinter.csaba@gmail.com&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
|{{collaborator|logo|sparkit}}|{{collaborator|longname|sparkit}}&lt;br /&gt;
|{{collaborator|logo|ocairo}}|{{collaborator|longname|ocairo}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
The {{documentation/modulename}} module manages segmentations. Each segmentation can contain multiple segments, which correspond to one structure or ROI. Each segment can contain multiple data representations for the same structure, and the module supports automatic conversion between these representations (the default ones are: planar contour, binary labelmap, closed surface model), as well as advanced display settings and import/export features.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Motivation, features, and details of the infrastructure are explained in [https://www.slicer.org/w/images/6/64/20160526_Segmentations.pptx these slides] ([https://www.slicer.org/w/images/a/ae/20160526_Segmentations.pdf PDF]).'''&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Note: It is important to remember that segmentations are not labelmaps, i.e. they are not one 3D volume containing color indices in a color table. There is a legacy labelmap support that temporarilymerges the segments into an old-school labelmap, but that feature will be removed, and under the hood the segmentation node is structured as explained above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
* 3D printing: Convert labelmaps to surface models and export them to STL&lt;br /&gt;
* Contour analysis: Convert RT planar contours to labelmap for per-voxel analysis&lt;br /&gt;
* Nice and flexible visualization: Show any structure as 3D surface, and line intersections in 2D views; Show surface and labelmap simultaneously&lt;br /&gt;
* Organize segmented structures: Each segmentation contains multiple &amp;quot;segments&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20160526_SegmentationObject.PNG|thumb|371px| Segmentation node containing and managing multiple structures (called segments - the columns in the figure) in multiple representations (rows)]]&lt;br /&gt;
|[[File:20150710_SegmentationsModuleUI.png|thumb|480px| Segmentations module UI]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
&lt;br /&gt;
* [[Documentation/{{documentation/version}}/Training#Slicer4_Image_Segmentation|Segmentation tutorials]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|How to}}&lt;br /&gt;
&lt;br /&gt;
; Edit segmentation&lt;br /&gt;
: Segment structures in the '''[http://slicer.readthedocs.io/en/latest/user_guide/module_segmenteditor.html Segment Editor]''' module&lt;br /&gt;
&lt;br /&gt;
; ''Import labelmap'' volume or ''model'' into segmentation&lt;br /&gt;
# In Segmentations module&lt;br /&gt;
#* Expand Copy/move segment (import/export) section at the bottom of the Segmentations module (it is collapsed by default)&lt;br /&gt;
#* Select labelmap volume or model in the list on the right&lt;br /&gt;
#* Click on '&amp;lt;+' button to import the selected object as a segment to the currently selected segmentation (multiple segments in case of multi-label labelmap)&lt;br /&gt;
# In Data module (Subject hierarchy tab)&lt;br /&gt;
#* Right-click model or model hierarchy node&lt;br /&gt;
#* Select 'Convert model to segmentation node'&lt;br /&gt;
&lt;br /&gt;
; ''Export labelmap'' or surface ''model'' from segmentation (for saving to STL, editing, etc).&lt;br /&gt;
# Expand the Export/import segments section at the bottom of the Segmentations module (it is collapsed by default). Select output type, then click Export. If exporting to an existing node is needed, it can be selected as Output node. If only a subset of the segments are needed, then open the Advanced section, where this selection can be changed, along with the reference volume.&lt;br /&gt;
# Switch to the Data module and make sure the Subject hierarchy tree is selected. Right-click the segmentation node, then select one of the Export functions&lt;br /&gt;
: To save exported result to file, use the Save data dialog (left side of top toolbar). To save to STL, change the File Format selector to STL in the rows of the models to be saved.&lt;br /&gt;
&lt;br /&gt;
; Create new representation in segmentation (conversion)&lt;br /&gt;
: The supported representations are listed as rows in the Representations section. The already existing representations have a green tick, the master representation (that is the source of all conversions and the representation that can be edited) a gold star&lt;br /&gt;
: To create a representation that is missing, click on the Create button in its row. If custom conversion path or parameters are to be used (reference grid for labelmaps, smoothing for surfaces, etc.), long-press the button and choose &amp;quot;Advanced create...&amp;quot;. In the appearing window the available conversion paths are listed in a list, ordered by estimated time cost. After selecting the desired path, the involved parameters are listed in the bottom section of the window&lt;br /&gt;
: To re-convert an existing representation (to use different conversion path or parameters), click the Update buitton in their row&lt;br /&gt;
&lt;br /&gt;
; Change display mode of segments&lt;br /&gt;
# By long-pressing the eye icon in the segments table the display options are shown and the different display modes can be turned on or off&lt;br /&gt;
# In Data module's Subject hierarchy, right-clicking the visibility eye icon next to the segmentation node or its segments also offers advanced display options&lt;br /&gt;
&lt;br /&gt;
; Managing segmentations in python&lt;br /&gt;
: See [https://www.slicer.org/slicerWiki/index.php?title=Documentation/Nightly/ScriptRepository#Segmentations Segmentations section] in the script in repository&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
* Segments table&lt;br /&gt;
** Add/remove segments&lt;br /&gt;
** Edit selected: takes user to [[Documentation/{{documentation/version}}/Modules/SegmentEditor|Segment Editor]] module&lt;br /&gt;
** Set visibility and per-segment display settings, opacity, color, segment name&lt;br /&gt;
* Display&lt;br /&gt;
** Segmentations-wide display settings (not per-segment!): visibility, opacity (will be multiplied with per-segment opacity for display)&lt;br /&gt;
** Views: Individual views to show the active segmentation in&lt;br /&gt;
** Slice intersection thickness&lt;br /&gt;
** Representation in 3D/2D views: The representation to be shown in the 3D and 2D views. Useful if there are multiple representations available, for example if we want to show the closed surface in the 3D view but the labelmap in the slice views&lt;br /&gt;
* Representations&lt;br /&gt;
** List of supported representations and related operations &lt;br /&gt;
** The already existing representations have a green tick, the master representation (that is the source of all conversions and the representation that can be edited) a gold star&lt;br /&gt;
** The buttons in each row can be used to create, remove, update a representation&lt;br /&gt;
*** Advanced conversion is possible (to use the non-default path or conversion parameters) by long-pressing the Create or Update button&lt;br /&gt;
*** Existing representations can be made master by clicking Make master. The master representation is used as source for conversions, it is the one that can be edited, and saved to disk&lt;br /&gt;
* Copy/move (import/export)&lt;br /&gt;
** Left panel lists the segments in the active segmentation&lt;br /&gt;
** Right panel shows the external data container&lt;br /&gt;
** The arrow buttons van be used to copy (with plus sign) or move (no plus sign) segments between the segmentation and the external node&lt;br /&gt;
** New labelmap or model can be created by clicking the appropriate button on the top of the right panel&lt;br /&gt;
** Multiple segments can be exported into a labelmap. In case of overlapping segments, the subsequent segments will overwrite the previous ones!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
''' Subject hierarchy support'''&lt;br /&gt;
* Segmentations are shown in subject hierarchy as any other node, with the exception that the contained segments are in a &amp;quot;virtual branch&amp;quot;.&lt;br /&gt;
** The segments can be moved between segmentations, but drag&amp;amp;drop to anywhere other than under another segmentation is not allowed&lt;br /&gt;
* Special subject hierarchy features for segmentations&lt;br /&gt;
** Create representation: Create the chosen representation using the default path&lt;br /&gt;
* Special subject hierarchy features for segments&lt;br /&gt;
** Show only this segment: Useful if only one segment needs to be shown and there are many, so clicking the eye buttons woud take a long time&lt;br /&gt;
** Show all segments&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
''' DICOM export '''&lt;br /&gt;
* The master representation is used when exporting into DICOM&lt;br /&gt;
* RT structure set export is available if SlicerRT is installed&lt;br /&gt;
* DICOM SegObj export - coming soon!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{documentation/{{documentation/version}}/module-parametersdescription}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
* [http://slicer.readthedocs.io/en/latest/user_guide/module_segmenteditor.html Segment Editor] module is used to edit Segmentation nodes&lt;br /&gt;
* This module and infrastructure is a successor of the [[Documentation/4.4/Modules/Contours|Contours]] module and mechanism, which was the first implementation for this task, but its design was overgrown by the new features and needs, and became inconvenient and unstable. Further information about the Segmentation effort on the related [https://github.com/SlicerRt/SlicerRT/wiki/Segmentation design wiki page], the [https://www.slicer.org/wiki/Documentation/Labs/Segmentations labs wiki page], and the links pointing from these pages.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
* Past references&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
** Issue for Segmentations (complete Contours overhaul, delivery June 2015) [https://www.assembla.com/spaces/slicerrt/tickets/626 here]&lt;br /&gt;
** Issue for original Contours effort on SlicerRT Assembla ticketing system [https://www.assembla.com/spaces/slicerrt/tickets/137 here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
** Development notes [https://github.com/SlicerRt/SlicerRT/wiki/Segmentation wiki page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
* [https://github.com/Slicer/Slicer/tree/master/Libs/vtkSegmentationCore vtkSegmentationCore on GitHub] (within Slicer)&lt;br /&gt;
* [https://github.com/Slicer/Slicer/tree/master/Modules/Loadable/Segmentations Segmentations Slicer module on GitHub]&lt;br /&gt;
* [http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/Segmentations Labs page]&lt;br /&gt;
* Numerous scripting examples are listed in the [https://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/ScriptRepository Script repository] page&lt;br /&gt;
* How to create new representation or converter - TODO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
=FAQ=&lt;br /&gt;
; The closed surface generated from the RT Structure Set contour points is flawed&lt;br /&gt;
: Please [[Documentation/SlicerRT/HowToReportAnError|report]] the issue first so that we can fix the conversion.&lt;br /&gt;
: Use advanced conversion and choose a path through Ribbon model representation. SlicerRT extension needs to be installed for this.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=60588</id>
		<title>Documentation/Nightly/ScriptRepository</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=60588"/>
		<updated>2018-11-30T15:11:37Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add link to Python scripting page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Community-contributed modules=&lt;br /&gt;
&lt;br /&gt;
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.&lt;br /&gt;
&lt;br /&gt;
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 &amp;gt;&amp;gt; next to Additional module paths, click Add, and choose the .py file's location).&lt;br /&gt;
&lt;br /&gt;
More information about python scripted modules and more usage examples can be found in the [[Documentation/{{documentation/version}}/Developers/Python_scripting | Python scripting]] wiki page.&lt;br /&gt;
&lt;br /&gt;
==Filters==&lt;br /&gt;
* [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).&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
* [https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.&lt;br /&gt;
* [https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.&lt;br /&gt;
&lt;br /&gt;
==Informatics==&lt;br /&gt;
* [https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.&lt;br /&gt;
* [https://gist.github.com/lassoan/0e7acfbec36e4577f8b7b0e07ad53a2a LineProfile.py]: Compute intensity profile in a volume along a line.&lt;br /&gt;
&lt;br /&gt;
=Community-contributed examples=&lt;br /&gt;
&lt;br /&gt;
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer.  Or save them to a file and run them using execfile.&lt;br /&gt;
&lt;br /&gt;
==Capture==&lt;br /&gt;
* Capture the full Slicer screen and save it into a file&lt;br /&gt;
  img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()&lt;br /&gt;
  img.save('c:/tmp/test.png')&lt;br /&gt;
* Capture all the views save it into a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
cap.showViewControllers(False)&lt;br /&gt;
cap.captureImageFromView(None,'c:/tmp/test.png')&lt;br /&gt;
cap.showViewControllers(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Capture a single view:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
viewNodeID = 'vtkMRMLViewNode1'&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
cap = ScreenCapture.ScreenCaptureLogic()&lt;br /&gt;
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))&lt;br /&gt;
cap.captureImageFromView(view,'c:/tmp/test.png')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. &lt;br /&gt;
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.&lt;br /&gt;
&lt;br /&gt;
* Capture a slice view sweep into a series of PNG files - for example, Red slice view, 30 images, from position -125.0 to 75.0, into c:/tmp folder, with name image_00001.png, image_00002.png, ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import ScreenCapture&lt;br /&gt;
ScreenCapture.ScreenCaptureLogic().captureSliceSweep(getNode('vtkMRMLSliceNodeRed'), -125.0, 75.0, 30, &amp;quot;c:/tmp&amp;quot;, &amp;quot;image_%05d.png&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Capture 3D view into PNG file with transparent background&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderWindow.SetAlphaBitPlanes(1)&lt;br /&gt;
wti = vtk.vtkWindowToImageFilter()&lt;br /&gt;
wti.SetInputBufferTypeToRGBA()&lt;br /&gt;
wti.SetInput(renderWindow)&lt;br /&gt;
writer = vtk.vtkPNGWriter()&lt;br /&gt;
writer.SetFileName(&amp;quot;c:/tmp/screenshot.png&amp;quot;)&lt;br /&gt;
writer.SetInputConnection(wti.GetOutputPort())&lt;br /&gt;
writer.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Launching Slicer==&lt;br /&gt;
* How to open an .mrb file with Slicer at the command line?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )&amp;quot;&lt;br /&gt;
* How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?&lt;br /&gt;
  Slicer.exe --python-code &amp;quot;doSomething; doSomethingElse; etc.&amp;quot; --testing --no-splash --no-main-window&lt;br /&gt;
&lt;br /&gt;
==Load volume from file==&lt;br /&gt;
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[success, loadedVolumeNode] = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd', returnNode=True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:&lt;br /&gt;
  vol=slicer.util.getNode('MR*')&lt;br /&gt;
  vol.GetImageData().GetDimensions()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Show volume rendering automatically when a volume is loaded==&lt;br /&gt;
&lt;br /&gt;
To show volume rendering of a volume automatically when it is loaded, add the lines below to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def onNodeAdded(caller, event, calldata):&lt;br /&gt;
  node = calldata&lt;br /&gt;
  if isinstance(node, slicer.vtkMRMLVolumeNode):&lt;br /&gt;
    # Call showVolumeRendering using a timer instead of calling it directly&lt;br /&gt;
    # to allow the volume loading to fully complete.&lt;br /&gt;
    qt.QTimer.singleShot(0, lambda: showVolumeRendering(node))&lt;br /&gt;
&lt;br /&gt;
def showVolumeRendering(volumeNode):&lt;br /&gt;
  print(&amp;quot;Show volume rendering of node &amp;quot;+volumeNode.GetName())&lt;br /&gt;
  volRenLogic = slicer.modules.volumerendering.logic()&lt;br /&gt;
  displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)&lt;br /&gt;
  displayNode.SetVisibility(True)&lt;br /&gt;
  scalarRange = volumeNode.GetImageData().GetScalarRange()&lt;br /&gt;
  if scalarRange[1]-scalarRange[0] &amp;lt; 1500:&lt;br /&gt;
    # small dynamic range, probably MRI&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('MR-Default'))&lt;br /&gt;
  else:&lt;br /&gt;
    # larger dynamic range, probably CT&lt;br /&gt;
    displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))&lt;br /&gt;
    &lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DICOM==&lt;br /&gt;
=== How to access tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' &amp;quot;0020,0032&amp;quot; field:===&lt;br /&gt;
  db=slicer.dicomDatabase&lt;br /&gt;
  patientList=db.patients()&lt;br /&gt;
  studyList=db.studiesForPatient(patientList[0])&lt;br /&gt;
  seriesList=db.seriesForStudy(studyList[0])&lt;br /&gt;
  fileList=db.filesForSeries(seriesList[0])&lt;br /&gt;
  print(db.fileValue(fileList[0],'0020,0032'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===&lt;br /&gt;
  volumeName='2: ENT IMRT'&lt;br /&gt;
  n=slicer.util.getNode(volumeName)&lt;br /&gt;
  instUids=n.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
  filename=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0018,5100'))&lt;br /&gt;
&lt;br /&gt;
=== How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===&lt;br /&gt;
  rtStructName = '3: RTSTRUCT: PROS'&lt;br /&gt;
  rtStructNode = slicer.util.getNode(rtStructName)&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
  rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)&lt;br /&gt;
  ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()&lt;br /&gt;
  filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])&lt;br /&gt;
  print(slicer.dicomDatabase.fileValue(filename,'0008,0033'))&lt;br /&gt;
&lt;br /&gt;
=== How to get path and filename of a loaded DICOM volume?===&lt;br /&gt;
  def pathFromNode(node):&lt;br /&gt;
    storageNode=node.GetStorageNode()&lt;br /&gt;
    if storageNode is not None: # loaded via drag-drop&lt;br /&gt;
        filepath=storageNode.GetFullNameFromFileName()&lt;br /&gt;
    else: # loaded via DICOM browser&lt;br /&gt;
        instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()&lt;br /&gt;
        filepath=slicer.dicomDatabase.fileForInstance(instUids[0])&lt;br /&gt;
    return filepath&lt;br /&gt;
  &lt;br /&gt;
  # example:&lt;br /&gt;
  node=slicer.util.getNode('volume1')&lt;br /&gt;
  path=self.pathFromNode(node)&lt;br /&gt;
  print(&amp;quot;DICOM path=%s&amp;quot; % path)&lt;br /&gt;
&lt;br /&gt;
=== How can I convert DICOM to NRRD on the command line?===&lt;br /&gt;
&lt;br /&gt;
 /Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code &amp;quot;node=slicer.util.loadVolume('/tmp/series/im0.dcm', returnNode=True)[1]; slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()&amp;quot;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Export a volume to DICOM file format ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('CTChest')&lt;br /&gt;
outputFolder = &amp;quot;c:/tmp/dicom-output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Create patient and study and put the volume under the study&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), &amp;quot;test patient&amp;quot;)&lt;br /&gt;
studyItemID = shNode.CreateStudyItem(patientItemID, &amp;quot;test study&amp;quot;)&lt;br /&gt;
volumeShItemID = shNode.GetItemByDataNode(volumeNode)&lt;br /&gt;
shNode.SetItemParent(volumeShItemID, studyItemID)&lt;br /&gt;
&lt;br /&gt;
import DICOMScalarVolumePlugin&lt;br /&gt;
exporter = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()&lt;br /&gt;
exportables = exporter.examineForExport(volumeShItemID)&lt;br /&gt;
for exp in exportables:&lt;br /&gt;
  exp.directory = outputFolder&lt;br /&gt;
&lt;br /&gt;
exporter.export(exportables)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Toolbar functions==&lt;br /&gt;
* How to turn on slice intersections in the crosshair menu on the toolbar:&lt;br /&gt;
  viewNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  viewNodes.UnRegister(slicer.mrmlScene)&lt;br /&gt;
  viewNodes.InitTraversal()&lt;br /&gt;
  viewNode = viewNodes.GetNextItemAsObject()&lt;br /&gt;
  while viewNode:&lt;br /&gt;
    viewNode.SetSliceIntersectionVisibility(1)&lt;br /&gt;
    viewNode = viewNodes.GetNextItemAsObject()&lt;br /&gt;
&lt;br /&gt;
How to find similar functions? For this one I searched for &amp;quot;slice intersections&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
==Manipulating objects in the slice viewer==&lt;br /&gt;
* How to define/edit a circular region of interest in a slice viewer?&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update the sphere from the fiducial points&lt;br /&gt;
def UpdateSphere(param1, param2):  &lt;br /&gt;
  import math&lt;br /&gt;
  centerPointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(0,centerPointCoord)&lt;br /&gt;
  circumferencePointCoord = [0.0, 0.0, 0.0]&lt;br /&gt;
  markups.GetNthFiducialPosition(1,circumferencePointCoord)&lt;br /&gt;
  sphere.SetCenter(centerPointCoord)&lt;br /&gt;
  radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)&lt;br /&gt;
  sphere.SetRadius(radius)&lt;br /&gt;
  sphere.SetPhiResolution(30)&lt;br /&gt;
  sphere.SetThetaResolution(30)&lt;br /&gt;
  sphere.Update()&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
markups=slicer.util.getNode('F')&lt;br /&gt;
sphere = vtk.vtkSphereSource()&lt;br /&gt;
UpdateSphere(0,0)&lt;br /&gt;
 &lt;br /&gt;
# Create model node and add to scene&lt;br /&gt;
modelsLogic = slicer.modules.models.logic()&lt;br /&gt;
model = modelsLogic.AddModel(sphere.GetOutput())&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionVisibility(True)&lt;br /&gt;
model.GetDisplayNode().SetSliceIntersectionThickness(3)&lt;br /&gt;
model.GetDisplayNode().SetColor(1,1,0)&lt;br /&gt;
 &lt;br /&gt;
# Call UpdateSphere whenever the fiducials are changed&lt;br /&gt;
markups.AddObserver(&amp;quot;ModifiedEvent&amp;quot;, UpdateSphere, 2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set slice position and orientation from 3 markup fiducials==&lt;br /&gt;
&lt;br /&gt;
Drop 3 markup points in the scene and copy-paste the code below into the Python console. After this, as you move the markups you’ll see the red slice view position and orientation will be set to make it fit to the 3 points.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Update plane from fiducial points&lt;br /&gt;
def UpdateSlicePlane(param1=None, param2=None):&lt;br /&gt;
  # Get point positions as numpy array&lt;br /&gt;
  import numpy as np&lt;br /&gt;
  nOfFiduciallPoints = markups.GetNumberOfFiducials()&lt;br /&gt;
  if nOfFiduciallPoints &amp;lt; 3:&lt;br /&gt;
    return  # not enough points&lt;br /&gt;
  points = np.zeros([3,nOfFiduciallPoints])&lt;br /&gt;
  for i in range(0, nOfFiduciallPoints):&lt;br /&gt;
    markups.GetNthFiducialPosition(i, points[:,i])&lt;br /&gt;
  # Compute plane position and normal&lt;br /&gt;
  planePosition = points.mean(axis=1)&lt;br /&gt;
  planeNormal = np.cross(points[:,1] - points[:,0], points[:,2] - points[:,0])&lt;br /&gt;
  planeX = points[:,1] - points[:,0]&lt;br /&gt;
  sliceNode.SetSliceToRASByNTP(planeNormal[0], planeNormal[1], planeNormal[2],&lt;br /&gt;
    planeX[0], planeX[1], planeX[2],&lt;br /&gt;
    planePosition[0], planePosition[1], planePosition[2], 0)&lt;br /&gt;
&lt;br /&gt;
# Get markup node from scene&lt;br /&gt;
sliceNode = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()&lt;br /&gt;
markups = slicer.util.getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Update slice plane manually&lt;br /&gt;
UpdateSlicePlane()&lt;br /&gt;
&lt;br /&gt;
# Update slice plane automatically whenever points are changed&lt;br /&gt;
markupObservation = [markups, markups.AddObserver(&amp;quot;ModifiedEvent&amp;quot;, UpdateSlicePlane, 2)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To stop automatic updates, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
markupObservation[0].RemoveObserver(markupObservation[1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Switching to markup fiducial placement mode ==&lt;br /&gt;
&lt;br /&gt;
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactionNode = slicer.app.applicationLogic().GetInteractionNode()&lt;br /&gt;
selectionNode = slicer.app.applicationLogic().GetSelectionNode()&lt;br /&gt;
selectionNode.SetReferenceActivePlaceNodeClassName(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()&lt;br /&gt;
slicer.mrmlScene.AddNode(fiducialNode)&lt;br /&gt;
fiducialNode.CreateDefaultDisplayNodes() &lt;br /&gt;
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())&lt;br /&gt;
interactionNode.SetCurrentInteractionMode(interactionNode.Place)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a markup point position is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMarkupsNodeModified(markupsNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  sliceView = markupsNode.GetAttribute('Markups.MovingInSliceView')&lt;br /&gt;
  if not sliceView:&lt;br /&gt;
    print(&amp;quot;Markup list was modified&amp;quot;)&lt;br /&gt;
    return&lt;br /&gt;
  movingMarkupIndex = markupsNode.GetAttribute('Markups.MovingMarkupIndex')&lt;br /&gt;
  pos = [0,0,0]&lt;br /&gt;
  markupsNode.GetNthFiducialPosition(int(movingMarkupIndex), pos)  &lt;br /&gt;
  print(&amp;quot;Markup {0} was moved in slice view {1} to {2}&amp;quot;.format(movingMarkupIndex, sliceView, pos))&lt;br /&gt;
&lt;br /&gt;
markupsNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLMarkupsFiducialNode&amp;quot;)&lt;br /&gt;
markupsNode.CreateDefaultDisplayNodes()&lt;br /&gt;
markupsNode.AddFiducial(0,0,0)&lt;br /&gt;
markupsNode.AddObserver(vtk.vtkCommand.ModifiedEvent, onMarkupsNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Get a notification if a transform is modified ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onTransformNodeModified(transformNode, unusedArg2=None, unusedArg3=None):&lt;br /&gt;
  transformMatrix = vtk.vtkMatrix4x4()&lt;br /&gt;
  transformNode.GetMatrixTransformToWorld(transformMatrix)&lt;br /&gt;
  print(&amp;quot;Position: [{0}, {1}, {2}]&amp;quot;.format(transformMatrix.GetElement(0,3), transformMatrix.GetElement(1,3), transformMatrix.GetElement(2,3)))&lt;br /&gt;
&lt;br /&gt;
transformNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTransformNode&amp;quot;)&lt;br /&gt;
transformNode.AddObserver(slicer.vtkMRMLTransformNode.TransformModifiedEvent, onTransformNodeModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a context menu when a markup point is clicked in a slice or 3D view ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Example actions to perform&lt;br /&gt;
&lt;br /&gt;
def action1():&lt;br /&gt;
  print('Action1 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action2():&lt;br /&gt;
  print('Action2 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
def action3():&lt;br /&gt;
  print('Action3 on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
&lt;br /&gt;
# Clicked markup index is saved here to let the action&lt;br /&gt;
# know which markup needs to be manipulated.&lt;br /&gt;
slicer.clickedMarkupIndex = -1&lt;br /&gt;
  &lt;br /&gt;
# Create a simple menu&lt;br /&gt;
&lt;br /&gt;
menu = qt.QMenu()&lt;br /&gt;
a1 = qt.QAction(&amp;quot;Test&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a1.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a1)&lt;br /&gt;
a2 = qt.QAction(&amp;quot;Action&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a2.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a2)&lt;br /&gt;
a3 = qt.QAction(&amp;quot;Here&amp;quot;, slicer.util.mainWindow())&lt;br /&gt;
a3.connect('triggered()', action1)&lt;br /&gt;
menu.addAction(a3)&lt;br /&gt;
&lt;br /&gt;
# Add observer to a markup fiducial list&lt;br /&gt;
&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_INT)&lt;br /&gt;
def markupClickedCallback(caller, eventId, callData):&lt;br /&gt;
  slicer.clickedMarkupIndex = callData&lt;br /&gt;
  print('Open menu on markup '+str(slicer.clickedMarkupIndex))&lt;br /&gt;
  menu.move(qt.QCursor.pos())&lt;br /&gt;
  menu.show()&lt;br /&gt;
&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
observerTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointClickedEvent, markupClickedCallback)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add a texture mapped plane to the scene as a model ==&lt;br /&gt;
Note that model textures are not exposed in the GUI and are not saved in the scene&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# use dummy image data here&lt;br /&gt;
e = vtk.vtkImageEllipsoidSource()&lt;br /&gt;
&lt;br /&gt;
scene = slicer.mrmlScene&lt;br /&gt;
&lt;br /&gt;
# Create model node&lt;br /&gt;
model = slicer.vtkMRMLModelNode()&lt;br /&gt;
model.SetScene(scene)&lt;br /&gt;
model.SetName(scene.GenerateUniqueName(&amp;quot;2DImageModel&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
planeSource = vtk.vtkPlaneSource()&lt;br /&gt;
model.SetAndObservePolyData(planeSource.GetOutput())&lt;br /&gt;
&lt;br /&gt;
# Create display node&lt;br /&gt;
modelDisplay = slicer.vtkMRMLModelDisplayNode()&lt;br /&gt;
modelDisplay.SetColor(1,1,0) # yellow&lt;br /&gt;
modelDisplay.SetBackfaceCulling(0)&lt;br /&gt;
modelDisplay.SetScene(scene)&lt;br /&gt;
scene.AddNode(modelDisplay)&lt;br /&gt;
model.SetAndObserveDisplayNodeID(modelDisplay.GetID())&lt;br /&gt;
&lt;br /&gt;
# Add to scene&lt;br /&gt;
modelDisplay.SetAndObserveTextureImageData(e.GetOutput())&lt;br /&gt;
scene.AddNode(model) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
transform = slicer.vtkMRMLLinearTransformNode()&lt;br /&gt;
scene.AddNode(transform) &lt;br /&gt;
model.SetAndObserveTransformNodeID(transform.GetID())&lt;br /&gt;
&lt;br /&gt;
vTransform = vtk.vtkTransform()&lt;br /&gt;
vTransform.Scale(50,50,50)&lt;br /&gt;
vTransform.RotateX(30)&lt;br /&gt;
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Export entire scene as VRML ==&lt;br /&gt;
&lt;br /&gt;
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exporter = vtk.vtkVRMLExporter()&lt;br /&gt;
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())&lt;br /&gt;
exporter.SetFileName('C:/tmp/something.wrl')&lt;br /&gt;
exporter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export model to Blender, including color by scalar ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modelNode = getNode(&amp;quot;Model&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;c:/tmp/model.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
modelDisplayNode = modelNode.GetDisplayNode()&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputConnection(triangles.GetOutputPort())&lt;br /&gt;
lut = vtk.vtkLookupTable()&lt;br /&gt;
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())&lt;br /&gt;
lut.SetRange(modelDisplayNode.GetScalarRange())&lt;br /&gt;
plyWriter.SetLookupTable(lut)&lt;br /&gt;
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export a tract (FiberBundle) to Blender, including color ==&lt;br /&gt;
&amp;lt;div id=&amp;quot;Export_a_fiber_tracts_to_Blender.2C_including_color&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Note: an interactive version of this script is now included in the [http://dmri.slicer.org/ SlicerDMRI extension] ([https://github.com/SlicerDMRI/SlicerDMRI/tree/master/Modules/Scripted/TractographyExportPLY module code]). &lt;br /&gt;
After installing SlicerDMRI, go to ''Modules -&amp;gt; Diffusion -&amp;gt; Import and Export -&amp;gt; Export tractography to PLY (mesh)''.&lt;br /&gt;
&lt;br /&gt;
The example below shows how to export a tractography &amp;quot;FiberBundleNode&amp;quot; to a PLY file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lineDisplayNode = getNode(&amp;quot;*LineDisplay*&amp;quot;)&lt;br /&gt;
plyFilePath = &amp;quot;/tmp/fibers.ply&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tuber = vtk.vtkTubeFilter()&lt;br /&gt;
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())&lt;br /&gt;
tuber.Update()&lt;br /&gt;
tubes = tuber.GetOutputDataObject(0)&lt;br /&gt;
scalars = tubes.GetPointData().GetArray(0)&lt;br /&gt;
scalars.SetName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
triangles = vtk.vtkTriangleFilter()&lt;br /&gt;
triangles.SetInputData(tubes)&lt;br /&gt;
triangles.Update()&lt;br /&gt;
&lt;br /&gt;
colorNode = lineDisplayNode.GetColorNode()&lt;br /&gt;
lookupTable = vtk.vtkLookupTable()&lt;br /&gt;
lookupTable.DeepCopy(colorNode.GetLookupTable())&lt;br /&gt;
lookupTable.SetTableRange(0,1)&lt;br /&gt;
&lt;br /&gt;
plyWriter = vtk.vtkPLYWriter()&lt;br /&gt;
plyWriter.SetInputData(triangles.GetOutput())&lt;br /&gt;
plyWriter.SetLookupTable(lookupTable)&lt;br /&gt;
plyWriter.SetArrayName(&amp;quot;scalars&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plyWriter.SetFileName(plyFilePath)&lt;br /&gt;
plyWriter.Write()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Iterate over tract (FiberBundle) streamline points ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to access the points in each line of a FiberBundle as a numpy array (view).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from vtk.util.numpy_support import vtk_to_numpy&lt;br /&gt;
&lt;br /&gt;
fb = getNode(&amp;quot;FiberBundle_F&amp;quot;) # &amp;lt;- fill in node ID here&lt;br /&gt;
&lt;br /&gt;
# get point data as 1d array&lt;br /&gt;
points = slicer.util.arrayFromModelPoints(fb)&lt;br /&gt;
&lt;br /&gt;
# get line cell ids as 1d array&lt;br /&gt;
line_ids = vtk_to_numpy(fb.GetPolyData().GetLines().GetData())&lt;br /&gt;
&lt;br /&gt;
# VTK cell ids are stored as&lt;br /&gt;
#   [ N0 c0_id0 ... c0_id0&lt;br /&gt;
#     N1 c1_id0 ... c1_idN1 ]&lt;br /&gt;
# so we need to&lt;br /&gt;
# - read point count for each line (cell)&lt;br /&gt;
# - grab the ids in that range from `line_ids` array defined above&lt;br /&gt;
# - index the `points` array by those ids&lt;br /&gt;
cur_idx = 1&lt;br /&gt;
for _ in range(pd.GetLines().GetNumberOfCells()):&lt;br /&gt;
    # - read point count for this line (cell)&lt;br /&gt;
    count = lines[cur_idx - 1]&lt;br /&gt;
&lt;br /&gt;
    # - grab the ids in that range from `lines`&lt;br /&gt;
    index_array = line_ids[ cur_idx : cur_idx + count]&lt;br /&gt;
    # update to the next range &lt;br /&gt;
    cur_idx += count + 1&lt;br /&gt;
&lt;br /&gt;
    # - index the point array by those ids&lt;br /&gt;
    line_points = points[index_array]&lt;br /&gt;
&lt;br /&gt;
    # do work here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a node ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to make a copy of any node that appears in Subject Hierarchy (in Data module).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a node from SampleData that we will clone&lt;br /&gt;
import SampleData&lt;br /&gt;
nodeToClone = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Clone the node&lt;br /&gt;
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
itemIDToClone = shNode.GetItemByDataNode(nodeToClone)&lt;br /&gt;
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)&lt;br /&gt;
clonedNode = shNode.GetItemDataNode(clonedItemID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Clone a volume ==&lt;br /&gt;
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sourceVolumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
volumesLogic = slicer.modules.volumes.logic()&lt;br /&gt;
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a new volume ==&lt;br /&gt;
This example shows how to create a new empty volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = &amp;quot;MyNewVolume&amp;quot;&lt;br /&gt;
imageSize = [512, 512, 512]&lt;br /&gt;
voxelType=vtk.VTK_UNSIGNED_CHAR&lt;br /&gt;
imageOrigin = [0.0, 0.0, 0.0]&lt;br /&gt;
imageSpacing = [1.0, 1.0, 1.0]&lt;br /&gt;
imageDirections = [[1,0,0], [0,1,0], [0,0,1]]&lt;br /&gt;
fillVoxelValue = 0&lt;br /&gt;
&lt;br /&gt;
# Create an empty image volume, filled with fillVoxelValue&lt;br /&gt;
imageData = vtk.vtkImageData()&lt;br /&gt;
imageData.SetDimensions(imageSize)&lt;br /&gt;
imageData.AllocateScalars(voxelType, 1)&lt;br /&gt;
thresholder = vtk.vtkImageThreshold()&lt;br /&gt;
thresholder.SetInputData(imageData)&lt;br /&gt;
thresholder.SetInValue(fillVoxelValue)&lt;br /&gt;
thresholder.SetOutValue(fillVoxelValue)&lt;br /&gt;
thresholder.Update()&lt;br /&gt;
# Create volume node&lt;br /&gt;
volumeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScalarVolumeNode&amp;quot;, nodeName)&lt;br /&gt;
volumeNode.SetOrigin(imageOrigin)&lt;br /&gt;
volumeNode.SetSpacing(imageSpacing)&lt;br /&gt;
volumeNode.SetIJKToRASDirections(imageDirections)&lt;br /&gt;
volumeNode.SetAndObserveImageData(thresholder.GetOutput())&lt;br /&gt;
volumeNode.CreateDefaultDisplayNodes()&lt;br /&gt;
volumeNode.CreateDefaultStorageNode()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modify voxels in a volume ==&lt;br /&gt;
&lt;br /&gt;
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nodeName = 'MRHead'&lt;br /&gt;
thresholdValue = 100&lt;br /&gt;
voxelArray = array(nodeName) # get voxels as numpy array&lt;br /&gt;
voxelArray[voxelArray &amp;lt; thresholdValue] = 0 # modify voxel values&lt;br /&gt;
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows how to change voxels values of the MRHead sample volume.&lt;br /&gt;
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('MRHead')&lt;br /&gt;
ijkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(ijkToRas)&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
for k in xrange(extent[4], extent[5]+1):&lt;br /&gt;
  for j in xrange(extent[2], extent[3]+1):&lt;br /&gt;
    for i in xrange(extent[0], extent[1]+1):&lt;br /&gt;
      position_Ijk=[i, j, k, 1]&lt;br /&gt;
      position_Ras=ijkToRas.MultiplyPoint(position_Ijk)&lt;br /&gt;
      r=position_Ras[0]&lt;br /&gt;
      a=position_Ras[1]&lt;br /&gt;
      s=position_Ras[2]      &lt;br /&gt;
      functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s&lt;br /&gt;
      imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)&lt;br /&gt;
imageData.SetScalarComponentFromFloat(distortionVectorPosition_Ijk[0], distortionVectorPosition_Ijk[1], distortionVectorPosition_Ijk[2], 0, fillValue)&lt;br /&gt;
imageData.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get volume voxel coordinates from markup fiducial RAS coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get voxel coordinate of a volume corresponding to a markup fiducial point position.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
markupsIndex = 0&lt;br /&gt;
&lt;br /&gt;
# Get point coordinate in RAS&lt;br /&gt;
point_Ras = [0, 0, 0, 1]&lt;br /&gt;
markupsNode.GetNthFiducialWorldCoordinates(markupsIndex, point_Ras)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformRasToVolumeRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(None, volumeNode.GetParentTransformNode(), transformRasToVolumeRas)&lt;br /&gt;
point_VolumeRas = transformRasToVolumeRas.TransformPoint(point_Ras[0:3])&lt;br /&gt;
&lt;br /&gt;
# Get voxel coordinates from physical coordinates&lt;br /&gt;
volumeRasToIjk = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetRASToIJKMatrix(volumeRasToIjk)&lt;br /&gt;
point_Ijk = [0, 0, 0, 1]&lt;br /&gt;
volumeRasToIjk.MultiplyPoint(np.append(point_VolumeRas,1.0), point_Ijk)&lt;br /&gt;
point_Ijk = [ int(round(c)) for c in point_Ijk[0:3] ]&lt;br /&gt;
&lt;br /&gt;
# Print output&lt;br /&gt;
print(point_Ijk)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get markup fiducial RAS coordinates from volume voxel coordinates ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to get position of maximum intensity voxel of a volume (determined by numpy, in IJK coordinates) in RAS coordinates so that it can be marked with a markup fiducial.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Inputs&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
markupsNode = getNode('F')&lt;br /&gt;
&lt;br /&gt;
# Get voxel position in IJK coordinate system&lt;br /&gt;
import numpy as np&lt;br /&gt;
volumeArray = slicer.util.arrayFromVolume(volumeNode)&lt;br /&gt;
# Get position of highest voxel value&lt;br /&gt;
point_Kji = np.where(volumeArray == volumeArray.max())&lt;br /&gt;
point_Ijk = [point_Kji[2][0], point_Kji[1][0], point_Kji[0][0]]&lt;br /&gt;
&lt;br /&gt;
# Get physical coordinates from voxel coordinates&lt;br /&gt;
volumeIjkToRas = vtk.vtkMatrix4x4()&lt;br /&gt;
volumeNode.GetIJKToRASMatrix(volumeIjkToRas)&lt;br /&gt;
point_VolumeRas = [0, 0, 0, 1]&lt;br /&gt;
volumeIjkToRas.MultiplyPoint(np.append(point_Ijk,1.0), point_VolumeRas)&lt;br /&gt;
&lt;br /&gt;
# If volume node is transformed, apply that transform to get volume's RAS coordinates&lt;br /&gt;
transformVolumeRasToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(volumeNode.GetParentTransformNode(), None, transformVolumeRasToRas)&lt;br /&gt;
point_Ras = transformVolumeRasToRas.TransformPoint(point_VolumeRas[0:3])&lt;br /&gt;
&lt;br /&gt;
# Add a markup at the computed position and print its coordinates&lt;br /&gt;
markupsNode.AddFiducial(point_Ras[0], point_Ras[1], point_Ras[2], &amp;quot;max&amp;quot;)&lt;br /&gt;
print(point_Ras)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get the values of all voxels for a label value  ==&lt;br /&gt;
&lt;br /&gt;
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy&lt;br /&gt;
volume = array(‘Volume’)&lt;br /&gt;
label = array(‘Volume-label’)&lt;br /&gt;
points  = numpy.where( label == 1 )  # or use another label number depending on what you segmented&lt;br /&gt;
values  = volume[points] # this will be a list of the label values&lt;br /&gt;
values.mean() # should match the mean value of LabelStatistics calculation as a double-check&lt;br /&gt;
numpy.savetxt(‘values.txt’, values)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Access values in a DTI tensor volume ==&lt;br /&gt;
This example shows how to access individual tensors at the voxel level.&lt;br /&gt;
&lt;br /&gt;
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’&lt;br /&gt;
&lt;br /&gt;
Then open the python window: View-&amp;gt;Python interactor&lt;br /&gt;
&lt;br /&gt;
Use this command to access tensors through numpy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tensors = array('Output DTI Volume')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Type the following code into the Python window to access all tensor components using vtk commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode=slicer.util.getNode('Output DTI Volume')&lt;br /&gt;
imageData=volumeNode.GetImageData()&lt;br /&gt;
tensors = imageData.GetPointData().GetTensors()&lt;br /&gt;
extent = imageData.GetExtent()&lt;br /&gt;
idx = 0&lt;br /&gt;
for k in xrange(extent[4], extent[5]+1):&lt;br /&gt;
  for j in xrange(extent[2], extent[3]+1):&lt;br /&gt;
    for i in xrange(extent[0], extent[1]+1):&lt;br /&gt;
      tensors.GetTuple9(idx)&lt;br /&gt;
      idx += 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change window/level (brightness/contrast) or colormap of a volume ==&lt;br /&gt;
This example shows how to change window/level of the MRHead sample volume.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = getNode('MRHead')&lt;br /&gt;
displayNode = volumeNode.GetDisplayNode()&lt;br /&gt;
displayNode.AutoWindowLevelOff()&lt;br /&gt;
displayNode.SetWindow(50)&lt;br /&gt;
displayNode.SetLevel(100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change color mapping from grayscale to rainbow:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create custom color table ==&lt;br /&gt;
This example shows how to create a new color table, for example with inverted color range from the default Ocean color table.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
invertedocean = slicer.vtkMRMLColorTableNode()&lt;br /&gt;
invertedocean.SetTypeToUser()&lt;br /&gt;
invertedocean.SetNumberOfColors(256)&lt;br /&gt;
invertedocean.SetName(&amp;quot;InvertedOcean&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(0,255):&lt;br /&gt;
    invertedocean.SetColor(i, 0.0, 1 - (i+1e-16)/255.0, 1.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
slicer.mrmlScene.AddNode(invertedocean)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Manipulate a Slice View ==&lt;br /&gt;
&lt;br /&gt;
=== Change the slice offset ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to moving the slider in slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
red = layoutManager.sliceWidget('Red')&lt;br /&gt;
redLogic = red.sliceLogic()&lt;br /&gt;
# Print current slice offset position&lt;br /&gt;
print(redLogic.GetSliceOffset())&lt;br /&gt;
# Change slice position&lt;br /&gt;
redLogic.SetSliceOffset(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show slice views in 3D window ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to clicking 'eye' icon in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  controller = layoutManager.sliceWidget(sliceViewName).sliceController()&lt;br /&gt;
  controller.setSliceVisible(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reset field of view to show background volume maximized ===&lt;br /&gt;
&lt;br /&gt;
Equivalent to click small rectangle button (&amp;quot;Adjust the slice viewer's field of view...&amp;quot;) in the slice view controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.resetSliceViews()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rotate slice views to volume plane ===&lt;br /&gt;
&lt;br /&gt;
Aligns slice views to volume axes, shows original image acquisition planes in slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('MRHead')&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  layoutManager.sliceWidget(sliceViewName).mrmlSliceNode().RotateToVolumePlane(volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Iterate over current visible slice views, and set foreground and background images ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=mrVolume, foreground=ctVolume)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Internally, this method performs something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     sliceWidget = layoutManager.sliceWidget(sliceViewName)&lt;br /&gt;
     # setup background volume&lt;br /&gt;
     compositeNode.SetBackgroundVolumeID(mrVolume.GetID())&lt;br /&gt;
     # setup foreground volume&lt;br /&gt;
     compositeNode.SetForegroundVolumeID(ctVolume.GetID())&lt;br /&gt;
     # change opacity&lt;br /&gt;
     compositeNode.SetForegroundOpacity(0.3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Synchronize zoom factor between slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.sliceNodes = [slicer.app.layoutManager().sliceWidget(viewName).mrmlSliceNode()&lt;br /&gt;
    for viewName in slicer.app.layoutManager().sliceViewNames()]&lt;br /&gt;
&lt;br /&gt;
slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
def sliceModified(caller, event):&lt;br /&gt;
    if slicer.updatingSliceNodes:&lt;br /&gt;
        # prevent infinite loop of slice node updates triggering slice node updates&lt;br /&gt;
        return&lt;br /&gt;
    slicer.updatingSliceNodes = True&lt;br /&gt;
    fov = caller.GetFieldOfView()&lt;br /&gt;
    for sliceNode in slicer.sliceNodes:&lt;br /&gt;
        if sliceNode != caller:&lt;br /&gt;
            sliceNode.SetFieldOfView(*fov)&lt;br /&gt;
    slicer.updatingSliceNodes = False&lt;br /&gt;
&lt;br /&gt;
for sliceNode in slicer.sliceNodes:&lt;br /&gt;
    sliceNode.AddObserver(vtk.vtkCommand.ModifiedEvent, sliceModified)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
Recommended:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
slicer.util.setSliceViewerLayers(background=volumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in all visible views where volume selection propagation is enabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
volumeNode = slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
applicationLogic = slicer.app.applicationLogic()&lt;br /&gt;
selectionNode = applicationLogic.GetSelectionNode()&lt;br /&gt;
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())&lt;br /&gt;
applicationLogic.PropagateForegroundVolumeSelection(0) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Show volume in selected views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
n =  slicer.util.getNode('YourVolumeNode')&lt;br /&gt;
for color in ['Red', 'Yellow', 'Green']:&lt;br /&gt;
    slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change opacity of foreground volume in slice views ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slicer.util.setSliceViewerLayers(foregroundOpacity=0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
Change opacity in a selected view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
sliceLogic = lm.sliceWidget('Red').sliceLogic()&lt;br /&gt;
compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
compositeNode.SetForegroundOpacity(0.4)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fit slice plane to markup fiducials ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID(&amp;quot;vtkMRMLSliceNodeRed&amp;quot;)&lt;br /&gt;
markupsNode = slicer.mrmlScene.GetFirstNodeByName(&amp;quot;F&amp;quot;)&lt;br /&gt;
# Get markup point positions as numpy arrays&lt;br /&gt;
import numpy as np&lt;br /&gt;
p1 = np.array([0,0,0])&lt;br /&gt;
p2 = np.array([0,0,0])&lt;br /&gt;
p3 = np.array([0,0,0])&lt;br /&gt;
markupsNode.GetNthFiducialPosition(0, p1)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(1, p2)&lt;br /&gt;
markupsNode.GetNthFiducialPosition(2, p3)&lt;br /&gt;
# Get plane axis directions&lt;br /&gt;
n = np.cross(p2-p1, p2-p3) # plane normal direction&lt;br /&gt;
n = n/np.linalg.norm(n)&lt;br /&gt;
t = np.cross([0, 0, 1], n) # plane transverse direction&lt;br /&gt;
t = t/np.linalg.norm(t)&lt;br /&gt;
# Set slice plane orientation and position&lt;br /&gt;
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a series of images from a Slice View ==&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;execfile('/tmp/record.py')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutName = 'Green'&lt;br /&gt;
imagePathPattern = '/tmp/image-%03d.png'&lt;br /&gt;
steps = 10&lt;br /&gt;
&lt;br /&gt;
widget = slicer.app.layoutManager().sliceWidget(layoutName)&lt;br /&gt;
view = widget.sliceView()&lt;br /&gt;
logic = widget.sliceLogic()&lt;br /&gt;
bounds = [0,]*6&lt;br /&gt;
logic.GetSliceBounds(bounds)&lt;br /&gt;
&lt;br /&gt;
for step in range(steps):&lt;br /&gt;
    offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])&lt;br /&gt;
    logic.SetSliceOffset(offset)&lt;br /&gt;
    view.forceRender()&lt;br /&gt;
    image = qt.QPixmap.grabWidget(view).toImage()&lt;br /&gt;
    image.save(imagePathPattern % step)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a new directory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Create a new directory where the scene will be saved into&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveDirectory = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;)&lt;br /&gt;
if not os.access(sceneSaveDirectory, os.F_OK):&lt;br /&gt;
  os.makedirs(sceneSaveDirectory)&lt;br /&gt;
&lt;br /&gt;
# Save the scene&lt;br /&gt;
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveDirectory))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save the scene into a single MRB file ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Generate file name&lt;br /&gt;
import time&lt;br /&gt;
sceneSaveFilename = slicer.app.temporaryPath + &amp;quot;/saved-scene-&amp;quot; + time.strftime(&amp;quot;%Y%m%d-%H%M%S&amp;quot;) + &amp;quot;.mrb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Save scene&lt;br /&gt;
if slicer.util.saveScene(sceneSaveFilename):&lt;br /&gt;
  logging.info(&amp;quot;Scene saved to: {0}&amp;quot;.format(sceneSaveFilename))&lt;br /&gt;
else:&lt;br /&gt;
  logging.error(&amp;quot;Scene saving failed&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Save a node to file ==&lt;br /&gt;
&lt;br /&gt;
Save a transform node to file (should work with any other node type, if file extension is set to a supported one):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myNode = getNode(&amp;quot;LinearTransform_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
myStorageNode = myNode.CreateDefaultStorageNode()&lt;br /&gt;
myStorageNode.SetFileName(&amp;quot;c:/tmp/something.tfm&amp;quot;)&lt;br /&gt;
myStorageNode.WriteData(myNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Center the 3D View on the Scene ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Rotate the 3D View==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
threeDWidget = layoutManager.threeDWidget(0)&lt;br /&gt;
threeDView = threeDWidget.threeDView()&lt;br /&gt;
threeDView.yaw()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Display text in a 3D view or slice view ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to show information overlaid on a viewer is to use corner annotations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
view=slicer.app.layoutManager().threeDWidget(0).threeDView()&lt;br /&gt;
# Set text to &amp;quot;Something&amp;quot;&lt;br /&gt;
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,&amp;quot;Something&amp;quot;)&lt;br /&gt;
# Set color to red&lt;br /&gt;
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)&lt;br /&gt;
# Update the view&lt;br /&gt;
view.forceRender()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hide slice view annotations (DataProbe) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Disable slice annotations immediately&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.sliceViewAnnotationsEnabled=False&lt;br /&gt;
slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations.updateSliceViewFromGUI()&lt;br /&gt;
# Disable slice annotations persistently (after Slicer restarts)&lt;br /&gt;
settings = qt.QSettings()&lt;br /&gt;
settings.setValue('DataProbe/sliceViewAnnotations.enabled', 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Turning off interpolation ==&lt;br /&gt;
&lt;br /&gt;
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def NoInterpolate(caller,event):&lt;br /&gt;
  for node in slicer.util.getNodes('*').values():&lt;br /&gt;
    if node.IsA('vtkMRMLScalarVolumeDisplayNode'):&lt;br /&gt;
      node.SetInterpolate(0)&lt;br /&gt;
	&lt;br /&gt;
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The below link explains how to put this in your startup script.&lt;br /&gt;
&lt;br /&gt;
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Customize viewer layout ==&lt;br /&gt;
&lt;br /&gt;
Show a custom layout of a 3D view on top of the red slice view:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customLayout = (&amp;quot;&amp;lt;layout type=\&amp;quot;vertical\&amp;quot; split=\&amp;quot;true\&amp;quot; &amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;view class=\&amp;quot;vtkMRMLViewNode\&amp;quot; singletontag=\&amp;quot;1\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;    &amp;lt;property name=\&amp;quot;viewlabel\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;1&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;/view&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;/item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;view class=\&amp;quot;vtkMRMLSliceNode\&amp;quot; singletontag=\&amp;quot;Red\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;   &amp;lt;property name=\&amp;quot;orientation\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;Axial&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;   &amp;lt;property name=\&amp;quot;viewlabel\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;R&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;   &amp;lt;property name=\&amp;quot;viewcolor\&amp;quot; action=\&amp;quot;default\&amp;quot;&amp;gt;#F34A33&amp;lt;/property&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;  &amp;lt;/view&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot; &amp;lt;/item&amp;gt;&amp;quot;&lt;br /&gt;
  &amp;quot;&amp;lt;/layout&amp;gt;&amp;quot;)&lt;br /&gt;
  &lt;br /&gt;
customLayoutId=501&lt;br /&gt;
&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout)                                         &lt;br /&gt;
layoutManager.setLayout(customLayoutId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See description of standard layouts (that can be used as examples) here:&lt;br /&gt;
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx&lt;br /&gt;
&lt;br /&gt;
== Customize keyboard shortcuts ==&lt;br /&gt;
&lt;br /&gt;
Keyboard shortcuts can be specified for activating any Slicer feature by adding a couple of lines to your &lt;br /&gt;
[[Documentation/{{documentation/version}}/Developers/Python_scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F|.slicerrc file]].&lt;br /&gt;
&lt;br /&gt;
For example, this script registers ''Ctrl+b'', ''Ctrl+n'', ''Ctrl+m'', ''Ctrl+,'' keyboard shortcuts to switch between red, yellow, green, and 4-up view layouts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shortcuts = [&lt;br /&gt;
    ('Ctrl+b', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)),&lt;br /&gt;
    ('Ctrl+n', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpYellowSliceView)),&lt;br /&gt;
    ('Ctrl+m', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpGreenSliceView)),&lt;br /&gt;
    ('Ctrl+,', lambda: slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView))&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
for (shortcutKey, callback) in shortcuts:&lt;br /&gt;
    shortcut = qt.QShortcut(slicer.util.mainWindow())&lt;br /&gt;
    shortcut.setKey(qt.QKeySequence(shortcutKey))&lt;br /&gt;
    shortcut.connect( 'activated()', callback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Disable certain user interactions in slice views ==&lt;br /&gt;
&lt;br /&gt;
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()&lt;br /&gt;
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all slice view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  lm.sliceWidget(sliceViewName).sliceController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hide all 3D view controllers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):&lt;br /&gt;
  lm.threeDWidget(0).threeDController().setVisible(False)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change default slice view orientation ==&lt;br /&gt;
&lt;br /&gt;
You can left-right &amp;quot;flip&amp;quot; slice view orientation presets (show patient left side on left/right side of the screen) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Axial slice axes:&lt;br /&gt;
#  1 0 0&lt;br /&gt;
#  0 1 0&lt;br /&gt;
#  0 0 1&lt;br /&gt;
axialSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
&lt;br /&gt;
# Coronal slice axes:&lt;br /&gt;
#  1 0 0 &lt;br /&gt;
#  0 0 -1&lt;br /&gt;
#  0 1 0&lt;br /&gt;
coronalSliceToRas=vtk.vtkMatrix3x3()&lt;br /&gt;
coronalSliceToRas.SetElement(1,1, 0)&lt;br /&gt;
coronalSliceToRas.SetElement(1,2, -1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,1, 1)&lt;br /&gt;
coronalSliceToRas.SetElement(2,2, 0)&lt;br /&gt;
&lt;br /&gt;
# Replace orientation presets in all existing slice nodes and in the default slice node&lt;br /&gt;
sliceNodes = slicer.util.getNodesByClass('vtkMRMLSliceNode')&lt;br /&gt;
sliceNodes.append(slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceNode'))&lt;br /&gt;
for sliceNode in sliceNodes:&lt;br /&gt;
  orientationPresetName = sliceNode.GetOrientation()&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Axial&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Axial&amp;quot;, axialSliceToRas)&lt;br /&gt;
  sliceNode.RemoveSliceOrientationPreset(&amp;quot;Coronal&amp;quot;)&lt;br /&gt;
  sliceNode.AddSliceOrientationPreset(&amp;quot;Coronal&amp;quot;, coronalSliceToRas)&lt;br /&gt;
  sliceNode.SetOrientation(orientationPresetName)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Set all slice views linked by default ==&lt;br /&gt;
&lt;br /&gt;
You can make slice views linked by default (when application starts or the scene is cleared) by copy-pasting the script below to your [[Documentation/{{documentation/version}}/Developers/FAQ/Python_Scripting#How_to_systematically_execute_custom_python_code_at_startup_.3F| .slicerrc.py file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set linked slice views  in all existing slice composite nodes and in the default node&lt;br /&gt;
sliceCompositeNodes = slicer.util.getNodesByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
defaultSliceCompositeNode = slicer.mrmlScene.GetDefaultNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
if not defaultSliceCompositeNode:&lt;br /&gt;
  defaultSliceCompositeNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceCompositeNode')&lt;br /&gt;
  slicer.mrmlScene.AddDefaultNode(defaultSliceCompositeNode)&lt;br /&gt;
sliceCompositeNodes.append(defaultSliceCompositeNode)&lt;br /&gt;
for sliceCompositeNode in sliceCompositeNodes:&lt;br /&gt;
  sliceCompositeNode.SetLinkedControl(True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set up custom units in slice view ruler ==&lt;br /&gt;
&lt;br /&gt;
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in lm.sliceViewNames():&lt;br /&gt;
  sliceView = lm.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  displayableManagerCollection = vtk.vtkCollection()&lt;br /&gt;
  sliceView.getDisplayableManagers(displayableManagerCollection)&lt;br /&gt;
  for dmIndex in xrange(displayableManagerCollection.GetNumberOfItems()):&lt;br /&gt;
    displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)&lt;br /&gt;
    if not displayableManager.IsA(&amp;quot;vtkMRMLRulerDisplayableManager&amp;quot;):&lt;br /&gt;
      continue&lt;br /&gt;
    displayableManager.RemoveAllRulerScalePresets()&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.001, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.010, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.100, 5, 2, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   0.500, 5, 1, &amp;quot;nm&amp;quot;, 1000.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   1.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(   5.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  10.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(  50.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 100.0,   5, 2, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset( 500.0,   5, 1, &amp;quot;um&amp;quot;,    1.0)&lt;br /&gt;
    displayableManager.AddRulerScalePreset(1000.0,   5, 2, &amp;quot;mm&amp;quot;,    0.001)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Show a slice view outside the view layout ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceLayoutName = &amp;quot;TestSlice&amp;quot;&lt;br /&gt;
sliceLayoutLabel = &amp;quot;T&amp;quot;&lt;br /&gt;
# ownerNode manages this view instead of the layout manager (it can be any node in the scene)&lt;br /&gt;
viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLScriptedModuleNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create MRML nodes&lt;br /&gt;
sliceNode = slicer.vtkMRMLSliceNode()&lt;br /&gt;
sliceNode.SetName(sliceLayoutName)&lt;br /&gt;
sliceNode.SetLayoutName(sliceLayoutName)&lt;br /&gt;
sliceNode.SetLayoutLabel(sliceLayoutLabel)&lt;br /&gt;
sliceNode.SetLayoutColor(1, 1, 0)&lt;br /&gt;
sliceNode.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())&lt;br /&gt;
sliceNode = slicer.mrmlScene.AddNode(sliceNode)&lt;br /&gt;
sliceCompositeNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLSliceCompositeNode&amp;quot;)&lt;br /&gt;
sliceCompositeNode.SetLayoutName(sliceLayoutName)&lt;br /&gt;
&lt;br /&gt;
# Create widget&lt;br /&gt;
sliceWidget = slicer.qMRMLSliceWidget()&lt;br /&gt;
sliceWidget.sliceViewName = sliceLayoutName&lt;br /&gt;
sliceWidget.sliceViewLabel = sliceLayoutLabel&lt;br /&gt;
c = sliceNode.GetLayoutColor()&lt;br /&gt;
sliceWidget.sliceViewColor = qt.QColor.fromRgbF(c[0],c[1],c[2])&lt;br /&gt;
sliceWidget.setMRMLScene(slicer.mrmlScene)&lt;br /&gt;
sliceWidget.setMRMLSliceNode(sliceNode)&lt;br /&gt;
sliceWidget.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Running an ITK filter in Python using SimpleITK ==&lt;br /&gt;
Open the &amp;quot;Sample Data&amp;quot; module and download &amp;quot;MR Head&amp;quot;, then paste the following snippet in Python interactor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SimpleITK as sitk&lt;br /&gt;
import sitkUtils&lt;br /&gt;
inputImage = sitkUtils.PullFromSlicer('MRHead')&lt;br /&gt;
filter = sitk.SignedMaurerDistanceMapImageFilter()&lt;br /&gt;
outputImage = filter.Execute(inputImage)&lt;br /&gt;
sitkUtils.PushToSlicer(outputImage,'outputImage')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
* See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html&lt;br /&gt;
* 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&lt;br /&gt;
&lt;br /&gt;
== Get current mouse coordinates in a slice view ==&lt;br /&gt;
&lt;br /&gt;
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def onMouseMoved(observer,eventid):  &lt;br /&gt;
  ras=[0,0,0]&lt;br /&gt;
  crosshairNode.GetCursorPositionRAS(ras)&lt;br /&gt;
  print(ras)&lt;br /&gt;
&lt;br /&gt;
crosshairNode=slicer.util.getNode('Crosshair') &lt;br /&gt;
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get DataProbe text ==&lt;br /&gt;
&lt;br /&gt;
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def printDataProbe():&lt;br /&gt;
  infoWidget = slicer.modules.DataProbeInstance.infoWidget&lt;br /&gt;
  for layer in ('B', 'F', 'L'):&lt;br /&gt;
    print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)&lt;br /&gt;
&lt;br /&gt;
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())&lt;br /&gt;
s.connect('activated()', printDataProbe)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thick slab reconstruction and maximum/minimum intensity volume projections ==&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMean()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set up 'red' slice viewer to show maximum intensity projection (MIP):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')&lt;br /&gt;
appLogic = slicer.app.applicationLogic()&lt;br /&gt;
sliceLogic = appLogic.GetSliceLogic(sliceNode)&lt;br /&gt;
sliceLayerLogic = sliceLogic.GetBackgroundLayer()&lt;br /&gt;
reslice = sliceLayerLogic.GetReslice()&lt;br /&gt;
reslice.SetSlabModeToMax()&lt;br /&gt;
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume&lt;br /&gt;
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)&lt;br /&gt;
sliceNode.Modified()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.&lt;br /&gt;
&lt;br /&gt;
== Change default file type for nodes (that have never been saved yet) ==&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()&lt;br /&gt;
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).&lt;br /&gt;
&lt;br /&gt;
== Change file type for saving for all volumes (with already existing storage nodes) ==&lt;br /&gt;
&lt;br /&gt;
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Delete existing model storage nodes so that they will be recreated with default settings&lt;br /&gt;
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')&lt;br /&gt;
for modelStorageNode in existingModelStorageNodes:&lt;br /&gt;
  slicer.mrmlScene.RemoveNode(modelStorageNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
requiredFileExtension = '.nia'&lt;br /&gt;
originalFileExtension = '.nrrd'&lt;br /&gt;
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')&lt;br /&gt;
for volumeNode in volumeNodes:&lt;br /&gt;
  volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
  if not volumeStorageNode:&lt;br /&gt;
    volumeNode.AddDefaultStorageNode()&lt;br /&gt;
    volumeStorageNode = volumeNode.GetStorageNode()&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)&lt;br /&gt;
  else:&lt;br /&gt;
    volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set all volume nodes to save uncompressed by default (add this to .slicerrc.py so it takes effect for the whole session):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Volume nodes will be stored uncompressed by default&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same thing as above, but applied to all  segmentations instead of volumes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set the default volume storage to not compress by default&lt;br /&gt;
defaultVolumeStorageNode = slicer.vtkMRMLSegmentationStorageNode()&lt;br /&gt;
defaultVolumeStorageNode.SetUseCompression(0)&lt;br /&gt;
slicer.mrmlScene.AddDefaultNode(defaultVolumeStorageNode)&lt;br /&gt;
logging.info(&amp;quot;Segmentation nodes will be stored uncompressed &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Segmentations ==&lt;br /&gt;
&lt;br /&gt;
=== Create a segmentation from a labelmap volume and display in 3D ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
labelmapVolumeNode = getNode('label')&lt;br /&gt;
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)&lt;br /&gt;
seg.CreateClosedSurfaceRepresentation()&lt;br /&gt;
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.&lt;br /&gt;
&lt;br /&gt;
=== Export labelmap node from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Export model nodes from segmentation node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
seg = getNode('Segmentation')&lt;br /&gt;
exportedModelsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelHierarchyNode')&lt;br /&gt;
slicer.modules.segmentations.logic().ExportAllSegmentsToModelHierarchy(seg, exportedModelsNode)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show a segmentation in 3D ===&lt;br /&gt;
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentation.CreateClosedSurfaceRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get a representation of a segment ===&lt;br /&gt;
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
image = segmentationNode.GetBinaryLabelmapRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get closed surface, if it does not exist, it will return None:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Same as above, for closed surface representation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
outputPolyData = vtk.vtkPolyData()&lt;br /&gt;
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using default path and conversion parameters ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode.CreateBinaryLabelmapRepresentation()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Convert all segments using custom path or conversion parameters ===&lt;br /&gt;
Change reference image geometry parameter based on an existing referenceImageData image:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)&lt;br /&gt;
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-convert using a modified conversion parameter ===&lt;br /&gt;
Changing smoothing factor for closed surface generation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import vtkSegmentationCorePython as vtkSegmentationCore&lt;br /&gt;
segmentation = getNode('Segmentation').GetSegmentation()&lt;br /&gt;
&lt;br /&gt;
# Turn of surface smoothing&lt;br /&gt;
segmentation.SetConversionParameter('Smoothing factor','0.0')&lt;br /&gt;
&lt;br /&gt;
# Recreate representation using modified parameters (and default conversion path)&lt;br /&gt;
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get centroid of a segment in world (RAS) coordinates ===&lt;br /&gt;
&lt;br /&gt;
This example shows how to get centroid of a segment in world coordinates and show that position in all slice views.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
segmentationNode = getNode('Segmentation')&lt;br /&gt;
segmentId = 'Segment_1'&lt;br /&gt;
&lt;br /&gt;
# Get array voxel coordinates&lt;br /&gt;
import numpy as np&lt;br /&gt;
seg=arrayFromSegment(segmentation_node, segmentId)&lt;br /&gt;
# numpy array has voxel coordinates in reverse order (KJI instead of IJK)&lt;br /&gt;
# and the array is cropped to minimum size in the segmentation&lt;br /&gt;
mean_KjiCropped = [coords.mean() for coords in np.nonzero(seg)]&lt;br /&gt;
&lt;br /&gt;
# Get segmentation voxel coordinates&lt;br /&gt;
segImage = segmentationNode.GetBinaryLabelmapRepresentation(segmentId)&lt;br /&gt;
segImageExtent = segImage.GetExtent()&lt;br /&gt;
# origin of the array in voxel coordinates is determined by the start extent&lt;br /&gt;
mean_Ijk = [mean_KjiCropped[2], mean_KjiCropped[1], mean_KjiCropped[0]] + np.array([segImageExtent[0], segImageExtent[2], segImageExtent[4]])&lt;br /&gt;
&lt;br /&gt;
# Get segmentation physical coordinates&lt;br /&gt;
ijkToWorld = vtk.vtkMatrix4x4()&lt;br /&gt;
segImage.GetImageToWorldMatrix(ijkToWorld)&lt;br /&gt;
mean_World = [0, 0, 0, 1]&lt;br /&gt;
ijkToRas.MultiplyPoint(np.append(mean_Ijk,1.0), mean_World)&lt;br /&gt;
mean_World = mean_World[0:3]&lt;br /&gt;
&lt;br /&gt;
# If segmentation node is transformed, apply that transform to get RAS coordinates&lt;br /&gt;
transformWorldToRas = vtk.vtkGeneralTransform()&lt;br /&gt;
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(segmentationNode.GetParentTransformNode(), None, transformWorldToRas)&lt;br /&gt;
mean_Ras = transformWorldToRas.TransformPoint(mean_World)&lt;br /&gt;
&lt;br /&gt;
# Show mean position value and jump to it in all slice viewers&lt;br /&gt;
print(mean_Ras)&lt;br /&gt;
slicer.modules.markups.logic().JumpSlicesToLocation(mean_Ras[0], mean_Ras[1], mean_Ras[2], True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How to run segment editor effects from a script ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
* [https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]&lt;br /&gt;
* [https://gist.github.com/lassoan/2f5071c562108dac8efe277c78f2620f mask a volume with segments and compute histogram for each region]&lt;br /&gt;
&lt;br /&gt;
This example shows how to perform operations on segmentations using VTK filters:&lt;br /&gt;
* [https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]&lt;br /&gt;
&lt;br /&gt;
== Accessing views, renderers, and cameras ==&lt;br /&gt;
&lt;br /&gt;
Iterate through all 3D views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for threeDViewIndex in range(layoutManager.threeDViewCount) :&lt;br /&gt;
  view = layoutManager.threeDWidget(threeDViewIndex).threeDView()&lt;br /&gt;
  threeDViewNode = view.mrmlViewNode()&lt;br /&gt;
  cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)&lt;br /&gt;
  print('View node for 3D widget ' + str(threeDViewIndex))&lt;br /&gt;
  print('  Name: ' + threeDViewNode .GetName())&lt;br /&gt;
  print('  ID: ' + threeDViewNode .GetID())&lt;br /&gt;
  print('  Camera ID: ' + cameraNode.GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iterate through all slice views in current layout:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
layoutManager = slicer.app.layoutManager()&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
  view = layoutManager.sliceWidget(sliceViewName).sliceView()&lt;br /&gt;
  sliceNode = view.mrmlSliceNode()&lt;br /&gt;
  sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)&lt;br /&gt;
  compositeNode = sliceLogic.GetSliceCompositeNode()&lt;br /&gt;
  print('Slice view ' + str(sliceViewName))&lt;br /&gt;
  print('  Name: ' + sliceNode.GetName())&lt;br /&gt;
  print('  ID: ' + sliceNode.GetID())&lt;br /&gt;
  print('  Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))&lt;br /&gt;
  print('  Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))&lt;br /&gt;
  print('  Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = view.renderWindow()&lt;br /&gt;
renderers = renderWindow.GetRenderers()&lt;br /&gt;
renderer = renderers.GetItemAsObject(0)&lt;br /&gt;
camera = cameraNode.GetCamera()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Change 3D view background color ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()&lt;br /&gt;
renderer = renderWindow.GetRenderers().GetFirstRenderer()&lt;br /&gt;
renderer.SetBackground(1,0,0)&lt;br /&gt;
renderer.SetBackground2(1,0,0)&lt;br /&gt;
renderWindow.Render()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subject hierarchy == &lt;br /&gt;
==== Get the pseudo-singleton subject hierarchy node ====&lt;br /&gt;
It manages the whole hierarchy and provides functions to access and manipulate&lt;br /&gt;
  shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
&lt;br /&gt;
==== Create subject hierarchy item ====&lt;br /&gt;
  # If it is for a data node, it is automatically created, but the create function can be used to set parent:&lt;br /&gt;
  shNode.CreateItem(parentItemID, dataNode)&lt;br /&gt;
  # If it is a hierarchy item without a data node, then the create function must be used:&lt;br /&gt;
  shNode.CreateSubjectItem(parentItemID, name)&lt;br /&gt;
  shNode.CreateFolderItem(parentItemID, name)&lt;br /&gt;
  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)&lt;br /&gt;
&lt;br /&gt;
==== Get subject hierarchy item ====&lt;br /&gt;
Items in subject hierarchy are uniquely identified by integer IDs&lt;br /&gt;
  # Get scene item ID first because it is the root item:&lt;br /&gt;
  sceneItemID = shNode.GetSceneItemID()&lt;br /&gt;
  # Get direct child by name&lt;br /&gt;
  subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')&lt;br /&gt;
  # Get item for data node&lt;br /&gt;
  itemID = shNode.GetItemByDataNode(dataNode)&lt;br /&gt;
  # Get item by UID (such as DICOM)&lt;br /&gt;
  itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)&lt;br /&gt;
  itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)&lt;br /&gt;
  # Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)&lt;br /&gt;
  invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()&lt;br /&gt;
&lt;br /&gt;
==== Traverse children of a subject hierarchy item ====&lt;br /&gt;
  children = vtk.vtkIdList()&lt;br /&gt;
  shNode.GetItemChildren(parent, children)&lt;br /&gt;
  for i in xrange(children.GetNumberOfIds()):&lt;br /&gt;
    child = children.GetId(i)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
==== Manipulate subject hierarchy item ====&lt;br /&gt;
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.&lt;br /&gt;
  # Set item name&lt;br /&gt;
  shNode.SetItemName(itemID, 'NewName')&lt;br /&gt;
  # Set item parent (reparent)&lt;br /&gt;
  shNode.SetItemParent(itemID, newParentItemID)&lt;br /&gt;
  # Set visibility of data nodes associated to items in a branch (or a leaf item)&lt;br /&gt;
  shNode.SetDisplayVisibilityForBranch(itemID, 1)&lt;br /&gt;
&lt;br /&gt;
==== Filter items in TreeView or ComboBox ====&lt;br /&gt;
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the  [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 3&lt;br /&gt;
    shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 1&lt;br /&gt;
    shTreeView.removeAttributeFilter()&lt;br /&gt;
    print(shTreeView.displayedItemCount()) # 5&lt;br /&gt;
&lt;br /&gt;
=== Listen to subject hierarchy item events ===&lt;br /&gt;
The subject hierarchy node sends the node item id as calldata. Item IDs are vtkIdType, which are NOT vtkObjects. You need to use vtk.calldata_type(vtk.VTK_LONG) (otherwise the application crashes).&lt;br /&gt;
  &lt;br /&gt;
  class MyListenerClass(VTKObservationMixin):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
      VTKObservationMixin.__init__(self)&lt;br /&gt;
      &lt;br /&gt;
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)&lt;br /&gt;
      self.addObserver(shNode, shNode.SubjectHierarchyItemModifiedEvent, self.shItemModifiedEvent)&lt;br /&gt;
     &lt;br /&gt;
    @vtk.calldata_type(vtk.VTK_LONG) &lt;br /&gt;
    def shItemModifiedEvent(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;SH Node modified&amp;quot;)&lt;br /&gt;
      print(&amp;quot;SH item ID: {0}&amp;quot;.format(callData))&lt;br /&gt;
&lt;br /&gt;
== Plotting ==&lt;br /&gt;
&lt;br /&gt;
=== Create histogram plot of a volume ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get a volume from SampleData&lt;br /&gt;
import SampleData&lt;br /&gt;
volumeNode = SampleData.SampleDataLogic().downloadMRHead()&lt;br /&gt;
&lt;br /&gt;
# Compute histogram values&lt;br /&gt;
import numpy as np&lt;br /&gt;
histogram = np.histogram(arrayFromVolume(volumeNode), bins=50)&lt;br /&gt;
&lt;br /&gt;
# Save results to a new table node&lt;br /&gt;
tableNode=slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLTableNode&amp;quot;)&lt;br /&gt;
updateTableFromArray(tableNode, histogram)&lt;br /&gt;
tableNode.GetTable().GetColumn(0).SetName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
tableNode.GetTable().GetColumn(1).SetName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Create plot&lt;br /&gt;
plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotSeriesNode&amp;quot;, volumeNode.GetName() + ' histogram')&lt;br /&gt;
plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())&lt;br /&gt;
plotSeriesNode.SetXColumnName(&amp;quot;Intensity&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetYColumnName(&amp;quot;Count&amp;quot;)&lt;br /&gt;
plotSeriesNode.SetPlotType(plotSeriesNode.PlotTypeScatterBar)&lt;br /&gt;
plotSeriesNode.SetColor(0, 0.6, 1.0)&lt;br /&gt;
&lt;br /&gt;
# Create chart and add plot&lt;br /&gt;
plotChartNode = slicer.mrmlScene.AddNewNodeByClass(&amp;quot;vtkMRMLPlotChartNode&amp;quot;)&lt;br /&gt;
plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())&lt;br /&gt;
plotChartNode.YAxisRangeAutoOff()&lt;br /&gt;
plotChartNode.SetYAxisRange(0, 500000)&lt;br /&gt;
&lt;br /&gt;
# Show plot in layout&lt;br /&gt;
slicer.modules.plots.logic().ShowChartInLayout(plotChartNode)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Execute external applications ==&lt;br /&gt;
&lt;br /&gt;
How to run external applications from Slicer.&lt;br /&gt;
&lt;br /&gt;
=== Run process in default environment ===&lt;br /&gt;
&lt;br /&gt;
When a process is launched from Slicer then by default Slicer's ITK, VTK, Qt, etc. libraries are used. If an external application has its own version of these libraries, then the application is expected to crash. To prevent crashing, the application must be run in the environment where Slicer started up (without all Slicer-specific library paths). This startup environment can be retrieved using ''slicer.util.startupEnvironment()''.&lt;br /&gt;
&lt;br /&gt;
Example: run Python3 script from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_to_execute = [&amp;quot;/usr/bin/python3&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
check_output(&lt;br /&gt;
  command_to_execute, &lt;br /&gt;
  env=slicer.util.startupEnvironment()&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'hola\n'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On some systems, ''shell=True'' must be specified as well.&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DoseComparison&amp;diff=60587</id>
		<title>Documentation/Nightly/Modules/DoseComparison</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DoseComparison&amp;diff=60587"/>
		<updated>2018-11-28T15:06:25Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add validation paper reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
This work is part of the SparKit project, funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health and Long-Term Care and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&amp;lt;br&amp;gt;&lt;br /&gt;
Author: Csaba Pinter (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contributor: Greg Sharp (Massachusetts General Hospital)&amp;lt;br&amp;gt;&lt;br /&gt;
Contact: Csaba Pinter, &amp;lt;email&amp;gt;pinter@cs.queensu.ca&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT Back to SlicerRT home]&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
|{{collaborator|logo|sparkit}}|{{collaborator|longname|sparkit}}&lt;br /&gt;
|{{collaborator|logo|ocairo}}|{{collaborator|longname|ocairo}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
The {{documentation/modulename}} module computes the difference between two co-registered dose volumes using the gamma dose distribution comparison method. This module uses the gamma Plastimatch algorithm internally.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
Comparing dose distributions&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20160121_DoseComparisonUI.png|thumb|499px|Dose Comparison module UI]]&lt;br /&gt;
|[[File:SlicerRT_0.11_Gamma.png|thumb|720px|Example of the result gamma volume]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
See [http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT#Tutorials SlicerRT main page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
* '''Reference dose volume:''' Dose distribution used as reference&lt;br /&gt;
* '''Evaluated dose volume:''' Dose distribution used as evaluation/compare&lt;br /&gt;
* '''Mask structure:''' Segmentation and contained segment within which the gamma index is calculated, but not outside (it will be 0)&lt;br /&gt;
* '''Distance-to-agreement (DTA):''' Mark dose voxel as failed if closest dose voxel with same value found in distance higher than this threshold, ''see Low paper below''&lt;br /&gt;
* '''Dose difference criteria:''' Mark dose voxel as failed if dose difference is equal or greater than this threshold, ''see Low paper below''&lt;br /&gt;
** '''Maximum value / Custom:''' Reference dose value for threshold can be either the maximum dose in the dose map, or a custom cGy value&lt;br /&gt;
* '''Do not calculate gamma values for voxels below analysis threshold'''&lt;br /&gt;
* '''Use linear interpolation'''&lt;br /&gt;
* '''Upper bound for gamma values:''' If gamma value would be higher than this value, the value will be set instead&lt;br /&gt;
* Dose threshold on reference only&lt;br /&gt;
* '''Gamma volume:''' Output volume to contain gamma map. Needs to be created using the combobox. Name will be automatically filled from the names of the input volumes&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{documentation/{{documentation/version}}/module-parametersdescription}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
[http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Modules/SegmentComparison Segment Comparison]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
* General information about the algorithm&lt;br /&gt;
** Low, D. A.; Harms, W. B.; Mutic, S. &amp;amp; Purdy, J. A. A technique for the quantitative evaluation of dose distributions Med. Phys, 1998, 25 (5), 656/6&lt;br /&gt;
** Low, D. A. &amp;amp; Dempsey, J. F. Evaluation of the gamma dose distribution comparison method Med. Phys, 2003, 30 (9), 2455/10&lt;br /&gt;
* Cross-validation of the SlicerRT gamma calculation algorithm&lt;br /&gt;
** [http://perk.cs.queensu.ca/sites/perkd7.cs.queensu.ca/files/Alexander2015_AAPM_Gamma.pdf Alexander, K. M., Jechel, C., Pinter, C., Salomons, G., Lasso, A., Fichtinger, G., &amp;amp; Schreiner, L. J. (2015). SU‐E‐T‐231: Cross‐Validation of 3D Gamma Comparison Tools. Medical physics, 42(6Part15), 3385-3385.]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
N/A&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DoseVolumeHistogram&amp;diff=60486</id>
		<title>Documentation/Nightly/Modules/DoseVolumeHistogram</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DoseVolumeHistogram&amp;diff=60486"/>
		<updated>2018-10-25T16:37:51Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
This work is part of the SparKit project, funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health and Long-Term Care and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&amp;lt;br&amp;gt;&lt;br /&gt;
Author: Csaba Pinter (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contact: Csaba Pinter, &amp;lt;email&amp;gt;pinter@cs.queensu.ca&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT Back to SlicerRT home]&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
|{{collaborator|logo|sparkit}}|{{collaborator|longname|sparkit}}&lt;br /&gt;
|{{collaborator|logo|ocairo}}|{{collaborator|longname|ocairo}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
The {{documentation/modulename}} module enables the user to compute and display the DVH curve from a dose volume and structure (set). DVH metrics, such as volume, minimum, maximum and mean dose, Vdose (the volume that is radiated by a dose greater than a specified dose), and Dvolume (the minimum dose in the most exposed portion of a certain volume in a structure) can be also computed.&lt;br /&gt;
&lt;br /&gt;
The dimensions of the 3D elements (voxels) describing delineated structures are derived from the selected dose distribution volume, in which the voxels have width in the transverse imaging plane as described in the DICOM image header. The image set volume is defined by a grid of voxels derived from the voxel grid in the dose volume. The dose grid is oversampled by a factor currently fixed to the value 2. The centre of each voxel is examined and if found to lie within a structure, is included in the volume for that structure. The dose value at the centre of the cube is interpolated in 3D from the dose grid.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
Evaluate single or accumulated dose distributions against target structures and organs at risk (OARs)&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20181025_DVH_Screenshot_ModulePanel.png|thumb|572px|Dose Volume Histogram module UI]]&lt;br /&gt;
|[[File:20181025_DVH_Screenshot_Viewers.png|thumb|853px| Dose volume histogram views using SlicerRT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
See [http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT#Tutorials SlicerRT main page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
* '''Input'''&lt;br /&gt;
** '''Dose volume:''' The dose distribution using which the DVH is computed and the structure labelmap is created if necessary. All the volumes present in the Slicer scene appear here, however, when selecting a volume that has not been created by a SlicerRT module (such as DicomRtImport or DoseAccumulation), a warning will be displayed. If using such a volume, it is assumed not to contain dose values, so an Intensity Volume Histogram is created.&lt;br /&gt;
** '''Structure set:''' A contour or a contour hierarchy can be selected for which the DVH tables are computed. In case of a hierarchy, the DVH is computed for every contained contour.&lt;br /&gt;
** '''Dose surface histogram:''' If checked, then dose surface histogram (DSH) is calculated instead of a DVH. A current limitation is that open contours are not supported, so for example rectum structure bottom and top is considered.&lt;br /&gt;
* '''Output'''&lt;br /&gt;
** '''Show/hide all:''' After computing histograms, this checkbox adds or removes every histogram from the chart&lt;br /&gt;
** '''Switch layout:''' Switch layout to &amp;quot;four-up quantitative interactive&amp;quot; or &amp;quot;one-up quantitative interactive&amp;quot; so that DVH/DSH chart is visible&lt;br /&gt;
** '''DVH table'''&lt;br /&gt;
*** '''Checkbox:''' show/hide that specific structure in the selected chart&lt;br /&gt;
*** Structure data and computed DVH metrics appear in the columns&lt;br /&gt;
* '''Advanced options'''&lt;br /&gt;
** '''V metric for dose values:''' Values can be entered separated by commas. If 'cc' or '%' is checked, then the V metric for all structures according the entered values will appear in the DVH table in the checked unit(s)&lt;br /&gt;
** '''D metric for volumes:''' Values can be entered separated by commas in either ccs or percents. If 'Gy' is checked then the D metric for the entered volumes are displayed in the DVH table&lt;br /&gt;
** '''Export DVH to file:''' The currently plotted DVH tables are saved in CSV format&lt;br /&gt;
** '''Export DVH metrics to file:''' The currently displayed DVH table can be exported in CSV format&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{documentation/{{documentation/version}}/module-parametersdescription}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
* DVH Comparison&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
* Pinter, C.; Lasso, A.; Wang, A.; Jaffray, D. &amp;amp; Fichtinger, G. SlicerRT: Radiation therapy research toolkit for 3D Slicer Med. Phys., 2012, 39(10), 6332/7&lt;br /&gt;
* Ebert, M. A.; Haworth, A.; Kearvell, R.; Hooton, B.; Hug, B.; Spry, N. A.; Bydder, S. A. &amp;amp; Joseph, D. J. Comparison of DVH data from multiple planning systems Phys. Med. Biol., 2010, 55, N337–N346&lt;br /&gt;
* Drzymala, R. E.; R. Mohan, l. B.; Chu, J.; Goitein, M.; Harms, W. &amp;amp; Urie, M. Dose-Volume Histograms Radiation Oncology Biol. Phys., 1991, 21, 71-78&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
{|align=&amp;quot;left&amp;quot;&lt;br /&gt;
|[[File:20181024_DVH_NodesArchitecture.png|thumb|447px|Dose Volume Histogram nodes architecture]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DoseVolumeHistogram&amp;diff=60485</id>
		<title>Documentation/Nightly/Modules/DoseVolumeHistogram</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DoseVolumeHistogram&amp;diff=60485"/>
		<updated>2018-10-25T16:34:44Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Update screenshots&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
This work is part of the SparKit project, funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health and Long-Term Care and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&amp;lt;br&amp;gt;&lt;br /&gt;
Author: Csaba Pinter (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contact: Csaba Pinter, &amp;lt;email&amp;gt;pinter@cs.queensu.ca&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT Back to SlicerRT home]&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
|{{collaborator|logo|sparkit}}|{{collaborator|longname|sparkit}}&lt;br /&gt;
|{{collaborator|logo|ocairo}}|{{collaborator|longname|ocairo}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
The {{documentation/modulename}} module enables the user to compute and display the DVH curve from a dose volume and structure (set). DVH metrics, such as volume, minimum, maximum and mean dose, Vdose (the volume that is radiated by a dose greater than a specified dose), and Dvolume (the minimum dose in the most exposed portion of a certain volume in a structure) can be also computed.&lt;br /&gt;
&lt;br /&gt;
The dimensions of the 3D elements (voxels) describing delineated structures are derived from the selected dose distribution volume, in which the voxels have width in the transverse imaging plane as described in the DICOM image header. The image set volume is defined by a grid of voxels derived from the voxel grid in the dose volume. The dose grid is oversampled by a factor currently fixed to the value 2. The centre of each voxel is examined and if found to lie within a structure, is included in the volume for that structure. The dose value at the centre of the cube is interpolated in 3D from the dose grid.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
Evaluate single or accumulated dose distributions against target structures and organs at risk (OARs)&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:20181025_DVH_Screenshot_ModulePanel.png|thumb|572px|Dose Volume Histogram module UI]]&lt;br /&gt;
|[[File:20181025_DVH_Screenshot_Viewers.png|thumb|853px| Dose volume histogram views using SlicerRT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
See [http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT#Tutorials SlicerRT main page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
* '''Input'''&lt;br /&gt;
** '''Dose volume:''' The dose distribution using which the DVH is computed and the structure labelmap is created if necessary. All the volumes present in the Slicer scene appear here, however, when selecting a volume that has not been created by a SlicerRT module (such as DicomRtImport or DoseAccumulation), a warning will be displayed. If using such a volume, it is assumed not to contain dose values, so an Intensity Volume Histogram is created.&lt;br /&gt;
** '''Structure set:''' A contour or a contour hierarchy can be selected for which the DVH tables are computed. In case of a hierarchy, the DVH is computed for every contained contour.&lt;br /&gt;
* '''Output'''&lt;br /&gt;
** '''Chart:''' A chart can be created or selected in which the DVH plots are added&lt;br /&gt;
** '''Show/hide all:''' After computing histograms and a chart, this checkbox adds or removes every histogram from the selected chart&lt;br /&gt;
** '''DVH table'''&lt;br /&gt;
*** '''Checkbox:''' show/hide that specific structure in the selected chart&lt;br /&gt;
*** Structure data and computed DVH metrics appear in the columns&lt;br /&gt;
* '''Advanced options'''&lt;br /&gt;
** '''V metric for dose values:''' Values can be entered separated by commas. If 'cc' or '%' is checked, then the V metric for all structures according the entered values will appear in the DVH table in the checked unit(s)&lt;br /&gt;
** '''D metric for volumes:''' Values can be entered separated by commas in either ccs or percents. If 'Gy' is checked then the D metric for the entered volumes are displayed in the DVH table&lt;br /&gt;
** '''Export DVH to file:''' The currently plotted DVH tables are saved in CSV format&lt;br /&gt;
** '''Export DVH metrics to file:''' The currently displayed DVH table can be exported in CSV format&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{documentation/{{documentation/version}}/module-parametersdescription}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
N/A&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
* Ebert, M. A.; Haworth, A.; Kearvell, R.; Hooton, B.; Hug, B.; Spry, N. A.; Bydder, S. A. &amp;amp; Joseph, D. J. Comparison of DVH data from multiple planning systems Phys. Med. Biol., 2010, 55, N337–N346&lt;br /&gt;
* Pinter, C.; Lasso, A.; Wang, A.; Jaffray, D. &amp;amp; Fichtinger, G. SlicerRT: Radiation therapy research toolkit for 3D Slicer Med. Phys., 2012, 39(10), 6332/7&lt;br /&gt;
* Drzymala, R. E.; R. Mohan, l. B.; Chu, J.; Goitein, M.; Harms, W. &amp;amp; Urie, M. Dose-Volume Histograms Radiation Oncology Biol. Phys., 1991, 21, 71-78&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
{|align=&amp;quot;left&amp;quot;&lt;br /&gt;
|[[File:20181024_DVH_NodesArchitecture.png|thumb|447px|Dose Volume Histogram nodes architecture]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=File:20181025_DVH_Screenshot_ModulePanel.png&amp;diff=60484</id>
		<title>File:20181025 DVH Screenshot ModulePanel.png</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=File:20181025_DVH_Screenshot_ModulePanel.png&amp;diff=60484"/>
		<updated>2018-10-25T16:20:46Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=File:20181025_DVH_Screenshot_Viewers.png&amp;diff=60483</id>
		<title>File:20181025 DVH Screenshot Viewers.png</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=File:20181025_DVH_Screenshot_Viewers.png&amp;diff=60483"/>
		<updated>2018-10-25T16:20:42Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DoseVolumeHistogram&amp;diff=60475</id>
		<title>Documentation/Nightly/Modules/DoseVolumeHistogram</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/DoseVolumeHistogram&amp;diff=60475"/>
		<updated>2018-10-24T18:41:12Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add DVH nodes architectures diagram&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
This work is part of the SparKit project, funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health and Long-Term Care and the Ontario Consortium for Adaptive Interventions in Radiation Oncology (OCAIRO) to provide free, open-source toolset for radiotherapy and related image-guided interventions.&amp;lt;br&amp;gt;&lt;br /&gt;
Author: Csaba Pinter (PerkLab, Queen's University)&amp;lt;br&amp;gt;&lt;br /&gt;
Contact: Csaba Pinter, &amp;lt;email&amp;gt;pinter@cs.queensu.ca&amp;lt;/email&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT Back to SlicerRT home]&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
|{{collaborator|logo|sparkit}}|{{collaborator|longname|sparkit}}&lt;br /&gt;
|{{collaborator|logo|ocairo}}|{{collaborator|longname|ocairo}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
The {{documentation/modulename}} module enables the user to compute and display the DVH curve from a dose volume and structure (set). DVH metrics, such as volume, minimum, maximum and mean dose, Vdose (the volume that is radiated by a dose greater than a specified dose), and Dvolume (the minimum dose in the most exposed portion of a certain volume in a structure) can be also computed.&lt;br /&gt;
&lt;br /&gt;
The dimensions of the 3D elements (voxels) describing delineated structures are derived from the selected dose distribution volume, in which the voxels have width in the transverse imaging plane as described in the DICOM image header. The image set volume is defined by a grid of voxels derived from the voxel grid in the dose volume. The dose grid is oversampled by a factor currently fixed to the value 2. The centre of each voxel is examined and if found to lie within a structure, is included in the volume for that structure. The dose value at the centre of the cube is interpolated in 3D from the dose grid.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
Evaluate single or accumulated dose distributions against target structures and organs at risk (OARs)&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[File:SlicerRT0.10_DvhModuleUi.png|thumb|447px|Dose Volume Histogram module UI]]&lt;br /&gt;
|[[File:SlicerRT_0.12_DoseVolumeHistogram_Ent_AllStructures.png|thumb|800px| Dose volume histogram views using SlicerRT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
See [http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/SlicerRT#Tutorials SlicerRT main page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
* '''Input'''&lt;br /&gt;
** '''Dose volume:''' The dose distribution using which the DVH is computed and the structure labelmap is created if necessary. All the volumes present in the Slicer scene appear here, however, when selecting a volume that has not been created by a SlicerRT module (such as DicomRtImport or DoseAccumulation), a warning will be displayed. If using such a volume, it is assumed not to contain dose values, so an Intensity Volume Histogram is created.&lt;br /&gt;
** '''Structure set:''' A contour or a contour hierarchy can be selected for which the DVH tables are computed. In case of a hierarchy, the DVH is computed for every contained contour.&lt;br /&gt;
* '''Output'''&lt;br /&gt;
** '''Chart:''' A chart can be created or selected in which the DVH plots are added&lt;br /&gt;
** '''Show/hide all:''' After computing histograms and a chart, this checkbox adds or removes every histogram from the selected chart&lt;br /&gt;
** '''DVH table'''&lt;br /&gt;
*** '''Checkbox:''' show/hide that specific structure in the selected chart&lt;br /&gt;
*** Structure data and computed DVH metrics appear in the columns&lt;br /&gt;
* '''Advanced options'''&lt;br /&gt;
** '''V metric for dose values:''' Values can be entered separated by commas. If 'cc' or '%' is checked, then the V metric for all structures according the entered values will appear in the DVH table in the checked unit(s)&lt;br /&gt;
** '''D metric for volumes:''' Values can be entered separated by commas in either ccs or percents. If 'Gy' is checked then the D metric for the entered volumes are displayed in the DVH table&lt;br /&gt;
** '''Export DVH to file:''' The currently plotted DVH tables are saved in CSV format&lt;br /&gt;
** '''Export DVH metrics to file:''' The currently displayed DVH table can be exported in CSV format&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{documentation/{{documentation/version}}/module-parametersdescription}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
N/A&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
* Ebert, M. A.; Haworth, A.; Kearvell, R.; Hooton, B.; Hug, B.; Spry, N. A.; Bydder, S. A. &amp;amp; Joseph, D. J. Comparison of DVH data from multiple planning systems Phys. Med. Biol., 2010, 55, N337–N346&lt;br /&gt;
* Pinter, C.; Lasso, A.; Wang, A.; Jaffray, D. &amp;amp; Fichtinger, G. SlicerRT: Radiation therapy research toolkit for 3D Slicer Med. Phys., 2012, 39(10), 6332/7&lt;br /&gt;
* Drzymala, R. E.; R. Mohan, l. B.; Chu, J.; Goitein, M.; Harms, W. &amp;amp; Urie, M. Dose-Volume Histograms Radiation Oncology Biol. Phys., 1991, 21, 71-78&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
{|align=&amp;quot;left&amp;quot;&lt;br /&gt;
|[[File:20181024_DVH_NodesArchitecture.png|thumb|447px|Dose Volume Histogram nodes architecture]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=File:20181024_DVH_NodesArchitecture.png&amp;diff=60474</id>
		<title>File:20181024 DVH NodesArchitecture.png</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=File:20181024_DVH_NodesArchitecture.png&amp;diff=60474"/>
		<updated>2018-10-24T18:39:20Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/Data&amp;diff=60473</id>
		<title>Documentation/Nightly/Modules/Data</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/Data&amp;diff=60473"/>
		<updated>2018-10-24T18:21:33Z</updated>

		<summary type="html">&lt;p&gt;Pinter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}} }}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
:'''Title''': Data&lt;br /&gt;
:'''Authors''': Csaba Pinter (Queen's), Julien Finet (Kitware), Alex Yarmarkovich (Isomics), Nicole Aucoin (SPL, BWH)&lt;br /&gt;
{{documentation/{{documentation/version}}/module-acknowledgements}}&lt;br /&gt;
:'''Acknowledgements''': This work is part of the National Alliance for Medical Image Computing (NAMIC), funded by the National Institutes of Health through the NIH Roadmap for Medical Research, Grant U54 EB005149. This work was also funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health, Canada&amp;lt;br&amp;gt;&lt;br /&gt;
: '''End-user advocate:''' Ron Kikinis (SPL, NA-MIC)&lt;br /&gt;
: '''Contact:''' Csaba Pinter, &amp;lt;email&amp;gt;csaba.pinter@queensu.ca&amp;lt;/email&amp;gt;, Julien Finet (Kitware), &amp;lt;email&amp;gt;julien.finet@kitware.com&amp;lt;/email&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|namic}}|{{collaborator|longname|namic}}&lt;br /&gt;
|{{collaborator|logo|kitware}}|{{collaborator|longname|kitware}}&lt;br /&gt;
|{{collaborator|logo|isomics}}|{{collaborator|longname|isomics}}&lt;br /&gt;
|{{collaborator|logo|spl}}|{{collaborator|longname|spl}}&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-description}}&lt;br /&gt;
&lt;br /&gt;
The Data module acts as a central data-organizing point in Slicer. It shows the data loaded into Slicer in various views. The Subject Hierarchy view shows the data in an easy-to-explore way, and offers operations on the data nodes, while Transform Hierarchy supports exploring transformation chains, and the All Nodes view shows all nodes in an unstructured way&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Subject Hierarchy, DICOM data is automatically added as patient-study-series hierarchy. Non-DICOM data can be parsed if loaded from a local directory structure, or can be manually organized in tree structure by creating DICOM-like hierarchy or folders. Model hierarchies are automatically mirrored in subject hierarchy, so an atlas can be explored the usual way.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Subject hierarchy provides features for the underlying data nodes, including cloning, bulk transforming, bulk show/hide, type-specific features, and basic node operations such as delete or rename. Additional plugins provide other type-specific features and general operations, see [[Documentation/Labs/SubjectHierarchy|Subject hierarchy labs page]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
* Subject hierarchy view&lt;br /&gt;
** Overview all loaded data objects in the same place, types indicated by icons&lt;br /&gt;
** Organize data in folders or patient/subject trees&lt;br /&gt;
** Visualize and bulk-handle lots of data nodes loaded from disk&lt;br /&gt;
** Easy show/hide of branches of displayable data&lt;br /&gt;
** Transform whole study (any branch)&lt;br /&gt;
** Export DICOM data (edit DICOM tags)&lt;br /&gt;
** Lots of type-specific functionality offered by the plugins&lt;br /&gt;
* Transform hierarchy view&lt;br /&gt;
** Manage transformation chains/hierarchies&lt;br /&gt;
* All nodes view&lt;br /&gt;
** Developer tool for debugging problems&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
&lt;br /&gt;
* 2016: [http://www.na-mic.org/Wiki/index.php/Winter2016TutorialContest This tutorial] demonstrates the basic usage and potential of Slicer’s data manager module Subject Hierarchy using a two-timepoint radiotherapy phantom dataset.&lt;br /&gt;
* 2015: Tutorial about [https://www.slicer.org/slicerWiki/index.php/Documentation/4.5/Training loading and viewing data]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
&lt;br /&gt;
; Subject hierarchy&lt;br /&gt;
Contains all the objects in the Subject hierarchy in a tree representation&lt;br /&gt;
* Data loaded from '''DICOM''' are automatically added to the tree in the right structure (patient, study, series)&lt;br /&gt;
* '''Non-DICOM''' data also appears automatically in Subject hierarchy. There two ways are two ways to organize them in hierarchy&lt;br /&gt;
** 'Create hierarchy '''from loaded directory structure'''' action in the context menu of the scene (right-click on empty area, see bottom screenshot). This organizes the nodes according to the local file structure they have been loaded from.&lt;br /&gt;
** Drag&amp;amp;drop manually under a hierarchy node&lt;br /&gt;
** Create model or other (e.g. annotation) hierarchies, and see the same structure in subject hierarchy&lt;br /&gt;
* When an item is selected, the related items are '''highlight'''ed:&lt;br /&gt;
** Green: Items referencing the current item directly via DICOM or node references&lt;br /&gt;
** Yellow: Items referenced by the current item directly via DICOM or node references&lt;br /&gt;
** Light yellow: Items referenced by the current item recursively via node references&lt;br /&gt;
* Nodes can be drag&amp;amp;dropped under other nodes, thus re-arranging the tree&lt;br /&gt;
* Basic operations (accessible in the context menu of the nodes by right-clicking them)&lt;br /&gt;
** '''Transform node or branch''': Double-click the cell of the node or branch to transform in the column named 'Tr', then set the desired transform. If the column is not visible, check the 'Transforms' checkbox under the tree. An example can be seen in the top screenshot at 'Day 2' study&lt;br /&gt;
** '''Show/hide''' node or branch: Click on the eye icon&lt;br /&gt;
** '''Delete''': Delete both data node and SH node&lt;br /&gt;
** '''Rename''': Rename both data node and SH node&lt;br /&gt;
** '''Clone''': Creates a copy of the selected node that will be identical in every manner. Its name will contain a '_Copy' postfix&lt;br /&gt;
** '''Edit properties''': If the role of the node is specified (i.e. its icon is not a question mark), then the corresponding module is opened and the node selected (e.g. Volumes module for volumes)&lt;br /&gt;
** '''Create child...''': Create a node with the specified type&lt;br /&gt;
* There are no nodes in the tree when Slicer is opened, new nodes can be added by right-clicking the empty area (or the scene item if visible)&lt;br /&gt;
* Roles and corresponding functions&lt;br /&gt;
** '''Volumes''': icon, Edit properties and additional information in tooltip&lt;br /&gt;
*** ''''Register this...'''' action to select fixed image for registration. Right-click the moving image to initiate registration&lt;br /&gt;
*** ''''Segment this...'''' action allows segmenting the volume, for example, in the Editor module&lt;br /&gt;
*** ''''Toggle labelmap outline display'''' for labelmaps&lt;br /&gt;
** '''Models''': icon, Edit properties and additional information in tooltip&lt;br /&gt;
** '''SceneViews''': icon, Edit properties and Restore scene view&lt;br /&gt;
** '''Transforms''': icon, additional tooltip info, Edit properties, Invert, Reset to identity&lt;br /&gt;
** Many others, such as Markups, Charts, Annotations, Tables, etc.&lt;br /&gt;
* Subject hierarchy item information&lt;br /&gt;
** Displays detailed information about the selected subject hierarchy item&lt;br /&gt;
&lt;br /&gt;
; Transform hierarchy&lt;br /&gt;
* '''Nodes''': The view lists all transformable nodes of the scene as a hierarchical tree that describes the relationships between nodes. Nodes are graphical objects such as volumes or models that control the displays in the different views (2D, 3D). To rename an item, double click with the left button on any item (but the scene) in the list. A right click pops up a menu containing different actions: &amp;quot;Insert Transform&amp;quot; creates an identity linear transform node and applies it on the selected node. &amp;quot;Edit properties&amp;quot; opens the module of the node (e.g. &amp;quot;Volumes&amp;quot; for volume nodes, &amp;quot;Models&amp;quot; for model nodes, etc.). &amp;quot;Rename&amp;quot; opens a dialog to rename the node. &amp;quot;Delete&amp;quot; removes the node from the scene. Internal drag-and-drops are supported in the view, while moving a node position within the same parent has no effect, changing the parent of a node has a different meaning depending on the current scene model.&lt;br /&gt;
* '''Show MRML ID's''': Show/hide in the tree view a second column containing the node ID of the nodes. Hidden by default&lt;br /&gt;
* '''Show hidden nodes''': Show/hide the hidden nodes. By default, only the main nodes are shown&lt;br /&gt;
&lt;br /&gt;
; All nodes&lt;br /&gt;
* Unstructured view of all nodes in the scene. Supports Edit properties, Rename, Delete&lt;br /&gt;
&lt;br /&gt;
; Common&lt;br /&gt;
* '''Filter''': Hide all the nodes not matching the typed string. This can be useful to quickly search for a specific node. Please note that the search is case sensitive&lt;br /&gt;
* '''MRML node information''': Attribute list of the currently selected node. Attributes can be edited (double click in the &amp;quot;Attribute value&amp;quot; cell), added (with the &amp;quot;Add&amp;quot; button) or removed (with the &amp;quot;Remove&amp;quot; button).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|How to}}&lt;br /&gt;
&lt;br /&gt;
; Create new Subject from scratch&lt;br /&gt;
: Right-click on the empty area and select 'Create new subject'&lt;br /&gt;
&lt;br /&gt;
; Create new folder&lt;br /&gt;
: Right-click on an existing item or the empty area and select 'Create new folder'. Folder type hierarchy item can be converted to Subject or Study using the context menu&lt;br /&gt;
&lt;br /&gt;
; Rename item&lt;br /&gt;
: Right-click on the node and select 'Rename', or double-click the name of a node&lt;br /&gt;
&lt;br /&gt;
; Apply transform on node or branch&lt;br /&gt;
: Double-click the cell of the node or branch to transform in the transform column (same icon as Transforms module), then set the desired transform. If the column is not visible, check the 'Transforms' checkbox under the tree.  An example can be seen in the top screenshot at Patient 2&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
[[File:20170425_SubjectHierarchyInDataNode.png|thumb|409px| Subject hierarchy tree]]&lt;br /&gt;
[[File:SlicerRT_0.13_HuntingtonsLongitudinalInSubjectHierarchy2.png|thumb|622px| Parse local data loaded from directory structures]]&lt;br /&gt;
[[File:20170425_TransformHierarchyInDataNode.png|thumb|410px| Transform hierarchy]]&lt;br /&gt;
[[File:20170425_AllNodesInDataNode.png|thumb|410px| All nodes view]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
N/A&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
* Additional information on [[Documentation/Labs/SubjectHierarchy|Subject hierarchy labs page]]&lt;br /&gt;
* Manual editing of segmentations can be done in the [http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Modules/SegmentEditor Segment Editor module]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
* Code snippets accessing and manipulating subject hierarchy items can be found in the [https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Subject_hierarchy script repository]&lt;br /&gt;
* '''Implementing new plugins''': Plugins are the real power of subject hierarchy, as they provide support for data node types, and add functionality to the context menu items.&amp;lt;br&amp;gt;To create a C++ plugin, implement a child class of qSlicerSubjectHierarchyAbstractPlugin, for Python plugin see below. Many examples can be found in Slicer core and in the SlicerRT extension, look for folders named SubjectHierarchyPlugins.&lt;br /&gt;
** Writing plugins in '''Python''':&lt;br /&gt;
*** Child class of AbstractScriptedSubjectHierarchyPlugin which is a Python adaptor of the C++ qSlicerSubjectHierarchyScriptedPlugin class&lt;br /&gt;
*** Example: [https://github.com/Slicer/Slicer/blob/master/Modules/Loadable/Annotations/SubjectHierarchyPlugins/AnnotationsSubjectHierarchyPlugin.py Annotations] role plugin, [https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/SegmentEditor/SubjectHierarchyPlugins/SegmentEditorSubjectHierarchyPlugin.py function plugin]&lt;br /&gt;
** '''Role''' plugins: add support for new data node types&lt;br /&gt;
*** Defines: ownership, icon, tooltip, edit properties, help text (in the yellow question mark popup), visibility icon, set/get display visibility, displayed node name (if different than name of the node object)&lt;br /&gt;
*** Existing plugins in Slicer core: Markups, Models, SceneViews, Charts, Folder, Tables, Transforms, LabelMaps, Volumes&lt;br /&gt;
** '''Function''' plugins: add feature in right-click context menu for certain types of nodes&lt;br /&gt;
*** Defines: list of contect menu actions for nodes and the scene, types of nodes for which the action shows up, functions handling the defined action&lt;br /&gt;
*** Existing plugins in Slicer core: CloneNode, ParseLocalData, Register, Segment, DICOM, Volumes, Markups, Models, Annotations, Segmentations, Segments, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/Data&amp;diff=60472</id>
		<title>Documentation/Nightly/Modules/Data</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Modules/Data&amp;diff=60472"/>
		<updated>2018-10-24T18:20:54Z</updated>

		<summary type="html">&lt;p&gt;Pinter: Add reference highlighting feature description&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-header}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}} }}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
:'''Title''': Data&lt;br /&gt;
:'''Authors''': Csaba Pinter (Queen's), Julien Finet (Kitware), Alex Yarmarkovich (Isomics), Nicole Aucoin (SPL, BWH)&lt;br /&gt;
{{documentation/{{documentation/version}}/module-acknowledgements}}&lt;br /&gt;
:'''Acknowledgements''': This work is part of the National Alliance for Medical Image Computing (NAMIC), funded by the National Institutes of Health through the NIH Roadmap for Medical Research, Grant U54 EB005149. This work was also funded by An Applied Cancer Research Unit of Cancer Care Ontario with funds provided by the Ministry of Health, Canada&amp;lt;br&amp;gt;&lt;br /&gt;
: '''End-user advocate:''' Ron Kikinis (SPL, NA-MIC)&lt;br /&gt;
: '''Contact:''' Csaba Pinter, &amp;lt;email&amp;gt;csaba.pinter@queensu.ca&amp;lt;/email&amp;gt;, Julien Finet (Kitware), &amp;lt;email&amp;gt;julien.finet@kitware.com&amp;lt;/email&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-row}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-logo-gallery&lt;br /&gt;
|{{collaborator|logo|namic}}|{{collaborator|longname|namic}}&lt;br /&gt;
|{{collaborator|logo|kitware}}|{{collaborator|longname|kitware}}&lt;br /&gt;
|{{collaborator|logo|isomics}}|{{collaborator|longname|isomics}}&lt;br /&gt;
|{{collaborator|logo|spl}}|{{collaborator|longname|spl}}&lt;br /&gt;
|{{collaborator|logo|cco}}|{{collaborator|longname|cco}}&lt;br /&gt;
}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-introduction-end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Module Description}}&lt;br /&gt;
{{documentation/{{documentation/version}}/module-description}}&lt;br /&gt;
&lt;br /&gt;
The Data module acts as a central data-organizing point in Slicer. It shows the data loaded into Slicer in various views. The Subject Hierarchy view shows the data in an easy-to-explore way, and offers operations on the data nodes, while Transform Hierarchy supports exploring transformation chains, and the All Nodes view shows all nodes in an unstructured way&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Subject Hierarchy, DICOM data is automatically added as patient-study-series hierarchy. Non-DICOM data can be parsed if loaded from a local directory structure, or can be manually organized in tree structure by creating DICOM-like hierarchy or folders. Model hierarchies are automatically mirrored in subject hierarchy, so an atlas can be explored the usual way.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Subject hierarchy provides features for the underlying data nodes, including cloning, bulk transforming, bulk show/hide, type-specific features, and basic node operations such as delete or rename. Additional plugins provide other type-specific features and general operations, see [[Documentation/Labs/SubjectHierarchy|Subject hierarchy labs page]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Use Cases}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
* Subject hierarchy view&lt;br /&gt;
** Overview all loaded data objects in the same place, types indicated by icons&lt;br /&gt;
** Organize data in folders or patient/subject trees&lt;br /&gt;
** Visualize and bulk-handle lots of data nodes loaded from disk&lt;br /&gt;
** Easy show/hide of branches of displayable data&lt;br /&gt;
** Transform whole study (any branch)&lt;br /&gt;
** Export DICOM data (edit DICOM tags)&lt;br /&gt;
** Lots of type-specific functionality offered by the plugins&lt;br /&gt;
* Transform hierarchy view&lt;br /&gt;
** Manage transformation chains/hierarchies&lt;br /&gt;
* All nodes view&lt;br /&gt;
** Developer tool for debugging problems&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Tutorials}}&lt;br /&gt;
&lt;br /&gt;
* 2016: [http://www.na-mic.org/Wiki/index.php/Winter2016TutorialContest This tutorial] demonstrates the basic usage and potential of Slicer’s data manager module Subject Hierarchy using a two-timepoint radiotherapy phantom dataset.&lt;br /&gt;
* 2015: Tutorial about [https://www.slicer.org/slicerWiki/index.php/Documentation/4.5/Training loading and viewing data]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Panels and their use}}&lt;br /&gt;
&lt;br /&gt;
; Subject hierarchy&lt;br /&gt;
Contains all the objects in the Subject hierarchy in a tree representation&lt;br /&gt;
* Data loaded from '''DICOM''' are automatically added to the tree in the right structure (patient, study, series)&lt;br /&gt;
* '''Non-DICOM''' data also appears automatically in Subject hierarchy. There two ways are two ways to organize them in hierarchy&lt;br /&gt;
** 'Create hierarchy '''from loaded directory structure'''' action in the context menu of the scene (right-click on empty area, see bottom screenshot). This organizes the nodes according to the local file structure they have been loaded from.&lt;br /&gt;
** Drag&amp;amp;drop manually under a hierarchy node&lt;br /&gt;
** Create model or other (e.g. annotation) hierarchies, and see the same structure in subject hierarchy&lt;br /&gt;
* When an item is selected, the related items are highlighted:&lt;br /&gt;
** Green: Items referencing the current item directly via DICOM or node references&lt;br /&gt;
** Yellow: Items referenced by the current item directly via DICOM or node references&lt;br /&gt;
** Light yellow: Items referenced by the current item recursively via node references&lt;br /&gt;
* Nodes can be drag&amp;amp;dropped under other nodes, thus re-arranging the tree&lt;br /&gt;
* Basic operations (accessible in the context menu of the nodes by right-clicking them)&lt;br /&gt;
** '''Transform node or branch''': Double-click the cell of the node or branch to transform in the column named 'Tr', then set the desired transform. If the column is not visible, check the 'Transforms' checkbox under the tree. An example can be seen in the top screenshot at 'Day 2' study&lt;br /&gt;
** '''Show/hide''' node or branch: Click on the eye icon&lt;br /&gt;
** '''Delete''': Delete both data node and SH node&lt;br /&gt;
** '''Rename''': Rename both data node and SH node&lt;br /&gt;
** '''Clone''': Creates a copy of the selected node that will be identical in every manner. Its name will contain a '_Copy' postfix&lt;br /&gt;
** '''Edit properties''': If the role of the node is specified (i.e. its icon is not a question mark), then the corresponding module is opened and the node selected (e.g. Volumes module for volumes)&lt;br /&gt;
** '''Create child...''': Create a node with the specified type&lt;br /&gt;
* There are no nodes in the tree when Slicer is opened, new nodes can be added by right-clicking the empty area (or the scene item if visible)&lt;br /&gt;
* Roles and corresponding functions&lt;br /&gt;
** '''Volumes''': icon, Edit properties and additional information in tooltip&lt;br /&gt;
*** ''''Register this...'''' action to select fixed image for registration. Right-click the moving image to initiate registration&lt;br /&gt;
*** ''''Segment this...'''' action allows segmenting the volume, for example, in the Editor module&lt;br /&gt;
*** ''''Toggle labelmap outline display'''' for labelmaps&lt;br /&gt;
** '''Models''': icon, Edit properties and additional information in tooltip&lt;br /&gt;
** '''SceneViews''': icon, Edit properties and Restore scene view&lt;br /&gt;
** '''Transforms''': icon, additional tooltip info, Edit properties, Invert, Reset to identity&lt;br /&gt;
** Many others, such as Markups, Charts, Annotations, Tables, etc.&lt;br /&gt;
* Subject hierarchy item information&lt;br /&gt;
** Displays detailed information about the selected subject hierarchy item&lt;br /&gt;
&lt;br /&gt;
; Transform hierarchy&lt;br /&gt;
* '''Nodes''': The view lists all transformable nodes of the scene as a hierarchical tree that describes the relationships between nodes. Nodes are graphical objects such as volumes or models that control the displays in the different views (2D, 3D). To rename an item, double click with the left button on any item (but the scene) in the list. A right click pops up a menu containing different actions: &amp;quot;Insert Transform&amp;quot; creates an identity linear transform node and applies it on the selected node. &amp;quot;Edit properties&amp;quot; opens the module of the node (e.g. &amp;quot;Volumes&amp;quot; for volume nodes, &amp;quot;Models&amp;quot; for model nodes, etc.). &amp;quot;Rename&amp;quot; opens a dialog to rename the node. &amp;quot;Delete&amp;quot; removes the node from the scene. Internal drag-and-drops are supported in the view, while moving a node position within the same parent has no effect, changing the parent of a node has a different meaning depending on the current scene model.&lt;br /&gt;
* '''Show MRML ID's''': Show/hide in the tree view a second column containing the node ID of the nodes. Hidden by default&lt;br /&gt;
* '''Show hidden nodes''': Show/hide the hidden nodes. By default, only the main nodes are shown&lt;br /&gt;
&lt;br /&gt;
; All nodes&lt;br /&gt;
* Unstructured view of all nodes in the scene. Supports Edit properties, Rename, Delete&lt;br /&gt;
&lt;br /&gt;
; Common&lt;br /&gt;
* '''Filter''': Hide all the nodes not matching the typed string. This can be useful to quickly search for a specific node. Please note that the search is case sensitive&lt;br /&gt;
* '''MRML node information''': Attribute list of the currently selected node. Attributes can be edited (double click in the &amp;quot;Attribute value&amp;quot; cell), added (with the &amp;quot;Add&amp;quot; button) or removed (with the &amp;quot;Remove&amp;quot; button).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|How to}}&lt;br /&gt;
&lt;br /&gt;
; Create new Subject from scratch&lt;br /&gt;
: Right-click on the empty area and select 'Create new subject'&lt;br /&gt;
&lt;br /&gt;
; Create new folder&lt;br /&gt;
: Right-click on an existing item or the empty area and select 'Create new folder'. Folder type hierarchy item can be converted to Subject or Study using the context menu&lt;br /&gt;
&lt;br /&gt;
; Rename item&lt;br /&gt;
: Right-click on the node and select 'Rename', or double-click the name of a node&lt;br /&gt;
&lt;br /&gt;
; Apply transform on node or branch&lt;br /&gt;
: Double-click the cell of the node or branch to transform in the transform column (same icon as Transforms module), then set the desired transform. If the column is not visible, check the 'Transforms' checkbox under the tree.  An example can be seen in the top screenshot at Patient 2&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
[[File:20170425_SubjectHierarchyInDataNode.png|thumb|409px| Subject hierarchy tree]]&lt;br /&gt;
[[File:SlicerRT_0.13_HuntingtonsLongitudinalInSubjectHierarchy2.png|thumb|622px| Parse local data loaded from directory structures]]&lt;br /&gt;
[[File:20170425_TransformHierarchyInDataNode.png|thumb|410px| Transform hierarchy]]&lt;br /&gt;
[[File:20170425_AllNodesInDataNode.png|thumb|410px| All nodes view]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Similar Modules}}&lt;br /&gt;
N/A&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|References}}&lt;br /&gt;
* Additional information on [[Documentation/Labs/SubjectHierarchy|Subject hierarchy labs page]]&lt;br /&gt;
* Manual editing of segmentations can be done in the [http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Modules/SegmentEditor Segment Editor module]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-section|Information for Developers}}&lt;br /&gt;
* Code snippets accessing and manipulating subject hierarchy items can be found in the [https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Subject_hierarchy script repository]&lt;br /&gt;
* '''Implementing new plugins''': Plugins are the real power of subject hierarchy, as they provide support for data node types, and add functionality to the context menu items.&amp;lt;br&amp;gt;To create a C++ plugin, implement a child class of qSlicerSubjectHierarchyAbstractPlugin, for Python plugin see below. Many examples can be found in Slicer core and in the SlicerRT extension, look for folders named SubjectHierarchyPlugins.&lt;br /&gt;
** Writing plugins in '''Python''':&lt;br /&gt;
*** Child class of AbstractScriptedSubjectHierarchyPlugin which is a Python adaptor of the C++ qSlicerSubjectHierarchyScriptedPlugin class&lt;br /&gt;
*** Example: [https://github.com/Slicer/Slicer/blob/master/Modules/Loadable/Annotations/SubjectHierarchyPlugins/AnnotationsSubjectHierarchyPlugin.py Annotations] role plugin, [https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/SegmentEditor/SubjectHierarchyPlugins/SegmentEditorSubjectHierarchyPlugin.py function plugin]&lt;br /&gt;
** '''Role''' plugins: add support for new data node types&lt;br /&gt;
*** Defines: ownership, icon, tooltip, edit properties, help text (in the yellow question mark popup), visibility icon, set/get display visibility, displayed node name (if different than name of the node object)&lt;br /&gt;
*** Existing plugins in Slicer core: Markups, Models, SceneViews, Charts, Folder, Tables, Transforms, LabelMaps, Volumes&lt;br /&gt;
** '''Function''' plugins: add feature in right-click context menu for certain types of nodes&lt;br /&gt;
*** Defines: list of contect menu actions for nodes and the scene, types of nodes for which the action shows up, functions handling the defined action&lt;br /&gt;
*** Existing plugins in Slicer core: CloneNode, ParseLocalData, Register, Segment, DICOM, Volumes, Markups, Models, Annotations, Segmentations, Segments, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;br /&gt;
{{documentation/{{documentation/version}}/module-footer}}&lt;br /&gt;
&amp;lt;!-- ---------------------------- --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pinter</name></author>
		
	</entry>
</feed>