<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.slicer.org/w/index.php?action=history&amp;feed=atom&amp;title=Documentation%2F4.5%2FDevelopers%2FFAQ%2FPython_Scripting</id>
	<title>Documentation/4.5/Developers/FAQ/Python Scripting - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.slicer.org/w/index.php?action=history&amp;feed=atom&amp;title=Documentation%2F4.5%2FDevelopers%2FFAQ%2FPython_Scripting"/>
	<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/4.5/Developers/FAQ/Python_Scripting&amp;action=history"/>
	<updated>2026-05-05T00:17:51Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.33.0</generator>
	<entry>
		<id>https://www.slicer.org/w/index.php?title=Documentation/4.5/Developers/FAQ/Python_Scripting&amp;diff=43607&amp;oldid=prev</id>
		<title>UpdateBot: Nightly -&gt; 4.5</title>
		<link rel="alternate" type="text/html" href="https://www.slicer.org/w/index.php?title=Documentation/4.5/Developers/FAQ/Python_Scripting&amp;diff=43607&amp;oldid=prev"/>
		<updated>2015-11-12T22:04:41Z</updated>

		<summary type="html">&lt;p&gt;Nightly -&amp;gt; 4.5&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&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 systematically execute custom python code at startup ? ==&lt;br /&gt;
&lt;br /&gt;
Each time Slicer starts, it will look up for a file named &amp;lt;code&amp;gt;.slicerrc.py&amp;lt;/code&amp;gt; into your HOME folder.&lt;br /&gt;
&lt;br /&gt;
See [[Documentation/{{documentation/version}}/FAQ/General#What_is_my_HOME_folder_.3F|What is my HOME folder ?]]&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;
&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 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;
* [Other reasons go here]&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 Wrapping\Python\vtk\util\misc.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;
A simplified syntax is available by using a mix-in:&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;
Note: VTKObservationMixin is a Python mix-in that allows adding a set of methods to a class by inheritance. VTKObservationMixin includes addObserver, hasObserver, observer, removeObserver, removeObservers methods, defined in Slicer (in Base\Python\slicer\util.py). For example 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;
== 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;/div&gt;</summary>
		<author><name>UpdateBot</name></author>
		
	</entry>
</feed>