<?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=Arankin</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=Arankin"/>
	<link rel="alternate" type="text/html" href="https://www.slicer.org/wiki/Special:Contributions/Arankin"/>
	<updated>2026-05-01T16:18:37Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.33.0</generator>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/FAQ/Python_Scripting&amp;diff=61372</id>
		<title>Documentation/Nightly/Developers/FAQ/Python Scripting</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/FAQ/Python_Scripting&amp;diff=61372"/>
		<updated>2019-08-21T15:23:21Z</updated>

		<summary type="html">&lt;p&gt;Arankin: Adding information about different decorator types and adding links to code source&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;noinclude&amp;gt;__TOC__&lt;br /&gt;
={{#titleparts: {{PAGENAME}} | | -1 }}=&amp;lt;/noinclude&amp;gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
='''Developer FAQ: {{{1}}}'''=&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How to run pip ? ==&lt;br /&gt;
&lt;br /&gt;
The pip executable is not distributed, instead the following command should be used:&lt;br /&gt;
* from build tree: &amp;lt;tt&amp;gt;/path/to/Slicer-SuperBuild/python-install/bin/PythonSlicer -m pip ...&amp;lt;/tt&amp;gt;&lt;br /&gt;
* from install tree:&lt;br /&gt;
  * Linux/MacOS: &amp;lt;tt&amp;gt;/path/to/Slicer-X.Y.Z-plat-arch/bin/PythonSlicer -m pip ...&amp;lt;/tt&amp;gt;&lt;br /&gt;
  * Windows: &amp;lt;tt&amp;gt;&amp;quot;c:\Program Files\Slicer 4.10.0\bin\PythonSlicer.exe&amp;quot; -m pip ...&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See this discussion for more details and background: https://discourse.slicer.org/t/slicer-python-packages-use-and-install/984/29.&lt;br /&gt;
&lt;br /&gt;
== How to access a scripted module from python scripts ==&lt;br /&gt;
&lt;br /&gt;
All slicer modules are accessible in the &amp;lt;code&amp;gt;slicer.modules&amp;lt;/code&amp;gt; namespace. For example, ''sampledata'' module can be accessed as &amp;lt;code&amp;gt;slicer.modules.sampledata&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To access a module's widget, use &amp;lt;code&amp;gt;widgetRepresentation()&amp;lt;/code&amp;gt; method to get the C++ base class and its &amp;lt;code&amp;gt;self()&amp;lt;/code&amp;gt; method to get the Python class. For example, &amp;lt;code&amp;gt;slicer.modules.sampledata.widgetRepresentation().self()&amp;lt;/code&amp;gt; returns the Python widget object of ''sampledata'' module.&lt;br /&gt;
&lt;br /&gt;
== How to systematically execute custom python code at startup ? ==&lt;br /&gt;
&lt;br /&gt;
Each time Slicer starts, it will look up for a startup script file named &amp;lt;code&amp;gt;.slicerrc.py&amp;lt;/code&amp;gt; in your [[Documentation/{{documentation/version}}/FAQ/General#What_is_my_HOME_folder_.3F|HOME folder]]. Content of this file is executed automatically at each startup of Slicer.&lt;br /&gt;
&lt;br /&gt;
You can find the path to the startup script in Slicer by opening in the menu: Edit / Application Settings. ''Application startup script'' path is shown in the ''General'' section.&lt;br /&gt;
&lt;br /&gt;
The default name and location of the file can be overridden by setting an environment variable named &amp;lt;code&amp;gt;SLICERRC&amp;lt;/code&amp;gt; that contains full path of a Python file.&lt;br /&gt;
&lt;br /&gt;
== How to save an image/volume using python ? ==&lt;br /&gt;
&lt;br /&gt;
The module &amp;lt;code&amp;gt;slicer.util&amp;lt;/code&amp;gt; provides methods allowing to save either a node or an entire scene:&lt;br /&gt;
* saveNode&lt;br /&gt;
* saveScene&lt;br /&gt;
&lt;br /&gt;
For more details see:&lt;br /&gt;
* https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/util.py#L229-267&lt;br /&gt;
* https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/tests/test_slicer_util_save.py&lt;br /&gt;
&lt;br /&gt;
=== Enable or disable compression while saving a volume ===&lt;br /&gt;
&lt;br /&gt;
While volumes can be accessed in Slicer Python modules as vtkMRMLVolumeNode, compression preference (or any other property for that matter) should be passed to slicer.util.saveNode function. The property will be passed to Slicer's storage node. For compression set the &amp;lt;code&amp;gt;useCompression&amp;lt;/code&amp;gt; to 0 or 1. Example script:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
properties = {'useCompression': 0}; #do not compress&lt;br /&gt;
file_path = os.path.join(case_dir, file_name)&lt;br /&gt;
slicer.util.saveNode(node, file_path, properties)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How to assign a volume to a Slice view ? ==&lt;br /&gt;
&lt;br /&gt;
Assuming the &amp;lt;code&amp;gt;MRHead&amp;lt;/code&amp;gt; sample data has been loaded, you could do the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
red_logic = slicer.app.layoutManager().sliceWidget(&amp;quot;Red&amp;quot;).sliceLogic()&lt;br /&gt;
red_cn = red_logic.GetSliceCompositeNode()&lt;br /&gt;
red_logic.GetSliceCompositeNode().SetBackgroundVolumeID(slicer.util.getNode('MRHead').GetID())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Discussion: http://slicer-devel.65872.n3.nabble.com/Assign-volumes-to-views-tt4028694.html&lt;br /&gt;
&lt;br /&gt;
== How to access vtkRenderer in Slicer 3D view ? ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
renderer = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow().GetRenderers().GetFirstRenderer()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How to get VTK rendering backend ? ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
backend = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow().GetRenderingBackend()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How to access displayable manager associated with a Slicer 2D or 3D view ? ==&lt;br /&gt;
&lt;br /&gt;
As originally explained [http://slicer-devel.65872.n3.nabble.com/How-to-get-the-point-of-a-3D-model-based-on-the-fiducial-position-td4031760.html#a4031762 here], you could use the method &amp;lt;code&amp;gt;getDisplayableManagers()&amp;lt;/code&amp;gt; available in any [{{doxygen-class-url|qMRMLThreeDView}} qMRMLThreeDView] and [{{doxygen-class-url|qMRMLSliceView}} qMRMLSliceView].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
for v in range(lm.threeDViewCount):&lt;br /&gt;
  td = lm.threeDWidget(v)&lt;br /&gt;
  ms = vtk.vtkCollection()&lt;br /&gt;
  td.getDisplayableManagers(ms)&lt;br /&gt;
  for i in range(ms.GetNumberOfItems()):&lt;br /&gt;
   m = ms.GetItemAsObject(i)&lt;br /&gt;
   if m.GetClassName() == &amp;quot;vtkMRMLModelDisplayableManager&amp;quot;:&lt;br /&gt;
     print(m)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How to center the 3D view on the scene ? ==&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.resetFocalPoint()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Should I use 'old style' or 'new style' python classes in my scripted module ? ==&lt;br /&gt;
&lt;br /&gt;
When python classes have no superclass specified they are 'old style' as described here [http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes].&lt;br /&gt;
&lt;br /&gt;
In general it doesn't matter for the classes in a scripted module, since they won't be subclassed either old or new style should be the same.&lt;br /&gt;
&lt;br /&gt;
For other python code in slicer where you might be subclassing, it's better to use new style classes.  See the class hierarchies in the [https://github.com/Slicer/Slicer/tree/master/Modules/Scripted/EditorLib EditorLib] and the [https://github.com/Slicer/Slicer/tree/master/Modules/Scripted/DICOM/DICOMLib DICOMLib] for examples.&lt;br /&gt;
&lt;br /&gt;
== How to harden a transform ? ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; n = getNode('Bone')&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; logic = slicer.vtkSlicerTransformLogic()&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; logic.hardenTransform(n)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Discussion: http://slicer-devel.65872.n3.nabble.com/Scripting-hardened-transforms-tt4029456.html&lt;br /&gt;
&lt;br /&gt;
== Where can I find example scripts? ==&lt;br /&gt;
&lt;br /&gt;
Have a look at [[Documentation/{{documentation/version}}/ScriptRepository]].&lt;br /&gt;
&lt;br /&gt;
== How can I use a visual debugger for step-by-step debugging ==&lt;br /&gt;
&lt;br /&gt;
===Debugging using PyCharm or PyDev===&lt;br /&gt;
Visual debugging (setting breakpoints, execute code step-by-step, view variables, stack, etc.) of Python scripted module is possible by using [https://www.jetbrains.com/pycharm/ PyCharm] or [http://pydev.org/ PyDev] by using the ''Python debugger'' module [[Documentation/{{documentation/version}}/Extensions/DebuggingTools|Debugging tools]] extension.&lt;br /&gt;
&lt;br /&gt;
'''See detailed instructions at the [[Documentation/{{documentation/version}}/Extensions/DebuggingTools|Debugging tools extension page]].'''&lt;br /&gt;
[[File:PyDevRemoteDebugSlicer.png|800px|thumb|center|Visual debugging of Python modules in Slicer]]&lt;br /&gt;
&lt;br /&gt;
===Debugging using Visual Studio===&lt;br /&gt;
On Windows, [https://github.com/Microsoft/PTVS Python Tools for Visual Studio] (PTVS) enables debugging Python inside Visual Studio. Its remote debugging capability allows attaching the debugger to Slicer's embedded Python environment.&lt;br /&gt;
&lt;br /&gt;
See [[Documentation/{{documentation/version}}/Developers/Tutorials/Debugging_Python_in_Visual_Studio | Debugging Python in Visual Studio]] for details.&lt;br /&gt;
&lt;br /&gt;
===Debugging using remote-pdb===&lt;br /&gt;
&lt;br /&gt;
A command line debugging session with a [https://docs.python.org/3/library/pdb.html pdb] interface can be achieved with [https://github.com/ionelmc/python-remote-pdb python-remote-pdb].&lt;br /&gt;
&lt;br /&gt;
Install python-remote-pdb into Slicer's Python:&lt;br /&gt;
&lt;br /&gt;
  git clone https://github.com/ionelmc/python-remote-pdb.git&lt;br /&gt;
  cd python-remote-pdb&lt;br /&gt;
  /path/to/Slicer-build/Slicer-build/Slicer ./setup.py install&lt;br /&gt;
&lt;br /&gt;
Then, call ''set_trace()'' where you want to start the debugger.&lt;br /&gt;
&lt;br /&gt;
  from remote_pdb import set_trace; set_trace()&lt;br /&gt;
&lt;br /&gt;
In the console where Slicer was started, a message like the following will be printed:&lt;br /&gt;
&lt;br /&gt;
  RemotePdb session open at 127.0.0.1:1234, waiting for connection&lt;br /&gt;
&lt;br /&gt;
In another terminal, connect with telnet:&lt;br /&gt;
&lt;br /&gt;
  telnet 127.0.0.1 1234&lt;br /&gt;
&lt;br /&gt;
or socat (has history, readline support):&lt;br /&gt;
&lt;br /&gt;
  socat readline tcp:127.0.0.1:1234&lt;br /&gt;
&lt;br /&gt;
== Why can't I access my C++ Qt class from python ==&lt;br /&gt;
* Python wrapping of a Qt class requires a Qt style constructor with QObject as argument (it can be defaulted to null though), which is public. If one of these are missing, python wrapping will fail for that class&lt;br /&gt;
* You cannot access your custom C++ Qt classes from python outside of the scope of your instantiated python class. These will not work:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BarIDRole = slicer.qFooItemDelegate.LastRole + 1&lt;br /&gt;
&lt;br /&gt;
class BarTableWidget(qt.QTableWidget, VTKObservationMixin):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, *args, **kwargs):&lt;br /&gt;
        [...]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class BarTableWidget(qt.QTableWidget, VTKObservationMixin):&lt;br /&gt;
&lt;br /&gt;
    BarIDRole = slicer.qFooItemDelegate.LastRole + 1&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, *args, **kwargs):&lt;br /&gt;
        [...]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class BarTableWidget(qt.QTableWidget, VTKObservationMixin):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, *args, **kwargs):&lt;br /&gt;
        self.BarIDRole = slicer.qFooItemDelegate.LastRole + 1&lt;br /&gt;
        [...]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* [Other reasons go here]&lt;br /&gt;
&lt;br /&gt;
== Can I use factory method like CreateNodeByClass or GetNodesByClass ? ==&lt;br /&gt;
&lt;br /&gt;
See [[Documentation/{{documentation/version}}/Developers/Tutorials/MemoryManagement#Factory_methods]]&lt;br /&gt;
&lt;br /&gt;
== How can I access callData argument in a VTK object observer callback function ==&lt;br /&gt;
&lt;br /&gt;
To get notification about an event emitted by a VTK object you can simply use the AddObserver method, for example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def sceneModifiedCallback(caller, eventId):&lt;br /&gt;
  print(&amp;quot;Scene modified&amp;quot;)&lt;br /&gt;
  print(&amp;quot;There are {0} nodes in the scene&amp;quot;. format(slicer.mrmlScene.GetNumberOfNodes()))&lt;br /&gt;
&lt;br /&gt;
sceneModifiedObserverTag = slicer.mrmlScene.AddObserver(vtk.vtkCommand.ModifiedEvent, sceneModifiedCallback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If an event also contains additional information as CallData then the type of this argument has to be specified as well, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
def nodeAddedCallback(caller, eventId, callData):&lt;br /&gt;
  print(&amp;quot;Node added&amp;quot;)&lt;br /&gt;
  print(&amp;quot;New node: {0}&amp;quot;.format(callData.GetName()))&lt;br /&gt;
&lt;br /&gt;
nodeAddedModifiedObserverTag = slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, nodeAddedCallback)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': @vtk.calldata_type is a Python decorator, which modifies properties of a function that is declared right after the decorator. The decorator is defined in VTK (in [https://github.com/Kitware/VTK/blob/master/Wrapping/Python/vtkmodules/util/misc.py Wrapping\Python\vtk\util\misc.py]).&lt;br /&gt;
&lt;br /&gt;
'''Note''': The available types are listed in [https://github.com/Kitware/VTK/blob/master/Wrapping/Python/vtkmodules/util/vtkConstants.py Wrapping\Python\vtkmodules\util\vtkConstants.py].&lt;br /&gt;
&lt;br /&gt;
Usage from a class requires an extra step of creating the callback in the class __init__ function, as Python2 by default does some extra wrapping (http://stackoverflow.com/questions/9523370/adding-attributes-to-instance-methods-in-python):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MyClass:&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    from functools import partial&lt;br /&gt;
    def nodeAddedCallback(self, caller, eventId, callData):&lt;br /&gt;
      print(&amp;quot;Node added&amp;quot;)&lt;br /&gt;
      print(&amp;quot;New node: {0}&amp;quot;.format(callData.GetName()))&lt;br /&gt;
    self.nodeAddedCallback = partial(nodeAddedCallback, self)&lt;br /&gt;
    self.nodeAddedCallback.CallDataType = vtk.VTK_OBJECT&lt;br /&gt;
  def registerCallbacks(self):&lt;br /&gt;
    self.nodeAddedModifiedObserverTag = slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, self.nodeAddedCallback)&lt;br /&gt;
  def unregisterCallbacks(self):&lt;br /&gt;
    slicer.mrmlScene.RemoveObserver(self.nodeAddedModifiedObserverTag)&lt;br /&gt;
        &lt;br /&gt;
myObject = MyClass()&lt;br /&gt;
myObject.registerCallbacks()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Allowed CallDataType values:  VTK_STRING, VTK_OBJECT, VTK_INT, VTK_LONG, VTK_DOUBLE, VTK_FLOAT, &amp;quot;string0&amp;quot;. See more information here:&lt;br /&gt;
https://github.com/Kitware/VTK/blob/master/Wrapping/PythonCore/vtkPythonCommand.cxx&lt;br /&gt;
&lt;br /&gt;
For a simplified syntax, see [[#How_to_manage_VTK_object_connections_.3F]]&lt;br /&gt;
&lt;br /&gt;
== How to manage VTK object connections ? ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;VTKObservationMixin&amp;lt;/tt&amp;gt; is a Python mix-in that allows adding a set of methods to a class by inheritance. &lt;br /&gt;
It includes the following methods defined in [https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/util.py#L995 Base/Python/slicer/util.py]:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addObserver&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;hasObserver&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;observer&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeObserver&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeObservers&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following illustrates how to observe the &amp;lt;tt&amp;gt;slicer.vtkMRMLScene.NodeAddedEvent&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from slicer.util import VTKObservationMixin&lt;br /&gt;
&lt;br /&gt;
class MyClass(VTKObservationMixin):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    VTKObservationMixin.__init__(self)&lt;br /&gt;
    self.addObserver(slicer.mrmlScene, slicer.vtkMRMLScene.NodeAddedEvent, self.nodeAddedCallback)&lt;br /&gt;
  &lt;br /&gt;
  @vtk.calldata_type(vtk.VTK_OBJECT)&lt;br /&gt;
  def nodeAddedCallback(self, caller, eventId, callData):&lt;br /&gt;
    print(&amp;quot;Node added&amp;quot;)&lt;br /&gt;
    print(&amp;quot;New node: {0}&amp;quot;.format(callData.GetName()))&lt;br /&gt;
&lt;br /&gt;
myObject = MyClass()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For additional examples of usage, see [https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/tests/test_slicer_util_VTKObservationMixin.py test_slicer_util_VTKObservationMixin.py]&lt;br /&gt;
&lt;br /&gt;
== Slicer crashes if I try to access a non-existing item in an array ==&lt;br /&gt;
&lt;br /&gt;
For example, this code makes Slicer crash:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
s = vtk.vtkStringArray()&lt;br /&gt;
s.GetValue(0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This behavior is expected, as all VTK objects are implemented in C++ that offers much faster operation but developers have to take care of addressing only valid array elements, for example by checking the number of elements in the array:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if itemIndex &amp;lt; 0 or itemIndex &amp;gt;= s.GetNumberOfValues()&lt;br /&gt;
  raise IndexError(&amp;quot;index out of bounds&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How to run CLI module from Python? ==&lt;br /&gt;
&lt;br /&gt;
See [[Documentation/{{documentation/version}}/Developers/Python_scripting#Running_a_CLI_from_Python|here]].&lt;br /&gt;
&lt;br /&gt;
== How can I run slicer operations from a batch script? ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Slicer --no-main-window --python-script /tmp/test.py&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Contents of /tmp/test.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# use a slicer scripted module logic&lt;br /&gt;
from SampleData import SampleDataLogic&lt;br /&gt;
SampleDataLogic().downloadMRHead()&lt;br /&gt;
head = slicer.util.getNode('MRHead')&lt;br /&gt;
&lt;br /&gt;
# use a vtk class&lt;br /&gt;
threshold = vtk.vtkImageThreshold()&lt;br /&gt;
threshold.SetInputData(head.GetImageData())&lt;br /&gt;
threshold.ThresholdBetween(100, 200)&lt;br /&gt;
threshold.SetInValue(255)&lt;br /&gt;
threshold.SetOutValue(0)&lt;br /&gt;
&lt;br /&gt;
#  use a slicer-specific C++ class&lt;br /&gt;
erode = slicer.vtkImageErode()&lt;br /&gt;
erode.SetInputConnection(threshold.GetOutputPort())&lt;br /&gt;
erode.SetNeighborTo4()  &lt;br /&gt;
erode.Update()          &lt;br /&gt;
&lt;br /&gt;
head.SetAndObserveImageData(erode.GetOutputDataObject(0))&lt;br /&gt;
&lt;br /&gt;
slicer.util.saveNode(head, &amp;quot;/tmp/eroded.nrrd&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
exit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How can I run Slicer on a headless compute node? ==&lt;br /&gt;
&lt;br /&gt;
Many cluster nodes are installed with minimal linux systems that don't include X servers.  X servers, particularly those with hardware acceleration traditionally needed to be installed with root privileges, making it impossible to run applications that rendered using X or OpenGL.&lt;br /&gt;
&lt;br /&gt;
But there is a workaround which allows everything in slicer to work normally so you could even do headless rendering.&lt;br /&gt;
&lt;br /&gt;
You can use a modern version of X that supports running a dummy framebuffer.  This can be installed in user mode so you don't even need to have root on the system.&lt;br /&gt;
&lt;br /&gt;
See [https://www.xpra.org/trac/wiki/Xdummy] for details.&lt;br /&gt;
&lt;br /&gt;
There's a thread here with more discussion: [http://massmail.spl.harvard.edu/public-archives/slicer-devel/2015/017317.html]&lt;br /&gt;
&lt;br /&gt;
Here is a working example of the approach running on a headless compute node running CTK tests (which also use Qt and VTK)&lt;br /&gt;
&lt;br /&gt;
[https://github.com/pieper/CTK/blob/master/.travis.yml]&lt;br /&gt;
&lt;br /&gt;
== How to save user's selection of parameters and nodes in the scene? ==&lt;br /&gt;
&lt;br /&gt;
It is preferable to save all the parameter values and nodes selections that the user made on the user interface into the MRML scene. This allows the user to load a scene and continue from where he left off. These information can be saved in a ''slicer.vtkMRMLScriptedModuleNode()'' node.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
parameterNode=slicer.vtkMRMLScriptedModuleNode()&lt;br /&gt;
&lt;br /&gt;
# Save parameter values and node references to parameter node&lt;br /&gt;
&lt;br /&gt;
alpha = 5.0&lt;br /&gt;
beta = &amp;quot;abc&amp;quot;&lt;br /&gt;
inputNode = slicer.util.getNode(&amp;quot;InputNode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
parameterNode.SetParameter(&amp;quot;Alpha&amp;quot;,str(alpha))&lt;br /&gt;
parameterNode.SetParameter(&amp;quot;Beta&amp;quot;, beta)&lt;br /&gt;
parameterNode.SetNodeReferenceID(&amp;quot;InputNode&amp;quot;, inputNode.GetID())&lt;br /&gt;
&lt;br /&gt;
# Retrieve parameter values and node references from parameter node&lt;br /&gt;
&lt;br /&gt;
alpha = float(parameterNode.GetParameter(&amp;quot;Alpha&amp;quot;))&lt;br /&gt;
beta = parameterNode.GetParameter(&amp;quot;Beta&amp;quot;)&lt;br /&gt;
inputNode = parameterNode.GetNodeReference(&amp;quot;InputNode&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Scripted module's logic class have a helper function, ''getParameterNode'', which returns a parameter node that is unique for a specific module. The function creates the parameter node if it has not been created yet. By default, the parameter node is a singleton node, which means that there is only a single instance of the node in the scene. If it is preferable to allow multiple instances of the parameter node, set ''isSingletonParameterNode'' member of the logic object to ''False''.&lt;br /&gt;
&lt;br /&gt;
== How to load a UI file ? ==&lt;br /&gt;
&lt;br /&gt;
See [[Documentation/Nightly/Developers/Tutorials/PythonAndUIFile]]&lt;br /&gt;
&lt;br /&gt;
== How to update progress bar in scripted (Python, or other) CLI modules ==&lt;br /&gt;
&lt;br /&gt;
As detailed in the [https://www.slicer.org/wiki/Documentation/Nightly/Developers/SlicerExecutionModel#Showing_Progress_in_an_Application|Slicer Execution Model documentation], Slicer parses specifically-formatted XML commands printed on stdout, to allow any out-of-process CLI program to report progress back to the main Slicer application (which will causing the progress bar to update). However, it is very important to note that the output must be flushed after each print statement, or else Slicer will not parse the progress sections until the process ends. See the calls to &amp;lt;pre&amp;gt;sys.stdout.flush()&amp;lt;/pre&amp;gt; in the example Python CLI shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python-real&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  import time&lt;br /&gt;
  import sys&lt;br /&gt;
  &lt;br /&gt;
  print(&amp;quot;&amp;quot;&amp;quot;&amp;lt;filter-start&amp;gt;&amp;lt;filter-name&amp;gt;TestFilter&amp;lt;/filter-name&amp;gt;&amp;lt;filter-comment&amp;gt;ibid&amp;lt;/filter-comment&amp;gt;&amp;lt;/filter-start&amp;gt;&amp;quot;&amp;quot;&amp;quot;)&lt;br /&gt;
  sys.stdout.flush()&lt;br /&gt;
&lt;br /&gt;
  for i in range(0,10):&lt;br /&gt;
      print(&amp;quot;&amp;quot;&amp;quot;&amp;lt;filter-progress&amp;gt;{}&amp;lt;/filter-progress&amp;gt;&amp;quot;&amp;quot;&amp;quot;.format(i/10.0))&lt;br /&gt;
      sys.stdout.flush()&lt;br /&gt;
      time.sleep(0.5)&lt;br /&gt;
&lt;br /&gt;
  print(&amp;quot;&amp;quot;&amp;quot;&amp;lt;filter-end&amp;gt;&amp;lt;filter-name&amp;gt;TestFilter&amp;lt;/filter-name&amp;gt;&amp;lt;filter-time&amp;gt;10&amp;lt;/filter-time&amp;gt;&amp;lt;/filter-end&amp;gt;&amp;quot;&amp;quot;&amp;quot;)&lt;br /&gt;
  sys.stdout.flush()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How to run Python script using a non-Slicer Python environment ==&lt;br /&gt;
&lt;br /&gt;
If you need to run Python scripts using not Slicer's embedded interpreter but using a different environment (Python3, Anaconda, etc.) then you need to run the Python executable using a default startup environment. Starting from Slicer's environment would cause loading of Slicer's Python libraries, which are expected to be binary incompatible with the external environment and therefore would make the external application crash.&lt;br /&gt;
&lt;br /&gt;
Example of running python code using system Python3 in Linux from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_line = [&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;
command_result = check_output(command_line, env=slicer.util.startupEnvironment())&lt;br /&gt;
print(command_result)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example script just prints 'hola' and exits, but the code can be replaced by more complex instructions or launching of a Python script.&lt;br /&gt;
&lt;br /&gt;
Example of running python code using Anaconda using environment named 'workspace-gpu' on Windows from Slicer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
command_line = [r&amp;quot;c:\Users\msliv\Miniconda3\envs\workspace-gpu\python.exe&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;print('hola')&amp;quot;]&lt;br /&gt;
from subprocess import check_output&lt;br /&gt;
command_result = check_output(command_line, env=slicer.util.startupEnvironment())&lt;br /&gt;
print(command_result)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arankin</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/IO&amp;diff=59246</id>
		<title>Documentation/Nightly/Developers/IO</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/IO&amp;diff=59246"/>
		<updated>2018-08-01T13:54:00Z</updated>

		<summary type="html">&lt;p&gt;Arankin: /* Example */ Updating Links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
=Read=&lt;br /&gt;
[[Image:IOOverview.png|600px|center]]&lt;br /&gt;
== Main classes ==&lt;br /&gt;
* &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;Node&amp;lt;/code&amp;gt; is a [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLStorableNode.h?view=markup storable node] that represents the data from file (e.g. [[http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLModelNode.h?view=markup vtkMRMLModelNode])&lt;br /&gt;
* &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode&amp;lt;/code&amp;gt; is the file reader. It populates the storable node using the method  &amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode::ReadData(vtkMRMLStorableNode*,bool)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sLogic&amp;lt;/code&amp;gt; is the MRML logic of the &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; module. It exposes a convenient method &amp;lt;code&amp;gt;AddXYZ(const char* fileName, const char* nodeName=0);&amp;lt;/code&amp;gt; that creates a MRML &amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt; node (&amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;Node&amp;lt;/code&amp;gt;)and its associated storage node (&amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode&amp;lt;/code&amp;gt;), add them into the scene, and call &amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode::ReadData(vtkMRMLStorableNode*,bool);&amp;lt;/code&amp;gt; on the storage node to load the file. If the loading fails, it removes the previously created nodes from the scene.&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sReaderPlugin&amp;lt;/code&amp;gt; is a plugin that is registered by modules into the &amp;lt;code&amp;gt;qSlicerCoreIOManager&amp;lt;/code&amp;gt;. It is the interface between Qt and MRML logics. It internally calls &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sLogic::Add&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;&amp;lt;/code&amp;gt;().&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sOptionsWidget&amp;lt;/code&amp;gt; is a widget that sets loading options that gets passed to the logic.&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicerCoreIOManager&amp;lt;/code&amp;gt; is the central class where any IO operation must go through. qSlicerIOs can be registered using &amp;lt;code&amp;gt;qSlicerCoreIOManager::registerIO(qSlicerIO*)&amp;lt;/code&amp;gt; and nodes can be loaded using &amp;lt;code&amp;gt;qSlicerCoreIOManager::loadNodes(...)&amp;lt;/code&amp;gt;. It exposes a set of convenient methods such as &amp;quot;what reader must be used for what file&amp;quot;.&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicerDataDialog&amp;lt;/code&amp;gt; is the dialog that allows the user to select the files to load.&lt;br /&gt;
&lt;br /&gt;
==How to add support for reading a new file format ?==&lt;br /&gt;
# Write method &amp;lt;code&amp;gt;vtkMRMLXYZStorageNode::ReadDataInternal(vtkMRMLStorableNode*, bool temporary);&amp;lt;/code&amp;gt;&lt;br /&gt;
# Write method &amp;lt;code&amp;gt;vtkMRMLXYZsLogic::AddXYZ(const char* fileName, const char nodeName =0);&amp;lt;/code&amp;gt;&lt;br /&gt;
# Write class &amp;lt;code&amp;gt;qSlicerXYZsReaderPlugin&amp;lt;/code&amp;gt;&lt;br /&gt;
# Optional: Write class &amp;lt;code&amp;gt;qSlicerXYZsOptionsWidget&amp;lt;/code&amp;gt; if you want the user to optionally specify loading options.&lt;br /&gt;
# In &amp;lt;code&amp;gt;qSlicerXYZsModule::setup()&amp;lt;/code&amp;gt;, instantiate and register &amp;lt;code&amp;gt;qSlicerXYZsIO&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;qSlicerCoreIOManager&amp;lt;/code&amp;gt;&lt;br /&gt;
# Add file format to [Documentation/{{documentation/version}}/SlicerApplication/SupportedDataFormat|SupportedDataFormat] wiki page&lt;br /&gt;
&lt;br /&gt;
== ModifiedSinceRead ==&lt;br /&gt;
In order to inform the user what data has been changed since it was last read, a ModifiedSinceRead mechanism is in place to track when was the file last read and when was the data last modified. If a modification happened , the storable node &amp;lt;code&amp;gt;vtkMRMLStorableNode::GetModifiedSinceRead()&amp;lt;/code&amp;gt; must return true. If the data in the node is the same as in the file, then &amp;lt;code&amp;gt;vtkMRMLStorableNode::GetModifiedSinceRead()&amp;lt;/code&amp;gt; must return false.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;vtkMRMLStorageNode&amp;lt;/code&amp;gt; keeps track of when a file was last read or written (&amp;lt;code&amp;gt;vtkTimeStamp* vtkMRMLStorageNode::StoredTime&amp;lt;/code&amp;gt;). &amp;lt;code&amp;gt;vtkMRMLStorableNode&amp;lt;/code&amp;gt; keeps track of when the data was last modified (&amp;lt;code&amp;gt;vtkTimeStamp vtkMRMLStorableNode::StorableModifiedTime&amp;lt;/code&amp;gt;). Anytime a &amp;lt;code&amp;gt;vtkMRMLStorableNode&amp;lt;/code&amp;gt; property that is saved in file is modified, the &amp;lt;code&amp;gt;StorableModifiedTime&amp;lt;/code&amp;gt; time stamp must be modified.&lt;br /&gt;
&lt;br /&gt;
At exit time (&amp;lt;code&amp;gt;qSlicerMainWindow::closeEvent()&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;vtkMRMLStorableNode::GetModifiedSinceRead()&amp;lt;/code&amp;gt; is called to check if the data in the node is the same as in the file or if it has been modified after the file was last read or written. It internally checks &amp;lt;code&amp;gt;vtkTimeStamp* vtkMRMLStorageNode::StoredTime&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;vtkTimeStamp vtkMRMLStorableNode::StorableModifiedTime&amp;lt;/code&amp;gt;. If the data is more recent, then a message dialog is shown to the user telling him that some data is different from file; leaving without saving will lose the changes.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
* Models &lt;br /&gt;
** [https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Core/vtkMRMLModelNode.h Libs/MRML/Core/vtkMRMLModelNode]&lt;br /&gt;
** [https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Core/vtkMRMLModelStorageNode.h Libs/MRML/Core/vtkMRMLModelStorageNode]&lt;br /&gt;
** [https://github.com/Slicer/Slicer/blob/master/Modules/Loadable/Models/Logic/vtkSlicerModelsLogic.h Modules/Loadable/Models/Logic/vtkSlicerModelsLogic]&lt;br /&gt;
** [https://github.com/Slicer/Slicer/blob/master/Modules/Loadable/Models/qSlicerModelsReader.h Modules/Loadable/Models/qSlicerModelsReader]&lt;br /&gt;
** [https://github.com/Slicer/Slicer/blob/master/Modules/Loadable/Models/qSlicerModelsModule.h Modules/Loadable/Models/qSlicerModelsModule]&lt;br /&gt;
* VffFileReader&lt;br /&gt;
** [https://github.com/SlicerRt/SlicerRT/tree/master/VffFileReader VffFileReader]&lt;br /&gt;
&lt;br /&gt;
== How to load files programmatically ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerCoreIOManager.html qSlicerCoreIOManager]* coreIOManager = qSlicerCoreApplication::application()-&amp;gt;coreIOManager();&lt;br /&gt;
 qSlicerIO::IOProperties fileParameters;&lt;br /&gt;
 fileParameters[&amp;quot;fileName&amp;quot;] = &amp;quot;/path/of/file.ext&amp;quot;;&lt;br /&gt;
 vtkMRMLNode* volumeNode = coreIOManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerCoreIOManager.html#a36a78dba553b52f395f997fe11aaff23 loadNodesAndGetFirst](&amp;quot;VolumeFile&amp;quot;, fileParameters);&lt;br /&gt;
Works also with &amp;quot;ModelFile&amp;quot;, &amp;quot;TransformFile&amp;quot;, &amp;quot;SceneFile&amp;quot;...&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; volumeNode = slicer.util.loadVolume('/path/of/file.ext')&lt;br /&gt;
It works also with loadModel, loadTransform, loadScene...&lt;br /&gt;
|}&lt;br /&gt;
Note that [[#IO_Dialogs|IO dialogs]] should be used as often as possible.&lt;br /&gt;
&lt;br /&gt;
=Write=&lt;br /&gt;
The mechanism is similar to '''Read'''. &amp;lt;code&amp;gt;vtkMRMLXYZStorageNode::WriteDataInternal(...)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;qSlicerXYZWriter&amp;lt;/code&amp;gt; must implemented.&lt;br /&gt;
&lt;br /&gt;
== How to save files programmatically ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerCoreIOManager.html qSlicerCoreIOManager]* coreIOManager = qSlicerCoreApplication::application()-&amp;gt;coreIOManager();&lt;br /&gt;
 qSlicerIO::IOProperties fileParameters;&lt;br /&gt;
 fileParameters[&amp;quot;nodeID&amp;quot;] = volumeNode-&amp;gt;GetID();&lt;br /&gt;
 fileParameters[&amp;quot;fileName&amp;quot;] = &amp;quot;/path/of/file.ext&amp;quot;;&lt;br /&gt;
 coreIOManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerCoreIOManager.html#a1cd29140ded984afdd0f667064d38845 saveNodes](&amp;quot;VolumeFile&amp;quot;, fileParameters);&lt;br /&gt;
Works also with &amp;quot;ModelFile&amp;quot;, &amp;quot;TransformFile&amp;quot;, &amp;quot;SceneFile&amp;quot;...&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; slicer.util.saveNode(volumeNode, '/path/of/file.ext')&lt;br /&gt;
|}&lt;br /&gt;
Note that [[#IO_Dialogs|IO dialogs]] should be used as often as possible.&lt;br /&gt;
&lt;br /&gt;
=IO Dialogs=&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerFileDialog.html qSlicerFileDialog]&amp;lt;/code&amp;gt; is the base class to override a custom dialog.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerStandardFileDialog.html qSlicerStandardFileDialog]&amp;lt;/code&amp;gt; is a multi-purpose file dialog.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerDataDialog.html qSlicerDataDialog.h]&amp;lt;/code&amp;gt; is the default dialog to load files.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerSaveDataDialog.html qSlicerSaveDataDialog]&amp;lt;/code&amp;gt; is the default dialog to save files.&lt;br /&gt;
&lt;br /&gt;
By default, all the IOs must be done through &amp;lt;code&amp;gt;qSlicerDataDialog&amp;lt;/code&amp;gt; for reading files and &amp;lt;code&amp;gt;qSlicerSaveDataDialog&amp;lt;/code&amp;gt; for writing files. However, due to historical reasons, it is possible to have custom dialogs for each node types.&lt;br /&gt;
&lt;br /&gt;
It can be useful to create your own IO dialog to add custom behavior to the Slicer drag&amp;amp;drop default behavior.&lt;br /&gt;
== How to register a dialog ? ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
Register dialogs in qSlicerXYZModule::[http://slicer.org/doc/html/classqSlicerAbstractCoreModule.html#a9ad37e756338e7226f157b4eb54b9bcd setup()]:&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerIOManager.html qSlicerIOManager]* ioManager = qSlicerApplication::application()-&amp;gt;ioManager();&lt;br /&gt;
 ioManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerIOManager.html#ae47e9cf27f230335b865bce84a56e156 registerDialog](new qSlicerXYZDialog(this));&lt;br /&gt;
 ioManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerIOManager.html#ae47e9cf27f230335b865bce84a56e156 registerDialog](new qSlicerSaveXYZDialog(this));&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
Declare an XYZFileDialog in your XYZ.py module file. It will be automatically registered. For example:&lt;br /&gt;
 class XYZFileDialog:&lt;br /&gt;
   def __init__(self, parent):&lt;br /&gt;
     self.parent = parent&lt;br /&gt;
     parent.fileType = 'XYZFile'&lt;br /&gt;
     parent.description = 'XYZ'&lt;br /&gt;
     parent.action = slicer.qSlicerFileDialog.Read&lt;br /&gt;
   def isMimeDataAccepted(self):&lt;br /&gt;
     accept = self.parent.mimeData().hasFormat(&amp;quot;text/uri-list&amp;quot;)&lt;br /&gt;
     self.parent.acceptMimeData(accept)&lt;br /&gt;
   def dropEvent(self):&lt;br /&gt;
     self.parent.dropEvent().accept()&lt;br /&gt;
   def execDialog(self):&lt;br /&gt;
     print 'exec' &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== How to open a registered a dialog ? ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerIOManager.html qSlicerIOManager]* ioManager = qSlicerApplication::application()-&amp;gt;ioManager();&lt;br /&gt;
 ioManager-&amp;gt;openDialog(&amp;quot;VolumeFile&amp;quot;, qSlicerFileDialog::Read, qSlicerIO::IOProperties());&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
  io = slicer.app.ioManager()&lt;br /&gt;
  params = {}&lt;br /&gt;
  io.openDialog(&amp;quot;VolumeFile&amp;quot;, slicer.qSlicerFileDialog.Read, params)&lt;br /&gt;
And the special case for standard data file types:&lt;br /&gt;
 slicer.util.openAddVolumeDialog()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== How to order the list of drag&amp;amp;drop dialogs ?==&lt;br /&gt;
By controlling the order of module initialization. This is done by adding module dependencies. Make your module dependent of of the &amp;quot;Data&amp;quot; would make it initialize after the Data module that registers the &amp;quot;Any Data&amp;quot; dialogs:&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 QStringList qSlicerXYZModule::dependencies() const&lt;br /&gt;
 {&lt;br /&gt;
   QStringList moduleDependencies;&lt;br /&gt;
   moduleDependencies &amp;lt;&amp;lt; &amp;quot;Data&amp;quot;;&lt;br /&gt;
   return moduleDependencies;&lt;br /&gt;
 }&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 def __init__(self, parent):&lt;br /&gt;
   ...&lt;br /&gt;
   parent.dependencies = [&amp;quot;Data&amp;quot;] class XYZFileDialog:&lt;br /&gt;
   ...&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Arankin</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/IO&amp;diff=59245</id>
		<title>Documentation/Nightly/Developers/IO</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/IO&amp;diff=59245"/>
		<updated>2018-08-01T13:46:26Z</updated>

		<summary type="html">&lt;p&gt;Arankin: /* How to add support for reading a new 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;
=Read=&lt;br /&gt;
[[Image:IOOverview.png|600px|center]]&lt;br /&gt;
== Main classes ==&lt;br /&gt;
* &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;Node&amp;lt;/code&amp;gt; is a [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLStorableNode.h?view=markup storable node] that represents the data from file (e.g. [[http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLModelNode.h?view=markup vtkMRMLModelNode])&lt;br /&gt;
* &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode&amp;lt;/code&amp;gt; is the file reader. It populates the storable node using the method  &amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode::ReadData(vtkMRMLStorableNode*,bool)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sLogic&amp;lt;/code&amp;gt; is the MRML logic of the &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; module. It exposes a convenient method &amp;lt;code&amp;gt;AddXYZ(const char* fileName, const char* nodeName=0);&amp;lt;/code&amp;gt; that creates a MRML &amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt; node (&amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;Node&amp;lt;/code&amp;gt;)and its associated storage node (&amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode&amp;lt;/code&amp;gt;), add them into the scene, and call &amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode::ReadData(vtkMRMLStorableNode*,bool);&amp;lt;/code&amp;gt; on the storage node to load the file. If the loading fails, it removes the previously created nodes from the scene.&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sReaderPlugin&amp;lt;/code&amp;gt; is a plugin that is registered by modules into the &amp;lt;code&amp;gt;qSlicerCoreIOManager&amp;lt;/code&amp;gt;. It is the interface between Qt and MRML logics. It internally calls &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sLogic::Add&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;&amp;lt;/code&amp;gt;().&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sOptionsWidget&amp;lt;/code&amp;gt; is a widget that sets loading options that gets passed to the logic.&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicerCoreIOManager&amp;lt;/code&amp;gt; is the central class where any IO operation must go through. qSlicerIOs can be registered using &amp;lt;code&amp;gt;qSlicerCoreIOManager::registerIO(qSlicerIO*)&amp;lt;/code&amp;gt; and nodes can be loaded using &amp;lt;code&amp;gt;qSlicerCoreIOManager::loadNodes(...)&amp;lt;/code&amp;gt;. It exposes a set of convenient methods such as &amp;quot;what reader must be used for what file&amp;quot;.&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicerDataDialog&amp;lt;/code&amp;gt; is the dialog that allows the user to select the files to load.&lt;br /&gt;
&lt;br /&gt;
==How to add support for reading a new file format ?==&lt;br /&gt;
# Write method &amp;lt;code&amp;gt;vtkMRMLXYZStorageNode::ReadDataInternal(vtkMRMLStorableNode*, bool temporary);&amp;lt;/code&amp;gt;&lt;br /&gt;
# Write method &amp;lt;code&amp;gt;vtkMRMLXYZsLogic::AddXYZ(const char* fileName, const char nodeName =0);&amp;lt;/code&amp;gt;&lt;br /&gt;
# Write class &amp;lt;code&amp;gt;qSlicerXYZsReaderPlugin&amp;lt;/code&amp;gt;&lt;br /&gt;
# Optional: Write class &amp;lt;code&amp;gt;qSlicerXYZsOptionsWidget&amp;lt;/code&amp;gt; if you want the user to optionally specify loading options.&lt;br /&gt;
# In &amp;lt;code&amp;gt;qSlicerXYZsModule::setup()&amp;lt;/code&amp;gt;, instantiate and register &amp;lt;code&amp;gt;qSlicerXYZsIO&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;qSlicerCoreIOManager&amp;lt;/code&amp;gt;&lt;br /&gt;
# Add file format to [Documentation/{{documentation/version}}/SlicerApplication/SupportedDataFormat|SupportedDataFormat] wiki page&lt;br /&gt;
&lt;br /&gt;
== ModifiedSinceRead ==&lt;br /&gt;
In order to inform the user what data has been changed since it was last read, a ModifiedSinceRead mechanism is in place to track when was the file last read and when was the data last modified. If a modification happened , the storable node &amp;lt;code&amp;gt;vtkMRMLStorableNode::GetModifiedSinceRead()&amp;lt;/code&amp;gt; must return true. If the data in the node is the same as in the file, then &amp;lt;code&amp;gt;vtkMRMLStorableNode::GetModifiedSinceRead()&amp;lt;/code&amp;gt; must return false.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;vtkMRMLStorageNode&amp;lt;/code&amp;gt; keeps track of when a file was last read or written (&amp;lt;code&amp;gt;vtkTimeStamp* vtkMRMLStorageNode::StoredTime&amp;lt;/code&amp;gt;). &amp;lt;code&amp;gt;vtkMRMLStorableNode&amp;lt;/code&amp;gt; keeps track of when the data was last modified (&amp;lt;code&amp;gt;vtkTimeStamp vtkMRMLStorableNode::StorableModifiedTime&amp;lt;/code&amp;gt;). Anytime a &amp;lt;code&amp;gt;vtkMRMLStorableNode&amp;lt;/code&amp;gt; property that is saved in file is modified, the &amp;lt;code&amp;gt;StorableModifiedTime&amp;lt;/code&amp;gt; time stamp must be modified.&lt;br /&gt;
&lt;br /&gt;
At exit time (&amp;lt;code&amp;gt;qSlicerMainWindow::closeEvent()&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;vtkMRMLStorableNode::GetModifiedSinceRead()&amp;lt;/code&amp;gt; is called to check if the data in the node is the same as in the file or if it has been modified after the file was last read or written. It internally checks &amp;lt;code&amp;gt;vtkTimeStamp* vtkMRMLStorageNode::StoredTime&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;vtkTimeStamp vtkMRMLStorableNode::StorableModifiedTime&amp;lt;/code&amp;gt;. If the data is more recent, then a message dialog is shown to the user telling him that some data is different from file; leaving without saving will lose the changes.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
* Models &lt;br /&gt;
** [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLModelNode.h?view=markup Libs/MRML/Core/vtkMRMLModelNode]&lt;br /&gt;
** [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLModelStorageNode.h?view=markup Libs/MRML/Core/vtkMRMLModelStorageNode]&lt;br /&gt;
** [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Modules/Loadable/Models/Logic/vtkSlicerModelsLogic.h?view=markup Modules/Loadable/Models/Logic/vtkSlicerModelsLogic]&lt;br /&gt;
** [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Modules/Loadable/Models/qSlicerModelsIO.h?view=markup Modules/Loadable/Models/qSlicerModelsIO]&lt;br /&gt;
** [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Modules/Loadable/Models/qSlicerModelsModule.h?view=markup Modules/Loadable/Models/qSlicerModelsModule]&lt;br /&gt;
&lt;br /&gt;
== How to load files programmatically ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerCoreIOManager.html qSlicerCoreIOManager]* coreIOManager = qSlicerCoreApplication::application()-&amp;gt;coreIOManager();&lt;br /&gt;
 qSlicerIO::IOProperties fileParameters;&lt;br /&gt;
 fileParameters[&amp;quot;fileName&amp;quot;] = &amp;quot;/path/of/file.ext&amp;quot;;&lt;br /&gt;
 vtkMRMLNode* volumeNode = coreIOManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerCoreIOManager.html#a36a78dba553b52f395f997fe11aaff23 loadNodesAndGetFirst](&amp;quot;VolumeFile&amp;quot;, fileParameters);&lt;br /&gt;
Works also with &amp;quot;ModelFile&amp;quot;, &amp;quot;TransformFile&amp;quot;, &amp;quot;SceneFile&amp;quot;...&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; volumeNode = slicer.util.loadVolume('/path/of/file.ext')&lt;br /&gt;
It works also with loadModel, loadTransform, loadScene...&lt;br /&gt;
|}&lt;br /&gt;
Note that [[#IO_Dialogs|IO dialogs]] should be used as often as possible.&lt;br /&gt;
&lt;br /&gt;
=Write=&lt;br /&gt;
The mechanism is similar to '''Read'''. &amp;lt;code&amp;gt;vtkMRMLXYZStorageNode::WriteDataInternal(...)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;qSlicerXYZWriter&amp;lt;/code&amp;gt; must implemented.&lt;br /&gt;
&lt;br /&gt;
== How to save files programmatically ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerCoreIOManager.html qSlicerCoreIOManager]* coreIOManager = qSlicerCoreApplication::application()-&amp;gt;coreIOManager();&lt;br /&gt;
 qSlicerIO::IOProperties fileParameters;&lt;br /&gt;
 fileParameters[&amp;quot;nodeID&amp;quot;] = volumeNode-&amp;gt;GetID();&lt;br /&gt;
 fileParameters[&amp;quot;fileName&amp;quot;] = &amp;quot;/path/of/file.ext&amp;quot;;&lt;br /&gt;
 coreIOManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerCoreIOManager.html#a1cd29140ded984afdd0f667064d38845 saveNodes](&amp;quot;VolumeFile&amp;quot;, fileParameters);&lt;br /&gt;
Works also with &amp;quot;ModelFile&amp;quot;, &amp;quot;TransformFile&amp;quot;, &amp;quot;SceneFile&amp;quot;...&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; slicer.util.saveNode(volumeNode, '/path/of/file.ext')&lt;br /&gt;
|}&lt;br /&gt;
Note that [[#IO_Dialogs|IO dialogs]] should be used as often as possible.&lt;br /&gt;
&lt;br /&gt;
=IO Dialogs=&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerFileDialog.html qSlicerFileDialog]&amp;lt;/code&amp;gt; is the base class to override a custom dialog.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerStandardFileDialog.html qSlicerStandardFileDialog]&amp;lt;/code&amp;gt; is a multi-purpose file dialog.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerDataDialog.html qSlicerDataDialog.h]&amp;lt;/code&amp;gt; is the default dialog to load files.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerSaveDataDialog.html qSlicerSaveDataDialog]&amp;lt;/code&amp;gt; is the default dialog to save files.&lt;br /&gt;
&lt;br /&gt;
By default, all the IOs must be done through &amp;lt;code&amp;gt;qSlicerDataDialog&amp;lt;/code&amp;gt; for reading files and &amp;lt;code&amp;gt;qSlicerSaveDataDialog&amp;lt;/code&amp;gt; for writing files. However, due to historical reasons, it is possible to have custom dialogs for each node types.&lt;br /&gt;
&lt;br /&gt;
It can be useful to create your own IO dialog to add custom behavior to the Slicer drag&amp;amp;drop default behavior.&lt;br /&gt;
== How to register a dialog ? ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
Register dialogs in qSlicerXYZModule::[http://slicer.org/doc/html/classqSlicerAbstractCoreModule.html#a9ad37e756338e7226f157b4eb54b9bcd setup()]:&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerIOManager.html qSlicerIOManager]* ioManager = qSlicerApplication::application()-&amp;gt;ioManager();&lt;br /&gt;
 ioManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerIOManager.html#ae47e9cf27f230335b865bce84a56e156 registerDialog](new qSlicerXYZDialog(this));&lt;br /&gt;
 ioManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerIOManager.html#ae47e9cf27f230335b865bce84a56e156 registerDialog](new qSlicerSaveXYZDialog(this));&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
Declare an XYZFileDialog in your XYZ.py module file. It will be automatically registered. For example:&lt;br /&gt;
 class XYZFileDialog:&lt;br /&gt;
   def __init__(self, parent):&lt;br /&gt;
     self.parent = parent&lt;br /&gt;
     parent.fileType = 'XYZFile'&lt;br /&gt;
     parent.description = 'XYZ'&lt;br /&gt;
     parent.action = slicer.qSlicerFileDialog.Read&lt;br /&gt;
   def isMimeDataAccepted(self):&lt;br /&gt;
     accept = self.parent.mimeData().hasFormat(&amp;quot;text/uri-list&amp;quot;)&lt;br /&gt;
     self.parent.acceptMimeData(accept)&lt;br /&gt;
   def dropEvent(self):&lt;br /&gt;
     self.parent.dropEvent().accept()&lt;br /&gt;
   def execDialog(self):&lt;br /&gt;
     print 'exec' &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== How to open a registered a dialog ? ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerIOManager.html qSlicerIOManager]* ioManager = qSlicerApplication::application()-&amp;gt;ioManager();&lt;br /&gt;
 ioManager-&amp;gt;openDialog(&amp;quot;VolumeFile&amp;quot;, qSlicerFileDialog::Read, qSlicerIO::IOProperties());&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
  io = slicer.app.ioManager()&lt;br /&gt;
  params = {}&lt;br /&gt;
  io.openDialog(&amp;quot;VolumeFile&amp;quot;, slicer.qSlicerFileDialog.Read, params)&lt;br /&gt;
And the special case for standard data file types:&lt;br /&gt;
 slicer.util.openAddVolumeDialog()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== How to order the list of drag&amp;amp;drop dialogs ?==&lt;br /&gt;
By controlling the order of module initialization. This is done by adding module dependencies. Make your module dependent of of the &amp;quot;Data&amp;quot; would make it initialize after the Data module that registers the &amp;quot;Any Data&amp;quot; dialogs:&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 QStringList qSlicerXYZModule::dependencies() const&lt;br /&gt;
 {&lt;br /&gt;
   QStringList moduleDependencies;&lt;br /&gt;
   moduleDependencies &amp;lt;&amp;lt; &amp;quot;Data&amp;quot;;&lt;br /&gt;
   return moduleDependencies;&lt;br /&gt;
 }&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 def __init__(self, parent):&lt;br /&gt;
   ...&lt;br /&gt;
   parent.dependencies = [&amp;quot;Data&amp;quot;] class XYZFileDialog:&lt;br /&gt;
   ...&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Arankin</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/IO&amp;diff=59244</id>
		<title>Documentation/Nightly/Developers/IO</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/IO&amp;diff=59244"/>
		<updated>2018-08-01T13:46:06Z</updated>

		<summary type="html">&lt;p&gt;Arankin: /* Main classes */ Updating class names to match current naming scheme&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
=Read=&lt;br /&gt;
[[Image:IOOverview.png|600px|center]]&lt;br /&gt;
== Main classes ==&lt;br /&gt;
* &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;Node&amp;lt;/code&amp;gt; is a [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLStorableNode.h?view=markup storable node] that represents the data from file (e.g. [[http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLModelNode.h?view=markup vtkMRMLModelNode])&lt;br /&gt;
* &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode&amp;lt;/code&amp;gt; is the file reader. It populates the storable node using the method  &amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode::ReadData(vtkMRMLStorableNode*,bool)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sLogic&amp;lt;/code&amp;gt; is the MRML logic of the &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; module. It exposes a convenient method &amp;lt;code&amp;gt;AddXYZ(const char* fileName, const char* nodeName=0);&amp;lt;/code&amp;gt; that creates a MRML &amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt; node (&amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;Node&amp;lt;/code&amp;gt;)and its associated storage node (&amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode&amp;lt;/code&amp;gt;), add them into the scene, and call &amp;lt;code&amp;gt;vtkMRML&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;StorageNode::ReadData(vtkMRMLStorableNode*,bool);&amp;lt;/code&amp;gt; on the storage node to load the file. If the loading fails, it removes the previously created nodes from the scene.&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sReaderPlugin&amp;lt;/code&amp;gt; is a plugin that is registered by modules into the &amp;lt;code&amp;gt;qSlicerCoreIOManager&amp;lt;/code&amp;gt;. It is the interface between Qt and MRML logics. It internally calls &amp;lt;code&amp;gt;vtkSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sLogic::Add&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;&amp;lt;/code&amp;gt;().&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicer&amp;lt;i&amp;gt;XYZ&amp;lt;/i&amp;gt;sOptionsWidget&amp;lt;/code&amp;gt; is a widget that sets loading options that gets passed to the logic.&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicerCoreIOManager&amp;lt;/code&amp;gt; is the central class where any IO operation must go through. qSlicerIOs can be registered using &amp;lt;code&amp;gt;qSlicerCoreIOManager::registerIO(qSlicerIO*)&amp;lt;/code&amp;gt; and nodes can be loaded using &amp;lt;code&amp;gt;qSlicerCoreIOManager::loadNodes(...)&amp;lt;/code&amp;gt;. It exposes a set of convenient methods such as &amp;quot;what reader must be used for what file&amp;quot;.&lt;br /&gt;
* &amp;lt;code&amp;gt;qSlicerDataDialog&amp;lt;/code&amp;gt; is the dialog that allows the user to select the files to load.&lt;br /&gt;
&lt;br /&gt;
==How to add support for reading a new file format ?==&lt;br /&gt;
# Write method &amp;lt;code&amp;gt;vtkMRMLXYZStorageNode::ReadDataInternal(vtkMRMLStorableNode*, bool temporary);&amp;lt;/code&amp;gt;&lt;br /&gt;
# Write method &amp;lt;code&amp;gt;vtkMRMLXYZsLogic::AddXYZ(const char* fileName, const char nodeName =0);&amp;lt;/code&amp;gt;&lt;br /&gt;
# Write class &amp;lt;code&amp;gt;qSlicerXYZsIO&amp;lt;/code&amp;gt;&lt;br /&gt;
# Optional: Write class &amp;lt;code&amp;gt;qSlicerXYZsIOOptionsWidget&amp;lt;/code&amp;gt; if you want the user to optionally specify loading options.&lt;br /&gt;
# In &amp;lt;code&amp;gt;qSlicerXYZsModule::setup()&amp;lt;/code&amp;gt;, instantiate and register &amp;lt;code&amp;gt;qSlicerXYZsIO&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;qSlicerCoreIOManager&amp;lt;/code&amp;gt;&lt;br /&gt;
# Add file format to [Documentation/{{documentation/version}}/SlicerApplication/SupportedDataFormat|SupportedDataFormat] wiki page&lt;br /&gt;
&lt;br /&gt;
== ModifiedSinceRead ==&lt;br /&gt;
In order to inform the user what data has been changed since it was last read, a ModifiedSinceRead mechanism is in place to track when was the file last read and when was the data last modified. If a modification happened , the storable node &amp;lt;code&amp;gt;vtkMRMLStorableNode::GetModifiedSinceRead()&amp;lt;/code&amp;gt; must return true. If the data in the node is the same as in the file, then &amp;lt;code&amp;gt;vtkMRMLStorableNode::GetModifiedSinceRead()&amp;lt;/code&amp;gt; must return false.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;vtkMRMLStorageNode&amp;lt;/code&amp;gt; keeps track of when a file was last read or written (&amp;lt;code&amp;gt;vtkTimeStamp* vtkMRMLStorageNode::StoredTime&amp;lt;/code&amp;gt;). &amp;lt;code&amp;gt;vtkMRMLStorableNode&amp;lt;/code&amp;gt; keeps track of when the data was last modified (&amp;lt;code&amp;gt;vtkTimeStamp vtkMRMLStorableNode::StorableModifiedTime&amp;lt;/code&amp;gt;). Anytime a &amp;lt;code&amp;gt;vtkMRMLStorableNode&amp;lt;/code&amp;gt; property that is saved in file is modified, the &amp;lt;code&amp;gt;StorableModifiedTime&amp;lt;/code&amp;gt; time stamp must be modified.&lt;br /&gt;
&lt;br /&gt;
At exit time (&amp;lt;code&amp;gt;qSlicerMainWindow::closeEvent()&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;vtkMRMLStorableNode::GetModifiedSinceRead()&amp;lt;/code&amp;gt; is called to check if the data in the node is the same as in the file or if it has been modified after the file was last read or written. It internally checks &amp;lt;code&amp;gt;vtkTimeStamp* vtkMRMLStorageNode::StoredTime&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;vtkTimeStamp vtkMRMLStorableNode::StorableModifiedTime&amp;lt;/code&amp;gt;. If the data is more recent, then a message dialog is shown to the user telling him that some data is different from file; leaving without saving will lose the changes.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
* Models &lt;br /&gt;
** [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLModelNode.h?view=markup Libs/MRML/Core/vtkMRMLModelNode]&lt;br /&gt;
** [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Core/vtkMRMLModelStorageNode.h?view=markup Libs/MRML/Core/vtkMRMLModelStorageNode]&lt;br /&gt;
** [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Modules/Loadable/Models/Logic/vtkSlicerModelsLogic.h?view=markup Modules/Loadable/Models/Logic/vtkSlicerModelsLogic]&lt;br /&gt;
** [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Modules/Loadable/Models/qSlicerModelsIO.h?view=markup Modules/Loadable/Models/qSlicerModelsIO]&lt;br /&gt;
** [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Modules/Loadable/Models/qSlicerModelsModule.h?view=markup Modules/Loadable/Models/qSlicerModelsModule]&lt;br /&gt;
&lt;br /&gt;
== How to load files programmatically ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerCoreIOManager.html qSlicerCoreIOManager]* coreIOManager = qSlicerCoreApplication::application()-&amp;gt;coreIOManager();&lt;br /&gt;
 qSlicerIO::IOProperties fileParameters;&lt;br /&gt;
 fileParameters[&amp;quot;fileName&amp;quot;] = &amp;quot;/path/of/file.ext&amp;quot;;&lt;br /&gt;
 vtkMRMLNode* volumeNode = coreIOManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerCoreIOManager.html#a36a78dba553b52f395f997fe11aaff23 loadNodesAndGetFirst](&amp;quot;VolumeFile&amp;quot;, fileParameters);&lt;br /&gt;
Works also with &amp;quot;ModelFile&amp;quot;, &amp;quot;TransformFile&amp;quot;, &amp;quot;SceneFile&amp;quot;...&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; volumeNode = slicer.util.loadVolume('/path/of/file.ext')&lt;br /&gt;
It works also with loadModel, loadTransform, loadScene...&lt;br /&gt;
|}&lt;br /&gt;
Note that [[#IO_Dialogs|IO dialogs]] should be used as often as possible.&lt;br /&gt;
&lt;br /&gt;
=Write=&lt;br /&gt;
The mechanism is similar to '''Read'''. &amp;lt;code&amp;gt;vtkMRMLXYZStorageNode::WriteDataInternal(...)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;qSlicerXYZWriter&amp;lt;/code&amp;gt; must implemented.&lt;br /&gt;
&lt;br /&gt;
== How to save files programmatically ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerCoreIOManager.html qSlicerCoreIOManager]* coreIOManager = qSlicerCoreApplication::application()-&amp;gt;coreIOManager();&lt;br /&gt;
 qSlicerIO::IOProperties fileParameters;&lt;br /&gt;
 fileParameters[&amp;quot;nodeID&amp;quot;] = volumeNode-&amp;gt;GetID();&lt;br /&gt;
 fileParameters[&amp;quot;fileName&amp;quot;] = &amp;quot;/path/of/file.ext&amp;quot;;&lt;br /&gt;
 coreIOManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerCoreIOManager.html#a1cd29140ded984afdd0f667064d38845 saveNodes](&amp;quot;VolumeFile&amp;quot;, fileParameters);&lt;br /&gt;
Works also with &amp;quot;ModelFile&amp;quot;, &amp;quot;TransformFile&amp;quot;, &amp;quot;SceneFile&amp;quot;...&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; slicer.util.saveNode(volumeNode, '/path/of/file.ext')&lt;br /&gt;
|}&lt;br /&gt;
Note that [[#IO_Dialogs|IO dialogs]] should be used as often as possible.&lt;br /&gt;
&lt;br /&gt;
=IO Dialogs=&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerFileDialog.html qSlicerFileDialog]&amp;lt;/code&amp;gt; is the base class to override a custom dialog.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerStandardFileDialog.html qSlicerStandardFileDialog]&amp;lt;/code&amp;gt; is a multi-purpose file dialog.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerDataDialog.html qSlicerDataDialog.h]&amp;lt;/code&amp;gt; is the default dialog to load files.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://slicer.org/doc/html/classqSlicerSaveDataDialog.html qSlicerSaveDataDialog]&amp;lt;/code&amp;gt; is the default dialog to save files.&lt;br /&gt;
&lt;br /&gt;
By default, all the IOs must be done through &amp;lt;code&amp;gt;qSlicerDataDialog&amp;lt;/code&amp;gt; for reading files and &amp;lt;code&amp;gt;qSlicerSaveDataDialog&amp;lt;/code&amp;gt; for writing files. However, due to historical reasons, it is possible to have custom dialogs for each node types.&lt;br /&gt;
&lt;br /&gt;
It can be useful to create your own IO dialog to add custom behavior to the Slicer drag&amp;amp;drop default behavior.&lt;br /&gt;
== How to register a dialog ? ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
Register dialogs in qSlicerXYZModule::[http://slicer.org/doc/html/classqSlicerAbstractCoreModule.html#a9ad37e756338e7226f157b4eb54b9bcd setup()]:&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerIOManager.html qSlicerIOManager]* ioManager = qSlicerApplication::application()-&amp;gt;ioManager();&lt;br /&gt;
 ioManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerIOManager.html#ae47e9cf27f230335b865bce84a56e156 registerDialog](new qSlicerXYZDialog(this));&lt;br /&gt;
 ioManager-&amp;gt;[http://slicer.org/doc/html/classqSlicerIOManager.html#ae47e9cf27f230335b865bce84a56e156 registerDialog](new qSlicerSaveXYZDialog(this));&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
Declare an XYZFileDialog in your XYZ.py module file. It will be automatically registered. For example:&lt;br /&gt;
 class XYZFileDialog:&lt;br /&gt;
   def __init__(self, parent):&lt;br /&gt;
     self.parent = parent&lt;br /&gt;
     parent.fileType = 'XYZFile'&lt;br /&gt;
     parent.description = 'XYZ'&lt;br /&gt;
     parent.action = slicer.qSlicerFileDialog.Read&lt;br /&gt;
   def isMimeDataAccepted(self):&lt;br /&gt;
     accept = self.parent.mimeData().hasFormat(&amp;quot;text/uri-list&amp;quot;)&lt;br /&gt;
     self.parent.acceptMimeData(accept)&lt;br /&gt;
   def dropEvent(self):&lt;br /&gt;
     self.parent.dropEvent().accept()&lt;br /&gt;
   def execDialog(self):&lt;br /&gt;
     print 'exec' &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== How to open a registered a dialog ? ==&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 [http://slicer.org/doc/html/classqSlicerIOManager.html qSlicerIOManager]* ioManager = qSlicerApplication::application()-&amp;gt;ioManager();&lt;br /&gt;
 ioManager-&amp;gt;openDialog(&amp;quot;VolumeFile&amp;quot;, qSlicerFileDialog::Read, qSlicerIO::IOProperties());&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
  io = slicer.app.ioManager()&lt;br /&gt;
  params = {}&lt;br /&gt;
  io.openDialog(&amp;quot;VolumeFile&amp;quot;, slicer.qSlicerFileDialog.Read, params)&lt;br /&gt;
And the special case for standard data file types:&lt;br /&gt;
 slicer.util.openAddVolumeDialog()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== How to order the list of drag&amp;amp;drop dialogs ?==&lt;br /&gt;
By controlling the order of module initialization. This is done by adding module dependencies. Make your module dependent of of the &amp;quot;Data&amp;quot; would make it initialize after the Data module that registers the &amp;quot;Any Data&amp;quot; dialogs:&lt;br /&gt;
{|width = &amp;quot;100%&amp;quot;&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|C++&lt;br /&gt;
! style=&amp;quot;border-bottom: 1px solid darkgrey;font-size: 75%;&amp;quot;|Python&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 QStringList qSlicerXYZModule::dependencies() const&lt;br /&gt;
 {&lt;br /&gt;
   QStringList moduleDependencies;&lt;br /&gt;
   moduleDependencies &amp;lt;&amp;lt; &amp;quot;Data&amp;quot;;&lt;br /&gt;
   return moduleDependencies;&lt;br /&gt;
 }&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; |&lt;br /&gt;
 def __init__(self, parent):&lt;br /&gt;
   ...&lt;br /&gt;
   parent.dependencies = [&amp;quot;Data&amp;quot;] class XYZFileDialog:&lt;br /&gt;
   ...&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Arankin</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&amp;diff=58769</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=58769"/>
		<updated>2018-03-19T20:08:57Z</updated>

		<summary type="html">&lt;p&gt;Arankin: Adding slice viewer examples&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;
==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;
* 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;
==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;
==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;
== 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;
== 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 fiber tracts to Blender, including color ==&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;
== 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 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;
== Manipulate a Slice View ==&lt;br /&gt;
&lt;br /&gt;
=== Change the slice offset ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lm = slicer.app.layoutManager()&lt;br /&gt;
red = lm.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;
=== Iterate over current visible slice views, and modify 3D visibility ===&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;
     &lt;br /&gt;
     controller = sliceWidget.sliceController()&lt;br /&gt;
     controller.setSliceVisible(True)&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;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for sliceViewName in layoutManager.sliceViewNames():&lt;br /&gt;
     sliceWidget = layoutManager.sliceWidget(sliceViewName)&lt;br /&gt;
     &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;
== 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;
== Show a volume in the Slice Views ==&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;
&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 the Slice Views ==&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;
== 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;
== 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;
== 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;
== 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;
=== 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;
=== 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;
== 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;/div&gt;</summary>
		<author><name>Arankin</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/Tutorials/QtDesigner&amp;diff=58258</id>
		<title>Documentation/Nightly/Developers/Tutorials/QtDesigner</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/Tutorials/QtDesigner&amp;diff=58258"/>
		<updated>2018-01-23T01:12:16Z</updated>

		<summary type="html">&lt;p&gt;Arankin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
=Using custom widgets in Qt Designer=&lt;br /&gt;
==Straight to the point==&lt;br /&gt;
*Windows&lt;br /&gt;
**Compile Slicer in Release mode OR build Qt in Debug&lt;br /&gt;
*All&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd Slicer-build;&lt;br /&gt;
./Slicer --designer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the option &amp;lt;code&amp;gt;--designer&amp;lt;/code&amp;gt; is not available, you should consider using QtCreator. See [[Documentation/{{documentation/version}}/Developers/Tutorials/QtCreator|here]] for more details.&lt;br /&gt;
&lt;br /&gt;
==Qt Designer requirements==&lt;br /&gt;
In order to have the CTK and MRML widgets in Qt Designer, Qt Designer offers 2 options:&lt;br /&gt;
*the first (not detailed here) is to copy (or symlink) the CTK and MRML plugin libraries into &amp;lt;i&amp;gt;%QT_DIR%/plugins/designer&amp;lt;/i&amp;gt;,&lt;br /&gt;
*the second is to set the environment variable &amp;lt;code&amp;gt;QT_PLUGIN_PATH&amp;lt;/code&amp;gt; to the directory &amp;lt;i&amp;gt;Slicer-build/bin&amp;lt;/i&amp;gt; containing the subdirectory &amp;lt;i&amp;gt;designer&amp;lt;/i&amp;gt; with the plugin libraries.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Qt requires that the directory containing the designer plugins is named &amp;quot;designer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Consider reading the [http://doc.qt.nokia.com/{{documentation/{{documentation/version}}/qtversion}}/designer-manual.html Qt Designer documentation].&lt;br /&gt;
If the widgets do not appear in Qt Designer, then open the &amp;quot;Help -&amp;gt; About Plugin&amp;quot; dialog and report the error associated to the plugin dll.&lt;br /&gt;
&lt;br /&gt;
=== Windows notes ===&lt;br /&gt;
On Windows, Qt Designer can only load plugins that have been compiled in the same build mode than Qt Designer. For example, if Qt is built in Debug mode, the plugins must also be built in Debug mode to be loaded by Qt Designer.&amp;lt;br&amp;gt;&lt;br /&gt;
If Qt is configured to build in both debug and release modes, Qt Designer is built in release mode only. If that case, it is necessary to ensure that plugins are also built in release mode. Otherwise, you can open the solution file for Qt, and recompile Designer in debug mode.&lt;br /&gt;
&lt;br /&gt;
==Running Qt Designer with the correct environment variables==&lt;br /&gt;
*On Windows, compile Slicer in the same build mode than Qt. If Qt is in Debug mode, compile Slicer in Debug mode, if it's in Release or Debug&amp;amp;Release mode, compile Slicer in Release mode.&lt;br /&gt;
*run Qt Designer via Slicer launcher located in &amp;lt;i&amp;gt;Slicer-build&amp;lt;/i&amp;gt;.&lt;br /&gt;
{| style=&amp;quot;border: 1px solid darkgray;&amp;quot;&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Mac Os X&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Linux&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Windows&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|&lt;br /&gt;
 $ cd Slicer-build&lt;br /&gt;
 $ ./Slicer --designer&lt;br /&gt;
|&lt;br /&gt;
 &amp;gt; cd Slicer-build&lt;br /&gt;
 &amp;gt; .\Slicer.exe --designer&lt;br /&gt;
|}&lt;br /&gt;
If the option &amp;lt;code&amp;gt;--designer&amp;lt;/code&amp;gt; is not available, you should consider using QtCreator. See [[Documentation/{{documentation/version}}/Developers/Tutorials/QtCreator|here]] for more details.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[Image:Screenshot-Qt Designer.png|thumb|300px|Qt Desginer loaded with CTKWidgets and qMRMLWidgets]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Build Slicer==&lt;br /&gt;
* Once you are satisfied with UI, save the file, quit Designer and build Slicer to take the changes into account.&lt;br /&gt;
{| style=&amp;quot;border: 1px solid darkgray;&amp;quot;&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Mac Os X&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Linux&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Windows&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|&lt;br /&gt;
 $ make -j4&lt;br /&gt;
or just build the related project&lt;br /&gt;
 $ make -j4 qSlicerMY_MODULE_NAMEModuleWidget&lt;br /&gt;
| Open the inner solution file ''...Slicer-Superbuild\Slicer-build\Slicer.sln'' and build the solution (F7) or build project &amp;lt;code&amp;gt;qSlicerMY_MODULE_NAMEModuleWidgets&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
It generates a ''ui_qSlicerMY_MODULE_NAMEModule.h'' file in ''...Slicer-Superbuild/Slicer-buildModules/Loadable/MY_MODULE_NAME/''. &lt;br /&gt;
&lt;br /&gt;
That file is used by ''...Slicer4/Modules/Loadable/MY_MODULE_NAME/qSlicerMY_MODULE_NAMEModuleWidget.cxx''.&lt;br /&gt;
&lt;br /&gt;
Note: The &amp;lt;code&amp;gt;objectName&amp;lt;/code&amp;gt;s of each widget in the UI correspond (see the Property editor) to the variable names in C++. From your code, you can access the widgets by their objectName. &lt;br /&gt;
* And launch Slicer to see the result&lt;br /&gt;
{| style=&amp;quot;border: 1px solid darkgray;&amp;quot;&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Mac Os X&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Linux&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Windows&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|&amp;lt;pre&amp;gt;$ ./Slicer&amp;lt;/pre&amp;gt;&lt;br /&gt;
| &amp;lt;pre&amp;gt;&amp;gt; .\Slicer.exe&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
* My [http://slicer.org/doc/html/classqMRMLNodeComboBox.html qMRMLNodeComboBox] widget is always disabled (gray) in my module.&lt;br /&gt;
To be enabled, qMRMLNodeComboBox needs a MRML scene. You can set a MRML scene to the combobox programmatically or directly from Qt Designer. Doing it in Qt Designer is the recommended way, to do so you need to be in [http://doc.qt.io/qt-5/designer-connection-mode.html Connection mode] and connect the signal [http://slicer.org/doc/html/classqSlicerWidget.html#a9c28318f7810ccce517ea7a1b0051da4 mrmlSceneChanged(vtkMRMLScene*)] of the module panel (of type [http://slicer.org/doc/html/classqSlicerWidget.html qSlicerWidget]) with the slot [http://slicer.org/doc/html/classqMRMLNodeComboBox.html#a2249be3ccec4783b592f738f1ef7bea3 setMRMLScene(vtkMRMLScene*)].&lt;br /&gt;
The programmatic connection can be done in the &amp;lt;code&amp;gt;setup()&amp;lt;/code&amp;gt; method of the module widget (or &amp;lt;code&amp;gt;init()&amp;lt;/code&amp;gt; of the module widget pimpl):&lt;br /&gt;
 void qSlicerDataModuleWidget::setup()&lt;br /&gt;
 {&lt;br /&gt;
 ...&lt;br /&gt;
 connect(this, SIGNAL(mrmlSceneChanged(vtkMRMLScene*)),&lt;br /&gt;
         myWidget, SLOT(setMRMLScene(vtkMRMLScene*)));&lt;br /&gt;
 ...&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>Arankin</name></author>
		
	</entry>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/Tutorials/QtDesigner&amp;diff=58255</id>
		<title>Documentation/Nightly/Developers/Tutorials/QtDesigner</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/Tutorials/QtDesigner&amp;diff=58255"/>
		<updated>2018-01-23T01:11:41Z</updated>

		<summary type="html">&lt;p&gt;Arankin: Updating link to connection mode documentation for Qt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation/versioncheck}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
=Using custom widgets in Qt Designer=&lt;br /&gt;
==Straight to the point==&lt;br /&gt;
*Windows&lt;br /&gt;
**Compile Slicer in Release mode OR build Qt in Debug&lt;br /&gt;
*All&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd Slicer-build;&lt;br /&gt;
./Slicer --designer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the option &amp;lt;code&amp;gt;--designer&amp;lt;/code&amp;gt; is not available, you should consider using QtCreator. See [[Documentation/{{documentation/version}}/Developers/Tutorials/QtCreator|here]] for more details.&lt;br /&gt;
&lt;br /&gt;
==Qt Designer requirements==&lt;br /&gt;
In order to have the CTK and MRML widgets in Qt Designer, Qt Designer offers 2 options:&lt;br /&gt;
*the first (not detailed here) is to copy (or symlink) the CTK and MRML plugin libraries into &amp;lt;i&amp;gt;%QT_DIR%/plugins/designer&amp;lt;/i&amp;gt;,&lt;br /&gt;
*the second is to set the environment variable &amp;lt;code&amp;gt;QT_PLUGIN_PATH&amp;lt;/code&amp;gt; to the directory &amp;lt;i&amp;gt;Slicer-build/bin&amp;lt;/i&amp;gt; containing the subdirectory &amp;lt;i&amp;gt;designer&amp;lt;/i&amp;gt; with the plugin libraries.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Qt requires that the directory containing the designer plugins is named &amp;quot;designer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Consider reading the [http://doc.qt.nokia.com/{{documentation/{{documentation/version}}/qtversion}}/designer-manual.html Qt Designer documentation].&lt;br /&gt;
If the widgets do not appear in Qt Designer, then open the &amp;quot;Help -&amp;gt; About Plugin&amp;quot; dialog and report the error associated to the plugin dll.&lt;br /&gt;
&lt;br /&gt;
=== Windows notes ===&lt;br /&gt;
On Windows, Qt Designer can only load plugins that have been compiled in the same build mode than Qt Designer. For example, if Qt is built in Debug mode, the plugins must also be built in Debug mode to be loaded by Qt Designer.&amp;lt;br&amp;gt;&lt;br /&gt;
If Qt is configured to build in both debug and release modes, Qt Designer is built in release mode only. If that case, it is necessary to ensure that plugins are also built in release mode. Otherwise, you can open the solution file for Qt, and recompile Designer in debug mode.&lt;br /&gt;
&lt;br /&gt;
==Running Qt Designer with the correct environment variables==&lt;br /&gt;
*On Windows, compile Slicer in the same build mode than Qt. If Qt is in Debug mode, compile Slicer in Debug mode, if it's in Release or Debug&amp;amp;Release mode, compile Slicer in Release mode.&lt;br /&gt;
*run Qt Designer via Slicer launcher located in &amp;lt;i&amp;gt;Slicer-build&amp;lt;/i&amp;gt;.&lt;br /&gt;
{| style=&amp;quot;border: 1px solid darkgray;&amp;quot;&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Mac Os X&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Linux&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Windows&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|&lt;br /&gt;
 $ cd Slicer-build&lt;br /&gt;
 $ ./Slicer --designer&lt;br /&gt;
|&lt;br /&gt;
 &amp;gt; cd Slicer-build&lt;br /&gt;
 &amp;gt; .\Slicer.exe --designer&lt;br /&gt;
|}&lt;br /&gt;
If the option &amp;lt;code&amp;gt;--designer&amp;lt;/code&amp;gt; is not available, you should consider using QtCreator. See [[Documentation/{{documentation/version}}/Developers/Tutorials/QtCreator|here]] for more details.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[Image:Screenshot-Qt Designer.png|thumb|300px|Qt Desginer loaded with CTKWidgets and qMRMLWidgets]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Build Slicer==&lt;br /&gt;
* Once you are satisfied with UI, save the file, quit Designer and build Slicer to take the changes into account.&lt;br /&gt;
{| style=&amp;quot;border: 1px solid darkgray;&amp;quot;&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Mac Os X&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Linux&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Windows&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|&lt;br /&gt;
 $ make -j4&lt;br /&gt;
or just build the related project&lt;br /&gt;
 $ make -j4 qSlicerMY_MODULE_NAMEModuleWidget&lt;br /&gt;
| Open the inner solution file ''...Slicer-Superbuild\Slicer-build\Slicer.sln'' and build the solution (F7) or build project &amp;lt;code&amp;gt;qSlicerMY_MODULE_NAMEModuleWidgets&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
It generates a ''ui_qSlicerMY_MODULE_NAMEModule.h'' file in ''...Slicer-Superbuild/Slicer-buildModules/Loadable/MY_MODULE_NAME/''. &lt;br /&gt;
&lt;br /&gt;
That file is used by ''...Slicer4/Modules/Loadable/MY_MODULE_NAME/qSlicerMY_MODULE_NAMEModuleWidget.cxx''.&lt;br /&gt;
&lt;br /&gt;
Note: The &amp;lt;code&amp;gt;objectName&amp;lt;/code&amp;gt;s of each widget in the UI correspond (see the Property editor) to the variable names in C++. From your code, you can access the widgets by their objectName. &lt;br /&gt;
* And launch Slicer to see the result&lt;br /&gt;
{| style=&amp;quot;border: 1px solid darkgray;&amp;quot;&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Mac Os X&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Linux&lt;br /&gt;
!align=left style=&amp;quot;border-bottom: 1px solid grey;&amp;quot;|Windows&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|&amp;lt;pre&amp;gt;$ ./Slicer&amp;lt;/pre&amp;gt;&lt;br /&gt;
| &amp;lt;pre&amp;gt;&amp;gt; .\Slicer.exe&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
* My [http://slicer.org/doc/html/classqMRMLNodeComboBox.html qMRMLNodeComboBox] widget is always disabled (gray) in my module.&lt;br /&gt;
To be enabled, qMRMLNodeComboBox needs a MRML scene. You can set a MRML scene to the combobox programmatically or directly from Qt Designer. Doing it in Qt Designer is the recommended way, to do so you need to be in [http://doc.qt.io/archives/qt-4.8/designer-connection-mode.html Connection mode] and connect the signal [http://slicer.org/doc/html/classqSlicerWidget.html#a9c28318f7810ccce517ea7a1b0051da4 mrmlSceneChanged(vtkMRMLScene*)] of the module panel (of type [http://slicer.org/doc/html/classqSlicerWidget.html qSlicerWidget]) with the slot [http://slicer.org/doc/html/classqMRMLNodeComboBox.html#a2249be3ccec4783b592f738f1ef7bea3 setMRMLScene(vtkMRMLScene*)].&lt;br /&gt;
The programmatic connection can be done in the &amp;lt;code&amp;gt;setup()&amp;lt;/code&amp;gt; method of the module widget (or &amp;lt;code&amp;gt;init()&amp;lt;/code&amp;gt; of the module widget pimpl):&lt;br /&gt;
 void qSlicerDataModuleWidget::setup()&lt;br /&gt;
 {&lt;br /&gt;
 ...&lt;br /&gt;
 connect(this, SIGNAL(mrmlSceneChanged(vtkMRMLScene*)),&lt;br /&gt;
         myWidget, SLOT(setMRMLScene(vtkMRMLScene*)));&lt;br /&gt;
 ...&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>Arankin</name></author>
		
	</entry>
</feed>