Difference between revisions of "ParaView/Python Scripting"

From KitwarePublic
Jump to navigationJump to search
(better cleanup with gc.collect())
 
(91 intermediate revisions by 17 users not shown)
Line 1: Line 1:
 +
'''Katie O adding to ParaView Guide LaTex'''
 +
 +
Note: This document if based on ParaView 3.6 or higher. If you are using 3.4, go to the history page and select the version from May 13, 2009.
 +
 
=ParaView and Python=
 
=ParaView and Python=
ParaView offers rich scripting support through Python. This support is available as part of the ParaView client (paraview), an MPI-enabled batch application (pvbatch), the ParaView python client (pvpython) or any other Python-enabled application. Using Python, users and developers can gain access to the ParaView engine called Server Manager.
+
ParaView offers rich scripting support through Python. This support is available as part of the ParaView client (paraview), an MPI-enabled batch application (pvbatch), the ParaView python client (pvpython), or any other Python-enabled application. Using Python, users and developers can gain access to the ParaView engine called Server Manager.
 +
 
 +
Note: Server Manager is a library that is designed to make it easy to build distributed client-server applications.
 +
 
 +
This document is a short introduction to ParaView's Python interface. You may also visit the [[Python recipes]] page for some examples.
  
 
=Quick Start - a Tutorial=
 
=Quick Start - a Tutorial=
 
==Getting Started==
 
==Getting Started==
  
To start interacting with the Server Manager, you have to load the servermanager module. This module can be loaded from any python interpreter as long as the necessary files are in PYTHONPATH. These files are the shared libraries located in the paraview binary directory and python modules in the paraview directory: paraview/servermanager.py, paraview/vtk.py etc. You can also use either pvpython (for stand-alone or client/server execution), pvbatch (for non-interactive, distributed batch processing) or the python shell invoked from Tools -> Python Shell using the ParaView client to execute Python scripts. You do not have to set PYTHONPATH when using these.
+
To start interacting with the Server Manager, you have to load the "simple" module. This module can be loaded from any python interpreter as long as the necessary files are in PYTHONPATH. These files are the shared libraries located in the paraview binary directory and python modules in the paraview directory: ''paraview/simple.py'', ''paraview/vtk.py'' etc. You can also use either pvpython (for stand-alone or client/server execution), pvbatch (for non-interactive, distributed batch processing) or the python shell invoked from '''Tools'''|Python Shell using the ParaView client to execute Python scripts. You do not have to set PYTHONPATH when using these.
In this tutorial, I will be using the python integrated development environment IDLE. My PYTHONPATH is set to the following.  
 
  
/Users/berk/work/paraview3-build/bin:/Users/berk/work/paraview3-build/Utilities/VTKPythonWrapping
+
This tutorial will be using the python integrated development environment IDLE. PYTHONPATH is set to the following:  
  
This is on my Mac and using the build tree. In IDLE, let’s start by loading the servermanager module.
+
/Users/berk/work/paraview3-build/lib:/Users/berk/work/paraview3-build/lib/site-packages
  
<source lang="python">
+
Note that depending on your build configuration, your *.libs files may not be under "lib" but under one of its sub-folders, like "lib/Release" or "lib/Debug". In those cases add the correct folder where the *.libs reside:
>>> from paraview import servermanager
+
 
</source>
+
/Users/berk/work/paraview3-build/lib/'''Release''':/Users/berk/work/paraview3-build/lib/site-packages
  
Note: Importing the paraview module directly is deprecated although still possible for backwards compatibility. This document refers to the servermanager module alone. Next, we need to connect to a server if we are not already connected.
+
Note: For older versions of ParaView this was '' /Users/berk/work/paraview3-build/bin:/Users/berk/work/paraview3-build/Utilities/VTKPythonWrapping/site-packages'' --[[User:Andy.bauer|Andy.bauer]] 24 January 2013, or
 +
''/Users/berk/work/paraview3-build/bin:/Users/berk/work/paraview3-build/Utilities/VTKPythonWrapping'' --[[User:Andy.bauer|Andy.bauer]] 23 July 2010.
  
<source lang="python">
+
You may also need to set your path variable for searching for shared libraries (i.e. PATH on Windows and LD_LIBRARY_PATH on Unix/Linux/Mac). The corresponding LD_LIBRARY_PATH would be:
>>> if not servermanager.ActiveConnection:
+
  /Users/berk/work/paraview3-build/lib (/Users/berk/work/paraview3-build/bin for versions before 3.98)
... connection = servermanager.Connect()
 
  
Connection (builtin:5)
+
(Under WindowsXP for a debug build of paraview, set both PATH and PYTHONPATH environment variables to include ${BUILD}/lib/Debug and ${BUILD}/lib/site-packages to make it work.)
</source>
 
  
In this example, we connected to the built-in server. When using pvbatch, this is the only connection mode supported, even when pvbatch is running as an MPI task. When running pvpython or loading servermanager from an external python interpreter, we can also connect to a remote server as shown in the following example
+
When using a Mac to use the build tree in IDLE, start by loading the servermanager module:
  
 
<source lang="python">
 
<source lang="python">
>>> connection = servermanager.Connect('localhost')
+
>>> from paraview.simple import *
Connection (localhost:11111)
 
 
</source>
 
</source>
This assumes that you already started the server (pvserver) on the local machine.
 
Note: Connect() returns a connection object on success and returns None on failure. You might want to check the return value to make sure connection succeeded.
 
  
<source lang="python">
+
Note: Importing the paraview module directly is deprecated, although still possible for backwards compatibility. This document refers to the simple module alone.  
>>> connection = servermanager.Connect('localhost')
+
 
>>> if not connection:
+
In this example, we will use ParaView in the stand-alone mode. Connecting to a ParaView server running on a cluster is covered later in this document.
...  raise exceptions.RuntimeError, “Connection to localhost failed.
 
</source>
 
  
Note: When importing the servermanager module from the application’s python shell, Connect() should not be called as a connection already exists.
+
===Tab-completion===
  
==Creating a Pipeline==
+
The Python shell in the ParaView Qt client provides auto-completion. One can also use IDLE, for example to enable auto-completion. To use auto-completion in pvpython, one can use the tips provided at [http://www.razorvine.net/blog/user/irmen/article/2004-11-22/17].
  
When first loaded, the servermanager module creates several sub-modules that can be used to create a visualization. The most important ones are listed below.
+
In summary, you need to create a variable  PYTHONSTARTUP as (in bash):
* sources
 
* filters
 
* rendering
 
  
You can get a list of classes these modules contain by using dir() as shown in the following example.
+
  export PYTHONSTARTUP = /home/<username>/.pythonrc
  
 +
where .pythonrc is:
 
<source lang="python">
 
<source lang="python">
>>> dir(servermanager.sources)
+
    # ~/.pythonrc
['AVSucdReader', 'ArrowSource', 'Axes', 'CSVReader', 'ConeSource', 'CubeSource', 'CylinderSource',
+
    # enable syntax completion
'DEMReader', 'ExodusIIReader', 'ExodusReader', 'FLUENTReader', 'Facet Reader', 'GlyphSource2D',
+
    try:
'HierarchicalFractal', 'ImageMandelbrotSource', 'ImageReader', ...]
+
        import readline
 +
    except ImportError:
 +
        print "Module readline not available."
 +
    else:
 +
        import rlcompleter
 +
        readline.parse_and_bind("tab: complete")
 
</source>
 
</source>
  
Let’s start by creating a ConeSource object:
+
That is it.  Tab completion works just as in any other shell.
 +
 
 +
==Creating a Pipeline==
 +
 
 +
The simple module contains many functions to instantiate sources, filters, and other related objects. You can get a list of objects this module can create from ParaView's online help (from help menu or here: http://paraview.org/OnlineHelpCurrent/)
 +
 
 +
Start by creating a Cone object:
  
 
<source lang="python">
 
<source lang="python">
>>> coneSource = servermanager.sources.ConeSource()
+
>>> cone = Cone()
 
</source>
 
</source>
  
The object assigned to coneSource is a proxy for the actual vtkConeSource. This proxy provides a set of properties and methods to control the behavior of the underlying VTK object(s). These objects may be in the same process (built-in server) or on one or more server processes (distributed remote server). The proxy will handle communication with the VTK objects in a transparent way. You can get some documentation about the proxy using help().
+
You can get some documentation about the cone object using help().
  
 
<source lang="python">
 
<source lang="python">
>>> help(coneSource)
+
>>> help(cone)
Help on ConeSource in module paraview.servermanager object:
+
Help on Cone in module paraview.servermanager object:
  
class ConeSource(Proxy)
+
class Cone(SourceProxy)
  |  The Cone source can be used to add a polygonal cone to the 3D scene. The output of the Cone source is
+
  |  The Cone source can be used to add a polygonal cone to the 3D scene. The output of the  
polygonal data.
+
Cone source is polygonal data.
 
  |   
 
  |   
 
  |  Method resolution order:
 
  |  Method resolution order:
  |      ConeSource
+
  |      Cone
 +
|      SourceProxy
 
  |      Proxy
 
  |      Proxy
 
  |      __builtin__.object
 
  |      __builtin__.object
Line 88: Line 99:
 
  |  Capping
 
  |  Capping
 
  |      If this property is set to 1, the base of the cone will be capped with a filled polygon.  
 
  |      If this property is set to 1, the base of the cone will be capped with a filled polygon.  
Otherwise, the base of the cone will be open.
+
Otherwise, the base of the cone will be open.
 
  |   
 
  |   
 
  |  Center
 
  |  Center
 
  |      This property specifies the center of the cone.
 
  |      This property specifies the center of the cone.
 +
 +
|  Direction
 +
|      Set the orientation vector of the cone.  The vector does not have to be normalized.  The cone
 +
will point in the direction specified.
 +
 +
|  Height
 +
|      This property specifies the height of the cone.
 +
 +
|  Radius
 +
|      This property specifies the radius of the base of the cone.
 +
 +
|  Resolution
 +
|      This property indicates the number of divisions around the cone. The higher this number, the
 +
closer the polygonal approximation will come to representing a cone, and the more polygons it will
 +
contain.
 +
 
  |...   
 
  |...   
 
</source>
 
</source>
  
This gives you a full list of properties. Let’s check what the resolution property is set to.
+
This gives you a full list of properties. Check what the resolution property is set to:
  
 
<source lang="python">
 
<source lang="python">
>>> coneSource.Resolution
+
>>> cone.Resolution
Property name= Resolution value = 6
+
6
 
</source>
 
</source>
  
You can increase the resolution as shown below.
+
You can increase the resolution as shown below:
  
 
<source lang="python">
 
<source lang="python">
>>> coneSource.Resolution = 32
+
>>> cone.Resolution = 32
 
</source>
 
</source>
  
Alternatively, we could have specified a value for resolution when creating the proxy.
+
Alternatively, we could have specified a value for resolution when creating the object:
  
 
<source lang="python">
 
<source lang="python">
>>> coneSource = servermanager.sources.ConeSource(Resolution=32)
+
>>> cone = Cone(Resolution=32)
 
</source>
 
</source>
  
You can assign values to any number of properties during construction using keyword arguments.
+
You can assign values to any number of properties during construction using keyword arguments:
Let’s also change the center.
+
You can also change the center.
  
 
<source lang="python">
 
<source lang="python">
>>> coneSource.Center
+
>>> cone.Center
Property name= Center value = [0.0, 0.0, 0.0]
+
[0.0, 0.0, 0.0]
>>> coneSource.Center[1] = 1
+
>>> cone.Center = [1, 2, 3]
 
</source>
 
</source>
  
Vector properties such as this one support setting and getting of individual elements as well as slices (ranges of elements).
+
Vector properties such as this one support setting and retrieval of individual elements, as well as slices (ranges of elements):
  
 
<source lang="python">
 
<source lang="python">
>>> coneSource.Center[0:3] = [1, 2, 3]
+
>>> cone.Center[0:2] = [2, 4]
>>> coneSource.Center
+
>>> cone.Center
Property name= Center value = [1.0, 2.0, 3.0]
+
[2.0, 4.0, 3.0]
 
</source>
 
</source>
  
Next, let’s apply a shrink filter to the cone:
+
Next, apply a shrink filter to the cone:
  
 
<source lang="python">
 
<source lang="python">
>>> shrinkFilter = servermanager.filters.ShrinkFilter(Input=coneSource)
+
>>> shrinkFilter = Shrink(cone)
 
>>> shrinkFilter.Input
 
>>> shrinkFilter.Input
Property name= Input value = <paraview.servermanager.ConeSource object at 0x2d00dd90>:0
+
<paraview.servermanager.Cone object at 0xaf701f0>
 
</source>
 
</source>
  
At this point, if you are interested in getting some information about the output of the shrink filter, you can force it to update (which will also cause the execution of the cone source. For details about VTK pipeline model, see one of the VTK books.
+
At this point, if you are interested in getting some information about the output of the shrink filter, you can force it to update (which will also cause the execution of the cone source). For details about VTK's demand-driven pipeline model used by ParaView, see one of the VTK books.
  
 
<source lang="python">
 
<source lang="python">
Line 153: Line 180:
 
==Rendering==
 
==Rendering==
  
Now that we created a small pipeline, let’s render the result. You will need two objects to render the output of an algorithm in a scene: a representation and a view. A representation is responsible for taking a data object and rendering it in a view. A view is responsible for managing a render context and a collection of representations.
+
Now that you've created a small pipeline, render the result. You will need two objects to render the output of an algorithm in a scene: a representation and a view. A representation is responsible for taking a data object and rendering it in a view. A view is responsible for managing a render context and a collection of representations. Simple creates a view by default. The representation object is created automatically with Show().
  
 
<source lang="python">
 
<source lang="python">
>>> view = servermanager.CreateRenderView()
+
>>> Show(shrinkFilter)
>>> rep = servermanager.CreateRepresentation(shrinkFilter, view)
+
>>> Render()
>>> view.StillRender()
 
</source>
 
 
 
Oops, nothing is visible. We need to reposition the camera to contain the entire scene.
 
 
 
<source lang="python">
 
>>> view.ResetCamera()
 
>>> view.StillRender()
 
 
</source>
 
</source>
  
 
Et voila:
 
Et voila:
  
[[Image:Servermanager_snapshot.png|center]]
+
[[File:Servermanager_snapshot.png|thumb|center|800px|'''Figure 14.1''' Server manager snapshot]]
 
  
CreateRenderView() and CreateRepresentation() are special methods in the servermanager module to facilitate the creation of representations and views. CreateRepresentation() automatically adds the new representation to the view.
+
In example Figure 14.1, the value returned by Cone() and Shrink() was assigned to Python variables and used to build the pipeline. ParaView keeps track of the last pipeline object created by the user. This allows you to accomplish everything you did above using the following code:
  
 
<source lang="python">
 
<source lang="python">
>>> view.Representations
+
>>> from paraview.simple import *
Property name= Representations value = [<paraview.servermanager.UnstructuredGridRepresentation object at 0x2d0170f0>]
+
# Create a cone and assign it as the active object
 +
>>> Cone()
 +
<paraview.servermanager.Cone object at 0x2910f0>
 +
# Set a property of the active object
 +
>>> SetProperties(Resolution=32)
 +
# Apply the shrink filter to the active object
 +
# Shrink is now active
 +
>>> Shrink()
 +
<paraview.servermanager.Shrink object at 0xaf64050>
 +
# Show shrink
 +
>>> Show()
 +
<paraview.servermanager.UnstructuredGridRepresentation object at 0xaf57f90>
 +
# Render the active view
 +
>>> Render()
 +
<paraview.servermanager.RenderView object at 0xaf57ff0>
 
</source>
 
</source>
  
This was a quick introduction to the servermanager module. In the following sections, we will discuss the servermanager in more detail and introduce more advanced concepts.
+
This was a quick introduction to the paraview.simple module. In the following sections, we will discuss the Python interface in more detail and introduce more advanced concepts.
 
 
=paraview.servermanager Module=
 
  
The servermanager module is a ParaView component written using Python on top of the VTK Server Manager C++ library. Its purpose is to make it easier to create ParaView data analysis and visualization pipelines using Python. The servermanager module can be loaded from Python interpreters running in several applications.
+
=paraview.simple Module=
  
* pvpython: The pvpython application, distributed with the ParaView application suite, is a Python client to the ParaView servers. It supports interactive execution as well as batch execution.
+
The simple module is a ParaView component written using Python on top of the Server Manager C++ library. Its purpose is to make it easier to create ParaView data analysis and visualization pipelines using Python. The simple module can be loaded from Python interpreters running in several applications.
  
* pvbatch: The pvbatch application, also distributed with the ParaView application suite, is a Python application designed to run batch scripts on distributed servers. When ParaView is compiled with MPI,
+
* '''pvpython''': The pvpython application, distributed with the ParaView application suite, is a Python client to the ParaView servers. It supports interactive execution as well as batch execution.
  
* pvbatch can be launched as an MPI program. In this mode, the first node will load a Python script specified as a command-line argument and execute it using a special built-in connection on all nodes. This application does not support interactive execution.
+
* '''pvbatch''': The pvbatch application, also distributed with the ParaView application suite, is a Python application designed to run batch scripts on distributed servers. When ParaView is compiled with MPI, pvbatch can be launched as an MPI program. In this mode, the first node will load a Python script specified as a command-line argument and execute it using a special built-in connection on all nodes. This application does not support interactive execution.
  
* paraview: Python scripts can be run from the paraview client using the Python shell that is invoked from Tools -> Python Shell. The Python shell supports interactive mode as well as loading of scripts from file.
+
* '''paraview''': Python scripts can be run from the paraview client using the Python shell that is invoked from '''Tools'''|Python Shell. The Python shell supports interactive mode as well as loading of scripts from file.
  
* External Python interpreter: Any Python-capable application can load the paraview.servermanager module if the right environment is configured. For this to work, you either have to install the paraview Python modules (including the right shared libraries) somewhere in sys.path or you have to set PYTHONPATH to point to the right locations.  
+
* '''External Python interpreter''': Any Python-capable application can load the paraview.simple module if the right environment is configured. For this to work, you either have to install the paraview Python modules (including the right shared libraries) somewhere in sys.path or you have to set PYTHONPATH to point to the right locations.  
  
 
==Overview==
 
==Overview==
  
The paraview.servermanager module contains several Python classes designed to be Python-friendly as well as all classes wrapped from the C++ Server Manager library. The most important classes are as follows.
+
The paraview.simple module contains several Python classes designed to be Python-friendly, as well as all classes wrapped from the C++ Server Manager library. The following sections cover the usage of this module and occasionally the paraview.servermanager module, which is lower level.
 
 
*Proxy
 
 
 
*ProxyManager
 
 
 
*Property and sub-classes
 
 
 
We will cover these classes in detail in following sections.
 
When first loaded,  the servermanager module creates several sub-modules. The most important ones are as follows.
 
 
 
*sources
 
 
 
*filters
 
 
 
*rendering
 
 
 
These modules are automatically populated (at load time) with various Proxy sub-classes as defined in the Server Manager configuration files (ParaView3/Servers/ServerManager/Resources/*.xml). This allows direct instantiation of actual Proxy sub-classes (for example, SphereSource) instead of having to use vtkSMProxyManager::CreateProxy(). Furthermore, the documentation for each class can be obtained using help().
 
  
 
==Connecting to a Server==
 
==Connecting to a Server==
  
Unless you are using the Python shell that is in the paraview application, the first step to any Server Manager Python script is connecting to a server. Even when running in stand-alone mode, you have to connect to a built-in server.
+
ParaView can run in two modes: stand-alone and client/server where the server is usually a visualization cluster. In this section, we discuss how to establish a connection to a server when using ParaView in the client/server mode. If you are using the ParaView graphical interface, you should use Connect from the File menu to connect to a server. If you are using ParaView from a Python shell (not the Python console that is part of the graphical interface), you need to use ''servermanager.Connect()'' to connect a server. <em>Note: you cannot connect to the ParaView application from a stand-alone Python shell. You can only connect to a server.</em>  This method takes four arguments, all of which have default values.
To connect to a server, use servermanager.Connect(). This method takes 4 arguments, all of which have default values.
 
  
 
<source lang="python">
 
<source lang="python">
Line 226: Line 238:
 
</source>
 
</source>
  
When connecting to the built-in server and running pvbatch, do not specify any of these arguments. The default values work well.
+
When connecting to a server (pvserver), specify only the first two arguments. These are the server name (or IP address) and port number.
  
When connecting to a hybrid server (pvserver), specify only the first 2 arguments. These are the server name (or IP address) and port number.
+
When connecting to a data-server/render-server pair, you have to specify all  four arguments. The first two are the host name (or IP address) and port number of the data server, the last two those of the render server.
 
+
Here are some examples:
When connecting to a data-server/render-server pair, you have to specify all  four arguments. The first 2 are the host name (or IP address) and port number of the data server, the last 2 those of the render server.
 
Here are some examples.
 
  
 
<source lang="python">
 
<source lang="python">
# Connect to built-in
 
>>> connection = servermanager.Connect()
 
 
 
# Connect to pvserver running on amber1 (first node of our test cluster)
 
# Connect to pvserver running on amber1 (first node of our test cluster)
 
# using the default port 11111
 
# using the default port 11111
>>> connection = servermanager.Connect(‘amber1’)
+
>>> Connect(‘amber1’)
  
 
# Connect to pvdataserver running on the amber cluster, pvrenderserver  
 
# Connect to pvdataserver running on the amber cluster, pvrenderserver  
 
# running on Berk’s desktop
 
# running on Berk’s desktop
>>> connection = servermanager.Connect(‘amber1’, 12000, ‘kamino’, 11111)
+
>>> Connect(‘amber1’, 12000, ‘kamino’, 11111)
</source>
 
 
 
Although not fully implemented yet, the servermanager supports multiple connection. The module keeps track of the active connection with the ActiveConnection  variable. By default, all communication is sent to the server to which the ActiveConnection points. The first time Connect() is called, servermanager automatically sets ActiveConnection. After the first time, unless Disconnect() is called first, ActiveConnection is not set. If you want to set the ActiveConnection to another connection, use the return value from Connect().
 
 
 
<source lang="python">
 
>>> servermanager.ActiveConnection = servermanager.Connect(‘amber1’)
 
 
</source>
 
</source>
  
Note: Connect() will return None on failure. To be safe, you should check the return value of Connect().
+
Note: Connect() will return None on failure. To be safe, you should check the return value of Connect().
  
 
==Getting Help==
 
==Getting Help==
  
The servermanager module is well documented. You can access it’s online documentation using help().
+
You can access the documentation of all Proxy types by using Python's built-in help.
  
 
<source lang="python">
 
<source lang="python">
>>> from paraview import servermanager
+
>>> help(paraview.simple.Cone)
>>> help(servermanager)
+
Help on function CreateObject in module paraview.simple:
 +
 
 +
CreateObject(*input, **params)
 +
    The Cone source can be used to add a polygonal cone to the 3D scene. The output of the
 +
    Cone source is polygonal data.
 
</source>
 
</source>
  
You can also access the documentation of all Proxy types using the sources, filters and rendering modules.
+
To get the full documentation, you have to create an instance.
  
 
<source lang="python">
 
<source lang="python">
>>> dir(servermanager.filters)
+
>>> c = Cone()
['AllToN', 'Append', 'AppendAttributes', 'AppendPolyData', 'ArbitrarySourceGlyph',
+
>>> help(c)
'ArbitrarySourceStreamTracer', 'Balance', 'BrownianPoints', 'CTHPart', 'Calculator', 'CellCenters',
 
'CellDataToPointData', 'CleanPolyData', 'CleanUnstructuredGrid', 'ClientServerMoveData', 'Clip',
 
'Contour', 'Curvatures', 'Cut', 'D3', 'DataSetSurfaceFilter', 'DataSetTriangleFilter', 'DecimatePro',
 
'Delaunay2D', ...]
 
>>> help(servermanager.filters.Calculator)
 
 
</source>
 
</source>
  
This documentation is automatically generated from the Server Manager configuration files and is identical to the class documentation found under the paraview Help menu.
+
This documentation is automatically generated from the Server Manager configuration files. It is identical to the class documentation found under the ParaView Help menu, as well as here: http://paraview.org/OnlineHelpCurrent/.  
Beyond this document and the online help, there are a few useful documentation sources.
+
Beyond this document and the online help, there are a few useful documentation sources:
  
 
* The ParaView Guide: http://www.kitware.com/products/paraviewguide.html
 
* The ParaView Guide: http://www.kitware.com/products/paraviewguide.html
 +
 +
* The ParaView Wiki: http://paraview.org/Wiki/ParaView
  
 
* The ParaView source documentation: http://www.paraview.org/doc/  
 
* The ParaView source documentation: http://www.paraview.org/doc/  
  
* The ParaView Wiki: http://paraview.org/Wiki/ParaView
 
  
 
If you are interested in learning more about the Visualization Toolkit that is at the foundation of ParaView, visit http://vtk.org.
 
If you are interested in learning more about the Visualization Toolkit that is at the foundation of ParaView, visit http://vtk.org.
Line 289: Line 290:
 
==Proxies==
 
==Proxies==
  
The VTK Server Manager design uses the Proxy design pattern2. Quoting from Wikipedia: “A proxy, in its most general form, is a class functioning as an interface to another thing. The other thing could be anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate”. In the case of Server Manager, a Proxy object acts as a proxy to one or more VTK objects. Most of the time, these are server-side objects and are distributed to the server nodes. Proxy objects allow you to interact with these object as if you directly have access to them, manipulate them and obtain information about them. When creating visualization pipelines, you create proxies instead of VTK objects.  
+
The VTK Server Manager design uses the Proxy design pattern (''See Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides for details''). Quoting from Wikipedia: “A proxy, in its most general form, is a class functioning as an interface to another thing. The other thing could be anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate”. In the case of Server Manager, a Proxy object acts as a proxy to one-or-more VTK objects. Most of the time, these are server-side objects and are distributed to the server nodes. Proxy objects allow you to interact with these objects as if you directly have access to them, manipulate them, and obtain information about them. When creating visualization pipelines, you create proxies instead of VTK objects.  
  
 
<source lang="python">
 
<source lang="python">
 
>>> sphereSource = vtk.vtkSphereSource() # VTK-Python script
 
>>> sphereSource = vtk.vtkSphereSource() # VTK-Python script
  
>>> sphereSourceP = servermanager.SphereSource() # servermanager script
+
>>> sphereSourceP = Sphere() # ParaView script
 
</source>
 
</source>
  
A proxy also provides an interface to modify the properties of the objects it maintains. For example, instead of
+
A proxy also provides an interface to modify the properties of the objects it maintains. For example, instead of:
  
 
<source lang="python">
 
<source lang="python">
Line 303: Line 304:
 
</source>
 
</source>
  
you can write the following.
+
you can write the following:
  
 
<source lang="python">
 
<source lang="python">
>>> sphereSourceP.Center = [1.0, 1.0, 0.0]
+
>>> sphere.Center = [1.0, 1.0, 0.0]
 
</source>
 
</source>
  
Properties are covered in detail in the next section.  
+
When a pipeline object proxy is created, it is set as the active object. You can also set an object as the active one. This is equivalent to clicking-on an object in the pipeline browser.
In the VTK Server Manager library, proxies are instances of vtkSMProxy or one of it’s sub-classes. The servermanager module wraps these classes with a set of Python classes to make them more Python-friendly. Using the Server Manager library, you create a proxy with the help of the Proxy Manager3 :
 
  
 
<source lang="python">
 
<source lang="python">
>>> pxm = servermanager.ProxyManager()
+
>>> c = Cone()
>>> sphereSourceP = pxm.SMProxyManager.NewProxy("sources", "SphereSource")
+
<paraview.servermanager.Cone object at 0xaf73090>
>>> type(sphereSourceP)
+
>>> GetActiveSource()
<type 'vtkobject'>
+
<paraview.servermanager.Cone object at 0xaf73090>
>>> sphereSourceP.GetClassName()
+
>>> Shrink()
'vtkSMSourceProxy'
+
<paraview.servermanager.Shrink object at 0xb4f8610>
 +
# Make the cone active
 +
>>> SetActiveSource(c)
 
</source>
 
</source>
  
The proxy groups (for example “sources”) and the proxy types that can be created are defined in a set of XML configuration files (e.g., ParaView3/Servers/ServerManager/Resources/*.xml). Using the servermanager module, you can directly create a proxy by instantiating the appropriate class.
+
When dealing with objects created through the graphical interface or by loading a state, it is useful to be able to search through existing pipeline objects. To accomplish this, you can use GetSources() and FindSource(). GetSources() returns a dictionary of (name, id) object pairs. Since multiple objects can have the same name, the (name,id) pair identifies objects uniquely. FindSource() returns an object given its name. If there are more than one objects with the same name, the first one is returned.
  
 
<source lang="python">
 
<source lang="python">
>>> sphereSourceP = servermanager.sources.SphereSource()
+
>>> Cone()
>>> type(sphereSourceP)
+
<paraview.servermanager.Cone object at 0xaf73090>
<class 'paraview.servermanager.SphereSource'>
+
>>> GetActiveSource()
>>> sphereSourceP.GetClassName()
+
<paraview.servermanager.Cone object at 0xaf73090>
'vtkSMSourceProxy'
+
>>> Shrink()
 +
<paraview.servermanager.Shrink object at 0xb4f8610>
 +
>>> SetActiveSource(c)
 
</source>
 
</source>
  
A servermanager proxy object contains a Server Manager proxy object. You can access this object directly using the SMProxy data member:
+
To delete pipeline objects, you need to use the Delete() function. Simply letting a Python variable go out of scope is not enough to delete the object. Following the example above:
  
 
<source lang="python">
 
<source lang="python">
>>> type(sphereSourceP.SMProxy)
+
# Delete the cone source
<type 'vtkobject'>
+
>>> Delete(c)
 +
# To fully remove the cone from memory, get rid of the
 +
# variable too
 +
>>> del c
 
</source>
 
</source>
  
All unknown attribute requests made to a servermanager proxy are passed to the SMProxy so you normally should not need to access SMProxy directly.  
+
If you do not use a Python variable to hold the value returned by the pipeline object proxy constructor, the following is needed to delete the object:
 +
<source lang="python">
 +
Cone() # not: c = Cone()
 +
# to delete this object:
 +
# First, delete its entry in the ParaView's pipeline GUI or call Delete(FindSource("Cone1"))
 +
# Then, this is needed:
 +
import gc
 +
gc.collect()
 +
</source>
  
 +
 +
Please note that for destructors to be called, calls such as ''c = FindSource("name")'', respecively ''FindSource("name")'' will also require the call to ''del(c)'', respectively ''gc.collect()'' afterward.
 
==Properties==
 
==Properties==
  
Property objects are used to read and modify the properties of VTK objects represented by proxies. Each proxy has a list of properties defined in the Server Manager configuration files. The property interface of the Server Manager library is somewhat cumbersome. Here is how you can set the radius property of a sphere source.
+
Property objects are used to read and modify the properties of pipeline objects. Each proxy has a list of properties defined in the Server Manager configuration files. The property interface of the Server Manager C++ library is somewhat cumbersome. Here is how you can set the radius property of a sphere source:
  
 
<source lang="python">
 
<source lang="python">
>>> rp = sphereSourceP.GetProperty("Radius")
+
>>> rp = sphere.GetProperty("Radius")
 
>>> rp.SetElement(0, 2)
 
>>> rp.SetElement(0, 2)
 
1
 
1
>>> sphereSourceP.UpdateProperty("Radius")
+
>>> sphere.UpdateProperty("Radius")
 
</source>
 
</source>
  
Line 354: Line 371:
  
 
<source lang="python">
 
<source lang="python">
>>> sphereSourceP.Radius = 3
+
>>> sphere.Radius = 3
 
</source>
 
</source>
  
Here Radius is a Python property which, when a value is assigned to it, calls sphereSourceP.SetPropertyWithName(Radius,3). The same property returns a servermanager Property object when accessed.
+
Here, Radius is a Python property which, when a value is assigned to it, calls sphere.SetPropertyWithName("Radius",3). Properties can also passed to the function creating the object:
  
 
<source lang="python">
 
<source lang="python">
>>> type(sphereSourceP.Radius)
+
>>> cone = Cone(Radius=0.5, Center=[1, 0.5, 0])
<class 'paraview.servermanager.VectorProperty'>
+
<paraview.servermanager.Cone object at 0xaf73090>
 
</source>
 
</source>
  
The class hierarchy for property classes looks like this.
+
You can also use the SetProperties() function to set property values.
 +
 
 +
<source lang="python">
 +
>>> SetProperties(cone, Radius=0.2, Center=[2, 0.5, 0])
 +
</source>
  
[[Image:Prophierarchy.png|center]]
+
If the first argument is not specified, the active object is used. You also use SetDisplayProperties() and SetViewProperties() to set display (representation) and view properties respectively.
  
+
All Property classes define the following methods:
All Property classes define the following methods.
 
  
 
* __len__()  
 
* __len__()  
Line 379: Line 399:
 
* SetData().  
 
* SetData().  
  
Therefore, all of the following are supported.
+
Therefore, all of the following are supported:
  
 
<source lang="python">
 
<source lang="python">
>>> sphereSourceP.Center
+
>>> sphere.Center
Property name= Center value = [0.0, 0.0, 0.0]
+
[0.0, 0.0, 0.0]
>>> sphereSourceP.Center[0] = 1
+
>>> sphere.Center[0] = 1
>>> sphereSourceP.Center[0:3] = [1,2,3]
+
>>> sphere.Center[0:3] = [1,2,3]
>>> sphereSourceP.Center[0:3]
+
>>> sphere.Center[0:3]
 
[1.0, 2.0, 3.0]
 
[1.0, 2.0, 3.0]
>>> sphereSourceP.Center.SetData([2,1,3])
+
>>> len(sphere.Center)
>>> sphereSourceP.Center.GetData()
 
[2.0, 1.0, 3.0]
 
>>> len(sphereSourceP.Center)
 
 
3
 
3
 
</source>
 
</source>
  
ProxyProperty and InputProperty also define  
+
ProxyProperty and InputProperty also define
  
 
* append()
 
* append()
Line 404: Line 421:
  
 
VectorProperty is used for scalars, vectors and lists of integer and floating point numbers as well as  
 
VectorProperty is used for scalars, vectors and lists of integer and floating point numbers as well as  
strings (vtkSMIntVectorProperty, vtkSMDoubleVectorProperty and vtkSMStringVectorProperty, respectively) . Most properties of this type are simple. Examples include SphereSource.Radius (double scalar), SphereSource.Center (vector of doubles), GlyphSource2D.Filled (boolean), GlyphSource2D.GlyphType (enumeration), VectorText.Text (string) and Contour.ContourValues (list of doubles).  Some properties may be more complicated because they map to C++ methods with mixed argument types. Two good examples of this case are Glyph.SelectInputScalars and ExodusIIReader.PointResultArrayStatus.
+
strings. Most properties of this type are simple. Examples include ''Sphere.Radius'' (double scalar), ''Sphere.Center'' (vector of doubles), ''a2DGlyph.Filled'' (boolean), ''a2DGlyph.GlyphType'' (enumeration), ''a3DText.Text'' (string), and ''Contour.Isosurfaces'' (list of doubles).  Some properties may be more complicated because they map to C++ methods with mixed argument types. Two good examples of this case are ''Glyph.Scalars'' and ''ExodusIIReader.PointVariables''.
  
 
<source lang="python">
 
<source lang="python">
>>> reader = servermanager.sources.ExodusIIReader(FileName='.../disk_out_ref.ex2')
+
>>> reader = ExodusIIReader(FileName='.../can.ex2')
>>> reader.UpdatePipelineInformation()
+
# These variables are currently selected
# Get information about arrays and whether they will be read. By
+
>>> reader.PointVariables
# default no arrays are read.
+
['DISPL', 'VEL', 'ACCL']
>>> reader.PointResultArrayInfo
+
# These are available in the file
Property name= PointResultArrayInfo value = ['Temp', '0', 'V', '0', 'Pres', '0', 'AsH3', '0', 'GaMe3',
+
>>> reader.PointVariables.Available
'0', 'CH4', '0', 'H2', '0']
+
['DISPL', 'VEL', 'ACCL']
# Enable the Temp array
+
# Enable the DISPL array only
>>> reader.PointResultArrayStatus = ['Temp', '1']
+
>>> reader.PointVariables = ['DISPL']
 
# Force read
 
# Force read
 
>>> reader.UpdatePipeline()
 
>>> reader.UpdatePipeline()
# Now check the output
+
# Now check the output. Note: GlobalNodeId is generated automatically by the reader.
>>> pdi = reader.GetDataInformation().GetPointDataInformation()
+
>>> reader.PointData[:]
>>> pdi.GetNumberOfArrays()
+
[Array: GlobalNodeId, Array: PedigreeNodeId, Array: DISPL]
1
 
>>> pdi.GetArrayInformation(0).GetName()
 
'Temp'
 
 
</source>
 
</source>
  
This example demonstrates the use of ExodusIIReader.PointResultArrayStatus. This is a VectorProperty that represents a list of tuples of strings of 2 elements: (array name, status [on|off]). The underlying C++ function has a signature of  SetPointResultArrayStatus( const char* name, int flag ). This method is usually called once per array to enable or disable it (i.e. to set whether the reader will read a particular array). From the previous case, let’s enable reading of V and CH4.
+
This example demonstrates the use of ''ExodusIIReader.PointVariables''. This is a VectorProperty that represents a list of array names. The underlying C++ function has a signature of  SetPointResultArrayStatus(const char* name, int flag). This method is usually called once per array to enable or disable it (i.e. to set whether the reader will read a particular array).
 
 
<source lang="python">
 
>>> reader.PointResultArrayStatus = [ ‘V’ , ‘1’, ‘CH4’, ‘1’ ]
 
</source>
 
  
Note that the property uses strings for both the array name and the flag (which is actually an integer). Properties do not directly support mixed types, thus forcing us to use strings in this situation.
+
Glyph.Scalars is a bit more complicated. This property allows the developer to select the scalar array with which to scale the glyphs.
Glyph.SelectInputScalars is more complicated.
 
  
 
<source lang="python">
 
<source lang="python">
>>> sph= servermanager.sources.SphereSource()
+
>>> sph = Sphere()
# Glyph source producing diamond
+
>>> elev=Elevation(sph)
>>> source=servermanager.sources.GlyphSource2D(GlyphType=8)
+
# Glyph the points of the sphere with spheres
>>> elev=servermanager.filters.ElevationFilter(Input=sph)
+
>>> glyph=Glyph(elev, GlyphType='Sphere')
# Glyph the points of the sphere with diamonds
 
>>> glyph=servermanager.filters.Glyph(Input=elev, Source=source)
 
 
# Scale the glyph with the Elevation array
 
# Scale the glyph with the Elevation array
>>> glyph.SelectInputScalars = [ '0', '0', '0', '0', 'Elevation' ]
+
>>> glyph.Scalars = 'Elevation'
>>> glyph.ScaleMode = 0 # Use scalars
+
>>> glyph.Scalars
 +
['POINTS', 'Elevation']
 +
# The above shows the association of the array as well as its name.
 +
# In this case, the array is associated with POINTS as it has to be
 +
# since Glyph cannot scale by cell arrays. We could have done:
 +
>>> glyph.Scalars = ['POINTS', 'Elevation']
 +
# Enable scaling by scalars
 +
>>> glyph.ScaleMode = 'scalar'
 
</source>
 
</source>
  
Here the property SelectInputScalars maps to SetInputArrayToProcess( int idx, int port, int connection, int fieldAssociation,  const char *name ) which has four integer arguments (some of which are enumeration) and 1 string argument5.
+
Here the property Scalars maps to SetInputArrayToProcess(int idx, int port, int connection, int fieldAssociation,  const char *name), which has four integer arguments (some of which are enumeration) and one string argument (''see vtkAlgorithm documentation for details'').
A ProxyProperty can point to one or more proxies. This is equivalent to a C++ method that takes a pointer to a VTK object. Examples of ProxyProperty include Cut.CutFunction (single proxy) and RenderView.Representations (a list of proxies) .
+
 
InputProperty is similar to ProxyProperty; it is used to connect pipeline objects (source proxies). It is covered in more detail in the next section.
+
Properties are either regular (push) or information (pull) properties. Information properties do not have a VTK method associated with them and are responsible for getting information from the server. A good example of an information property is TimestepValues, which returns all time steps available in a file (if the reader supports time).
Properties are either regular (push) or information (pull) properties. Information properties do not have a VTK method associated with them and are responsible for getting information from the server. A good example of an information property is TimestepValues which returns all time steps available in a file (if the reader supports time).
 
  
 
<source lang="python">
 
<source lang="python">
>>> reader = servermanager.sources.ExodusIIReader(FileName='.../can.ex2')
+
>>> reader = ExodusIIReader(FileName='.../can.ex2')
>>> reader.UpdatePropertyInformation()
 
 
>>> reader.TimestepValues
 
>>> reader.TimestepValues
Property name= TimestepValues value = [0.0, 0.00010007373930420727, 0.00019990510190837085,  
+
[0.0, 0.00010007373930420727, 0.00019990510190837085, 0.00029996439116075635, 0.00040008654468692839,
0.00029996439116075635, 0.00040008654468692839, 0.00049991923151537776, 0.00059993512695655227,  
+
0.00049991923151537776, 0.00059993512695655227, 0.00070004, ...]
0.00070004921872168779,  
 
...]
 
 
</source>
 
</source>
  
By default, information properties are not pulled. To force a pull, call UpdatePropertyInformation() on the proxy.
+
You can obtain a list of properties a proxy supports by using ''help()''. However, this does not allow introspection programmatically. If you need to obtain information about a proxy’s properties programmatically, you can use a property iterator:
You can obtain a list of properties a proxy supports by using help(). However, this does not allow introspection programmatically. If you need to obtain information about a proxy’s properties programmatically, you can use a property iterator:
 
  
 
<source lang="python">
 
<source lang="python">
 
>>> for prop in glyph:
 
>>> for prop in glyph:
print prop
+
print type(prop), prop.GetXMLLabel()
  
Property name= Input value = <paraview.servermanager.ElevationFilter>:0
+
<class 'paraview.servermanager.InputProperty'> Input
Property name= MaximumNumberOfPoints value = 5000
+
<class 'paraview.servermanager.VectorProperty'> Maximum Number of Points
Property name= RandomMode value = 1
+
<class 'paraview.servermanager.VectorProperty'> Random Mode
Property name= SelectInputScalars value = ['0', '0', '0', '0', 'Elevation']
+
<class 'paraview.servermanager.ArraySelectionProperty'> Scalars
Property name= SelectInputVectors value = ['1', '', '', '', '']
+
<class 'paraview.servermanager.ArraySelectionProperty'> Vectors
Property name= Orient value = 1
+
<class 'paraview.servermanager.VectorProperty'> Orient
Property name= ScaleFactor value = 1.0
+
<class 'paraview.servermanager.VectorProperty'> Set Scale Factor
Property name= ScaleMode value = 0
+
<class 'paraview.servermanager.EnumerationProperty'> Scale Mode
Property name= Source value = <paraview.servermanager.GlyphSource2D>:0
+
<class 'paraview.servermanager.InputProperty'> Glyph Type
Property name= UseMaskPoints value = 1
+
<class 'paraview.servermanager.VectorProperty'> Mask Points
 
</source>
 
</source>
  
As an alternative, you can use a PropertyIterator object.
+
The XMLLabel is the text display by the graphical user-interface. Note that there is a direct mapping from the XMLLabel to the property name. If you remove all spaces from the label, you get the property name. You can use the ''PropertyIterator'' object directly.
  
 
<source lang="python">
 
<source lang="python">
>>> it = s.__iter__()
+
>>> it = iter(s)
 
>>> for i in it:
 
>>> for i in it:
 
print it.GetKey(), it.GetProperty()
 
print it.GetKey(), it.GetProperty()
 
</source>
 
</source>
  
==Domains (advanced)==
+
==Domains==
  
The Server Manager provides information about values that are valid for properties. The main use of this information is for the user interface to provide good ranges and choices in enumeration. However, some of this information is also very useful for introspection. For example, enumeration properties look like simple integer properties unless a (value, name) pair is associated with them. The Server Manager uses Domain objects to store this information. The contents of domains may be loaded from xml configuration files or computed automatically. Let’s look at an example.
+
The Server Manager provides information about values that are valid for properties. The main use of this information is for the user-interface to provide good ranges and choices in enumeration. However, some of this information is also very useful for introspection. For example, enumeration properties look like simple integer properties unless a (value, name) pair is associated with them. The Server Manager uses Domain objects to store this information. The contents of domains may be loaded from xml configuration files or computed automatically. For example:
  
 
<source lang="python">
 
<source lang="python">
>>> s = servermanager.sources.SphereSource()
+
>>> s = Sphere()
>>> v = servermanager.CreateRenderView()
+
>>> Show(s)
>>> r = servermanager.CreateRepresentation(s, v)
+
>>> dp = GetDisplayProperties(s)
>>> r.Representation
+
>>> dp.Representation
Property name= Representation value = 2
+
'Surface'
# So, what does 2 mean? Let’s find out. Find the first domain for
+
# The current representation type is Surface. What other types
# the Representation property. Usually, there is only one domain per
+
# are available?
# property but you still have to use an iterator to get to it.
+
>>> dp.GetProperty("Representation").Available
>>> r.Representation.NewDomainIterator().GetKey()
+
['Outline', 'Points', 'Wireframe', 'Surface', 'Surface With Edges']
'enum'
+
# Choose outline
# It is the domain called “enum”. This domain gives us information
+
>>> dp.Representation = 'Outline'
# about the enumeration values.
 
>>> d = r.Representation.GetDomain("enum")
 
# Iterate over the possible values and print them.
 
>>> for i in range(d.GetNumberOfEntries()):
 
print d.GetEntryValue(i), d.GetEntryText(i)
 
 
 
0 Points
 
1 Wireframe
 
2 Surface
 
3 Outline
 
 
</source>
 
</source>
 
There are many other domain types but most are either not very useful or are difficult to update when used from Python. For more information, see http://www.paraview.org/ParaView3/Doc/Nightly/html/classvtkSMDomain.html.
 
  
 
==Source Proxies==
 
==Source Proxies==
  
Source proxies are proxies that represent pipeline objects (vtkAlgorithm6). They have special properties to connect them as well as special method to query the meta-data of their output.
+
Source proxies are proxies that represent pipeline objects (''For more information about VTK pipelines, see the VTK books: http://vtk.org/buy-books.php''). They have special properties to connect them as well as special method to query the meta-data of their output. To connect a source proxy to another, use one of its input properties.
To connect a source proxy, use one of its input properties. An input property can either accept another source proxy or an OutputPort object. An OutputPort object is a simple object that has two attributes: a source proxy and an output port index. Since most of the VTK algorithms have one output, OutputPort is usually not needed. Use it when you have to connect an algorithm to an output other than the first one.
 
  
 
<source lang="python">
 
<source lang="python">
 +
# Either
 +
>>> glyph = Glyph(elev)
 +
# or
 
>>> glyph.Input = elev
 
>>> glyph.Input = elev
 
</source>
 
</source>
  
is equivalent to the following.
+
The SourceProxy class provides several additional properties and methods that are specific to pipelines (See vtkSMSourceProxy documentation for a full list).
 
+
* '''UpdatePipelineInformation()''': This method calls UpdateInformation() on the VTK algorithm. It also calls UpdatePropertyInformation() to update any information properties.
<source lang="python">
+
* '''UpdatePipeline()''': This method calls Update() on the VTK algorithm causing a pipeline execution if the pipeline changed. Another way of causing pipeline updates is to render. The render view updates all connected pipelines.
>>> glyph.Input = OutputPort(elev, 0)
+
* '''GetDataInformation()''': This method is used to obtain meta-data about one output. It is discussed further below.
</source>
+
* PointData and CellData properties discussed below.
 
 
To connect glyph to the second output of some filter, use the following
 
 
 
<source lang="python">
 
>>> glyph.Input = OutputPort(elev, 1)
 
</source>
 
 
 
Note that GetData() and associated methods of an InputProperty always return OutputPort objects.
 
 
 
<source lang="python">
 
>>> type(glyph.Input.GetData())
 
<class 'paraview.servermanager.OutputPort'>
 
</source>
 
 
 
The SourceProxy class provides several additional methods that are specific to pipelines (See vtkSMSourceProxy documentation for a full list).
 
* UpdatePipelineInformation(): This method calls UpdateInformation() on the VTK algorithm. It also calls UpdatePropertyInformation() to update any information properties.
 
  
* UpdatePipeline(): This method calls Update() on the VTK algorithm causing a pipeline execution if the pipeline changed. Another way of causing pipeline updates is to render. The render view updates all connected pipelines.
+
There are two common ways of getting meta-data information from a proxy: information properties and DataInformation. Information properties are updated automatically every time UpdatePropertyInformation() and UpdatePipelineInformation() are called. All you have to do is read the data from the property as usual. To get a DataInformation object from a source proxy use ''GetDataInformation(port=0''). By default, this method returns data information for the first output. You can pass an optional port number to get information for another output. You can get detailed documentation on DataInformation by using help() and by reading online documentation for vtkPVDataInformation (''http://www.paraview.org/doc/nightly/html/classvtkPVDataInformation.html''). Here are the use of some common methods:
* GetDataInformation(): This method is used to obtain meta-data about one output. It is discussed further below.
 
 
 
There are two common ways of getting meta-data information from a proxy: information properties and DataInformation. Information properties are updated automatically every time UpdatePropertyInformation() and UpdatePipelineInformation() are called. All you have to do is read the data from the property as usual. To get a DataInformation object from a source proxy use GetDataInformation(port=0). By default, this method returns data information for the first output. You can pass an optional port number to get information for another output. You can get detailed documentation on DataInformation by using help() and by reading online documentation for vtkPVDataInformation. Here are the use of some common methods.
 
  
 
<source lang="python">
 
<source lang="python">
Line 560: Line 540:
 
<paraview.servermanager.DataInformation object at 0x2d0920d0>
 
<paraview.servermanager.DataInformation object at 0x2d0920d0>
 
>>> glyph.UpdatePipeline()
 
>>> glyph.UpdatePipeline()
# Make sure to update the data information after updating the
 
# pipeline. This does not happen automatically
 
>>> di.Update()
 
 
# Get the data type.
 
# Get the data type.
>>> di.GetDataSetType()
+
>>> di.GetDataClassName()
0
 
>>> di.GetDataSetTypeAsString()
 
 
'vtkPolyData'
 
'vtkPolyData'
# Get information about point data. Use GetCellDataInformation() and
+
# Get information about point data.  
# GetFieldDataInformation() for cell and field data.
+
>>> pdi = glyph.PointData
>>> pdi = di.GetPointDataInformation()
 
 
# We are now directly accessing the wrapper for a VTK class
 
# We are now directly accessing the wrapper for a VTK class
>>> pdi.GetClassName()
+
>>> len(pdi)
'vtkPVDataSetAttributesInformation'
+
2
>>> pdi.GetNumberOfArrays()
 
1
 
 
# Get information for a point array
 
# Get information for a point array
>>> ai = pdi.GetArrayInformation(0)
+
>>> ai = pdi[0]
>>> ai.GetClassName()
+
>>> ai.GetRange(0)
'vtkPVArrayInformation'
 
>>> ai.GetName()
 
'Elevation'
 
>>> ai.GetNumberOfComponents()
 
1
 
>>> ai.GetComponentRange(0)
 
 
(0.0, 0.5)
 
(0.0, 0.5)
 
</source>
 
</source>
  
When meta-data is not enough and you need access to the raw data, you can use Fetch() to bring it to the client side8. Fetch() has three modes:
+
When meta-data is not enough and you need access to the raw data, you can use Fetch() to bring it to the client side. Note that this function is provided by the servermanager module. Fetch() has three modes:
  
 
*Append all of the data together and bring it to the client (only available for polygonal and unstructured datasets). Note: Do not do this if data is large otherwise the client will run out of memory.
 
*Append all of the data together and bring it to the client (only available for polygonal and unstructured datasets). Note: Do not do this if data is large otherwise the client will run out of memory.
Line 596: Line 562:
 
*Use a reduction algorithm and bring its output to the client. For example, find the minimum value of an attribute.
 
*Use a reduction algorithm and bring its output to the client. For example, find the minimum value of an attribute.
  
Here is a demonstration.
+
Here is a demonstration:
  
 
<source lang="python">
 
<source lang="python">
>>> from paraview import servermanager
+
>>> from paraview.simple import *
>>> servermanager.Connect("kamino")
+
>>> Connect("kamino")
 
Connection (kamino:11111)
 
Connection (kamino:11111)
>>> s = servermanager.sources.SphereSource()
+
>>> s = Sphere()
>>> s.UpdatePipeline()
 
 
# Get the whole sphere. DO NOT DO THIS IF THE DATA IS LARGE otherwise
 
# Get the whole sphere. DO NOT DO THIS IF THE DATA IS LARGE otherwise
 
# the client will run out of memory.
 
# the client will run out of memory.
Line 617: Line 582:
 
48
 
48
 
# Apply the elevation filter so that we have a useful scalar array.
 
# Apply the elevation filter so that we have a useful scalar array.
>>> elev = servermanager.filters.ElevationFilter(Input=s)
+
>>> elev = Elevation(s)
>>> elev.UpdatePipeline()
 
 
# We will use the MinMax algorithm to compute the minimum value of
 
# We will use the MinMax algorithm to compute the minimum value of
 
# elevation. MinMax will be first applied on each processor. The results
 
# elevation. MinMax will be first applied on each processor. The results
 
# will then be gathered to the first node. MinMax will be then applied
 
# will then be gathered to the first node. MinMax will be then applied
 
# to the gathered results.
 
# to the gathered results.
>>> mm = servermanager.filters.MinMax()
+
# We first create MinMax without an input.
# How do I make it compute minimum? I think the property is called
+
>>> mm = MinMax(None)
# Operation
+
# Set it to compute min
>>> d = mm.Operation.NewDomainIterator().GetDomain()
 
>>> d.GetNumberOfStrings()
 
3
 
>>> for i in range(3):
 
print d.GetString(i)
 
 
 
MIN
 
MAX
 
SUM
 
 
>>> mm.Operation = "MIN"
 
>>> mm.Operation = "MIN"
 
# Get the minimum
 
# Get the minimum
Line 645: Line 600:
 
>>> a0.GetName()
 
>>> a0.GetName()
 
'Elevation'
 
'Elevation'
>>> a1.GetTuple1(0)
+
>>> a0.GetTuple1(0)
 
0.0
 
0.0
 
</source>
 
</source>
Line 651: Line 606:
 
==Representations and Views==
 
==Representations and Views==
  
Once a pipeline is created, it can be rendered using representations and views. A view is essentially a “window” in which multiple representations can be displayed. When the view is a VTK view (such as RenderView), this corresponds to a collection of objects including vtkRenderers and a vtkRenderWindow. However, there is no requirement for a view to be a VTK view or to render anything. A representation is  a collection of objects, usually a pipeline, that takes a data object, converts it to something that can be rendered and renders it. When the view is a VTK view, this corresponds to a collection of objects including geometry filters, level-of-detail algorithms, vtkMappers and vtkActors.  
+
Once a pipeline is created, it can be rendered using representations and views. A view is essentially a “window” in which multiple representations can be displayed. When the view is a VTK view (such as RenderView), this corresponds to a collection of objects including vtkRenderers and a vtkRenderWindow. However, there is no requirement for a view to be a VTK view or to render anything. A representation is  a collection of objects, usually a pipeline, that takes a data object, converts it to something that can be rendered, and renders it. When the view is a VTK view, this corresponds to a collection of objects including geometry filters, level-of-detail algorithms, vtkMappers and vtkActors. The simple module automatically creates a view after connecting to a server (including the built-in connection when using the stand-alone mode). Furthermore, the simple module creates a representation the first time a pipeline object is displayed with Show().
Using the servermanager module, it is easy to create default representations and views.
+
It is easy to create new views.
  
 
<source lang="python">
 
<source lang="python">
>>> view = servermanager.CreateRenderView()
+
>>> view = CreateRenderView()
>>> rep = servermanager.CreateRepresentation(glyph, view)
 
 
</source>
 
</source>
  
CreateRenderView() is a special method that creates the render view appropriate for the ActiveConnection (or for another connection specified as an argument). It returns a sub-class of Proxy. Like the constructor of Proxy, it can take an arbitrary number of keyword arguments to set initial values for properties.
+
CreateRenderView() is a special method that creates the render view appropriate for the ActiveConnection (or for another connection specified as an argument). It returns a sub-class of Proxy. Like the constructor of Proxy, it can take an arbitrary number of keyword arguments to set initial values for properties. Note that ParaView makes the view that was created last the active view. When using Show() without a view argument, the pipeline is shown in the active view. You can get a list of views as well as the active view as follows:
  
Once you have a render view, you can use CreateRepresentation() to create a default representation appropriate for that view. Under the cover, this function uses CreateDefaultRepresentation() defined by vtkSMViewProxy.  
+
<source lang="python">
 +
>>> GetRenderViews()
 +
[<paraview.servermanager.RenderView object at 0xaf64ef0>, <paraview.servermanager.RenderView object at 0xaf64b70>]
 +
>>> GetActiveView()
 +
<paraview.servermanager.RenderView object at 0xaf64b70>
 +
</source>
  
Although it is possible to create representations and views directly by instantiating their class objects, we recommend not doing it. Not all views work with all connections types and not all representations work with all view types.
+
You can also change the active view using SetActiveView().
  
Representations and views have a large number of unfortunately poorly documented methods. We will cover some them here.
+
Once you have a render view, you can use pass it to Show in order to select in which view a pipeline object is displayed. You can also pass it to Render() to select which view is rendered.
  
 
<source lang="python">
 
<source lang="python">
>>> from paraview import servermanager
+
>>> Show(elev, GetRenderViews()[1])
 +
<paraview.servermanager.GeometryRepresentation object at 0xaf64e30>
 +
>>> Render(GetRenderViews()[1])
 +
</source>
 +
 
 +
Notice that Show() returns a representation object (aka DisplayProperties in the simple module). This object can be used to manipulate how the pipeline object is displayed in the view. You can also access the display properties of an object using GetDisplayProperties().
 +
 
 +
<source lang="python">
 +
>>> dp = GetDisplayProperties(elev)
 +
>>> dp
 +
<paraview.servermanager.GeometryRepresentation object at 0xaf649d0>
 +
</source>
 +
 
 +
Display properties and views have a large number of properties some of which are poorly documented. We will cover some them here.
 +
 
 +
<source lang="python">
 +
>>> from paraview.simple import *
 
# Create a simple pipeline
 
# Create a simple pipeline
>>> sph = servermanager.sources.SphereSource()
+
>>> sph = Sphere()
>>> elev = servermanager.filters.ElevationFilter(Input=sph)
+
>>> elev = Elevation(sph)
# Create representation, view
+
>>> Show(elev)
>>> view = servermanager.CreateRenderView()
+
>>> Render()
>>> rep = servermanager.CreateRepresentation(elev, view)
+
# Set the representation type of elev
>>> view.StillRender()
+
>>> dp = GetDisplayProperties(elev)
>>> view.ResetCamera()
+
>>> dp.Representation = 'Points'
>>> view.StillRender()
+
# Here is how you get the list of representation types
# Look at the domain for the Representation property to get a
+
>>> dp.GetProperty("Representation").Available
# list of possible representation values.
+
['Outline', 'Points', 'Wireframe', 'Surface', 'Surface With Edges']
>>> domain = rep.Representation.NewDomainIterator().GetDomain()
+
>>> Render()
>>> for i in range(domain.GetNumberOfEntries()):
 
print domain.GetEntryValue(i), ":", domain.GetEntryText(i)
 
 
 
0 : Points
 
1 : Wireframe
 
2 : Surface
 
3 : Outline
 
# Change the representation to points
 
>>> rep.Representation = 0
 
>>> view.StillRender()
 
 
# Change the representation to wireframe
 
# Change the representation to wireframe
>>> rep.Representation = 1
+
>>> dp.Representation = 'Wireframe'
>>> view.StillRender()
+
>>> Render()
# Change the representation to surface
 
>>> rep.Representation = 2
 
>>> view.StillRender()
 
 
# Let’s get some information about the output of the elevation
 
# Let’s get some information about the output of the elevation
 
# filter. We want to color the representation by one of it’s
 
# filter. We want to color the representation by one of it’s
 
# arrays.
 
# arrays.
>>> di = elev.GetDataInformation()
 
# First array = Normals. Boring.
 
>>> ai = di.GetPointDataInformation().GetArrayInformation(0)
 
>>> ai.GetName()
 
'Normals'
 
 
# Second array = Elevation. Interesting. Let’s use this one.
 
# Second array = Elevation. Interesting. Let’s use this one.
>>> ai = di.GetPointDataInformation().GetArrayInformation(1)
+
>>> ai = elev.PointData[1]
 
>>> ai.GetName()
 
>>> ai.GetName()
 
'Elevation'
 
'Elevation'
 
# What is its range?
 
# What is its range?
>>> ai.GetComponentRange(0)
+
>>> ai.GetRange()
 
(0.0, 0.5)
 
(0.0, 0.5)
 
# To color the representation by an array, we need to first create
 
# To color the representation by an array, we need to first create
# a lookup table.  
+
# a lookup table. We use the range of the Elevation array
>>> lt = servermanager.rendering.PVLookupTable()
+
>>> dp.LookupTable = MakeBlueToRedLT(0, 0.5)
>>> rep.LookupTable = lt
+
>>> dp.ColorAttributeType = 'POINT_DATA'
>>> rep.ColorAttributeType = 0 # point data
+
>>> dp.ColorArrayName = 'Elevation' # color by Elevation
>>> rep.ColorArrayName = 'Elevation' # color by Elevation
+
>>> Render()
# The lookup table is used to map scalar values to colors. The
 
# values in the lookup table have 4 numbers: 1 scalar value, 3 color
 
# values (rgb). Thisparticular table has 2 values, 0 = (0, 0, 1) (blue)
 
# and 0.5 = (1, 0, 0) (red). The colors in between are interpolated.
 
>>> lt.RGBPoints = [0, 0, 0, 1, 0.5, 1, 0, 0]
 
# Use the HSV color space to interpolate
 
>>> lt.ColorSpace = 1 # HSV
 
>>> view.StillRender()
 
 
</source>
 
</source>
  
 
Here is the result:
 
Here is the result:
+
[[Image:SMView.png|thumb|center|800px|'''Figure 14.2''' Object displayed in a view]]
 +
 
 +
 
 
Once you create a scene, you will probably want to interact with the camera and ResetCamera() is likely to be insufficient. In this case, you can directly get the camera from the view and manipulate it. GetActiveCamera() returns a VTK object (not a proxy) with which you can interact.
 
Once you create a scene, you will probably want to interact with the camera and ResetCamera() is likely to be insufficient. In this case, you can directly get the camera from the view and manipulate it. GetActiveCamera() returns a VTK object (not a proxy) with which you can interact.
  
 
<source lang="python">
 
<source lang="python">
>>> camera = view.GetActiveCamera()
+
>>> camera = GetActiveCamera()
 
>>> camera
 
>>> camera
 
<libvtkCommonPython.vtkCamera vtkobject at 0xe290>
 
<libvtkCommonPython.vtkCamera vtkobject at 0xe290>
 
>>> camera.Elevation(45)
 
>>> camera.Elevation(45)
>>> view.StillRender()
+
>>> Render()
 
</source>
 
</source>
  
Line 743: Line 694:
  
 
<source lang="python">
 
<source lang="python">
>> view.WriteImage("/Users/berk/image.png", "vtkPNGWriter", 1)
+
>> WriteImage("/Users/berk/image.png")
0
 
 
</source>
 
</source>
  
The resulting image.png looks like this.
+
The resulting image.png looks like this. See the documentation for WriteImage() for details on choosing file type, as well as a magnification factor to save images larger than the view size.
+
 
The last, integer argument to WriteImage() controls the magnification factor. The dimensions of the saved image are magnification factor times the dimensions of the render view. This argument is optional.
+
[[Image:Image.jpg|thumb|center|800px|'''Figure 14.3''' Saving a view as an image]]
 +
 
 +
=Advanced Concepts=
  
=Proxy Manager and Interaction with GUI=
+
==Dealing with lookup tables==
 +
In v4.1 LUT manipulation was simplified so that the LUTs found in the GUI may be assigned to arrays by name. See [[ParaView/Python/Lookup_tables | Lookup tables recipe]] for more information.
  
So far, we only talked about Python scripts in isolation and did not clarify how you can interact with the user interface (i.e. notify the application that you created a proxy or access proxies created using the user interface). For this, we need to talk about the Proxy Manager. The Proxy Manager is a helper class used to create and manage proxies. We have already seen how it can be used to create proxies.
+
As shown earlier, you can use MakeBlueToRedLt(min, max) to create a lookup table. However, this simply creates a new lookup table that the GUI won't be aware of. In the ParaView Qt application, we have special lookup table management that ensures that the same lookup table is used for all arrays with same name and number of components. To reproduce the same behavior in Python, use GetLookupTableForArray().
  
 
<source lang="python">
 
<source lang="python">
>>> pxm = servermanager.ProxyManager()
+
def GetLookupTableForArray(arrayname, num_components, **params):
>>> sphereSourceP = pxm.SMProxyManager.NewProxy("sources", "SphereSource")
+
    """Used to get an existing lookuptable for a array or to create one if none
>>> type(sphereSourceP)
+
    exists. Keyword arguments can be passed in to initialize the LUT if a new
<type 'vtkobject'>
+
    one is created. Returns the lookup table."""
>>> sphereSourceP.GetClassName()
+
    ....
'vtkSMSourceProxy'
 
 
</source>
 
</source>
  
Under the cover, Proxy’s __init__() calls NewProxy() to create the VTK proxy. Another important role of the Proxy Manager is to manage instances of proxies in different groups to allow easy access to them. Like Proxy and Property classes, servermanager defines a Python-friend wrapper around the Server Manager Proxy Manager (vtkSMProxyManager). This class is called ProxyManager. Although you can create as many ProxyManager instances you want, there is only one instance of vtkSMProxyManager underneath9.
+
This will create a new lookup table and associate it with that array, if none already exists. Any default arguments to be passed to the lookup table if a new one is created, can be specified as additional parameters. You can always change the properties on the lookup table returned by this function.
 +
 
 +
 
 +
<source lang="python">
 +
# To color the representation by an array, we need to first create
 +
# a lookup table.  We use the range of the Elevation array
 +
>>> dp.LookupTable = GetLookupTableForArray("Elevation", 1,
 +
                      RGBPoints = [min, 0, 0, 1, max, 1, 0, 0],
 +
                      ColorSpace = "HSV")
 +
>>> dp.ColorAttributeType = 'POINT_DATA'
 +
>>> dp.ColorArrayName = 'Elevation' # color by Elevation
 +
>>> Render()
 +
</source>
  
==Registering Proxies==
+
==Loading State and Manipulating It==
  
You can register proxies under any arbitrary group using RegisterProxy().
+
Let’s say you created a complicated visualization using the paraview application and now you want to make slight changes to it and run it in a loop as a batch script. What do you do? The best way of dealing with this is to save your visualization state and then load it from Python. Let’s say you have a state file saved as myteststate.pvsm:
  
 
<source lang="python">
 
<source lang="python">
>>> sph=servermanager.sources.SphereSource()
+
>>> from paraview.simple import *
>>> print sph
+
# Load the state
<paraview.servermanager.SphereSource object at 0x4d2fad30>
+
>>> servermanager.LoadState("/Users/berk/myteststate.pvsm")
>>> pm=servermanager.ProxyManager()
+
# Make sure that the view in the state is the active one
>>> pm.RegisterProxy("foo", "bar", sph)
+
>>> SetActiveView(GetRenderView())
 +
# Now render
 +
>>> Render()
 +
# Get the list of sources
 +
>>> GetSources()
 +
{('Sphere1', '5'): <paraview.servermanager.Sphere object at 0xaf80e30>,
 +
('Shrink1', '11'): <paraview.servermanager.Shrink object at 0xaf80df0>,
 +
('Cone1', '8'): <paraview.servermanager.Cone object at 0xaf80cf0>}
 +
# Change the resolution of the cone and render again
 +
>>> FindSource("Cone1").Resolution = 32
 +
>>> Render()
 
</source>
 
</source>
  
In this example, we registered the sphere source proxy under the name “bar” in the group “foo”. We can verify that the proxy is registered.
+
You can also save state.
  
 
<source lang="python">
 
<source lang="python">
>>> print pm.GetProxy("foo", "bar")
+
>>> from paraview.simple import *
<paraview.servermanager.SphereSource object at 0x4d2fad30>
+
>>> sph = Sphere()
 +
>>> Render()
 +
>>> servermanager.SaveState("/Users/berk/pythonstate.pvsm")
 
</source>
 
</source>
  
If you are typing this script in the Python shell of the paraview application, you should see no change in the pipeline browser yet. The paraview application keeps the proxies registered under several predetermined groups and will not respond to the creation of arbitrary groups. Now try this:
+
==Dealing with Time==
 +
 
 +
If a reader or a filter supports time, it is easy to request a certain time step from Python. All time requests are set on views that then propagate them to the representations which then propagate them to the visualization pipeline. Here is an example demonstrating how a time request can be made:
  
 
<source lang="python">
 
<source lang="python">
>>> pm.RegisterProxy("sources", "mysource", sph)
+
>>> Show(ExodusIIReader(FileName=".../can.ex2"))
 +
>>> Render()
 +
# Get a nice view angle
 +
>>> cam = GetActiveCamera()
 +
>>> cam.Elevation(45)
 +
>>> Render()
 +
# Check the current view time
 +
>>> view = GetActiveView()
 +
>>> view.ViewTime
 +
0.0
 +
>>> reader = GetActiveSource()
 +
>>> reader.TimestepValues
 +
[0.0, 0.00010007373930420727, 0.00019990510190837085,  
 +
0.00029996439116075635, 0.00040008654468692839,  
 +
...]
 +
>>> tsteps = reader.TimestepValues
 +
# Let’s be fancy and use a time annotation filter. This will show the
 +
# current time value of the reader as text in the corner of the view.
 +
>>> annTime = AnnotateTimeFilter(reader)
 +
# Show the filter
 +
>>> Show(annTime)
 +
# Look at a few time steps. Note that the time value is requested not
 +
# the time step index.
 +
>>> view.ViewTime = tsteps[2]
 +
>>> Render()
 +
>>> view.ViewTime = tsteps[4]
 +
>>> Render()
 
</source>
 
</source>
  
You should now see something like this.
+
==Animating==
+
 
Note that the visibility of the new source is off. This is because there is no representation associated with it. You can simply click on the eye and have paraview create one or you can create on yourself. However, this requires a view. How do we get a proxy to the active view? We will learn in the next section. Let’s create and register an elevation filter next:
+
Server Manager has a complicated animation engine based on keyframes and scenes. This section will introduce a few simple ways of animating your visualization.  
 +
If you have a time-aware reader, you can animate it with AnimateReader().
  
 
<source lang="python">
 
<source lang="python">
>>> elev=servermanager.filters.ElevationFilter()
+
>>> reader = ExodusIIReader(FileName=“.../can.ex2”)
>>> elev.Input=sph
+
>>> Show(reader)
>>> pm.RegisterProxy("sources", "elev", elev)
+
>>> Render()
 +
>>> c = GetActiveCamera()
 +
>>> c.Elevation(95)
 +
# Animate over all time steps. Note that we are not passing the optional
 +
# 3rd argument here. If you pass a filename as the 3rd argument,
 +
# AnimateReader will create a movie.
 +
>>> AnimateReader(reader)
 +
# Save the animation to an avi file
 +
>>> AnimateReader(reader, filename=".../movie.avi")
 
</source>
 
</source>
  
Note: All algorithms (even filters) are registered in the “sources” group.
+
To animate properties other than time, you can use regular keyframes.
 +
 
 +
'''''ParaView 3.8.0 and earlier'''''
 +
----
 +
<font color="blue">Although the following script will work with 3.8.1 and later, it's not the recommended way since the changes done so will not be reflected in the GUI. Refer to the following sub-section for the recommended style for 3.8.1 and later versions.</font>
 +
 
 +
<source lang="python">
 +
>>> Sphere()
 +
>>> Show()
 +
>>> Render()
 +
 
 +
# Create an animation scene
 +
>>> scene = servermanager.animation.AnimationScene()
 +
# Add one view
 +
>>> scene.ViewModules = [GetActiveView()]
  
==Finding Registered Proxies==
+
# Create a cue to animate the StartTheta property
 +
>>> cue = servermanager.animation.KeyFrameAnimationCue()
 +
>>> cue.AnimatedProxy = GetActiveSource()
 +
>>> cue.AnimatedPropertyName = "StartTheta"
 +
# Add it to the scene's cues
 +
>>> scene.Cues = [cue]
  
If you know the group and registered name of the proxy, it is easy to get it:
+
# Create 2 keyframes for the StartTheta track
 +
>>> keyf0 = servermanager.animation.CompositeKeyFrame()
 +
>>> keyf0.Interpolation = 'Ramp'
 +
# At time = 0, value = 0
 +
>>> keyf0.KeyTime = 0
 +
>>> keyf0.KeyValues= [0]
 +
 
 +
>>> keyf1 = servermanager.animation.CompositeKeyFrame()
 +
# At time = 1.0, value = 200
 +
>>> keyf1.KeyTime = 1.0
 +
>>> keyf1.KeyValues= [200]
 +
 
 +
# Add keyframes.
 +
>>> cue.KeyFrames = [keyf0, keyf1]
 +
 
 +
>>> scene.Play()
 +
 
 +
# Some properties you can change
 +
#
 +
# Number of frames used in Sequence mode
 +
# scene.NumberOfFrames = 100
 +
#
 +
# Or you can use real time mode
 +
# scene.PlayMode = 'Real Time'
 +
# scene.Duration = 20
 +
</source>
 +
 
 +
 
 +
'''ParaView 3.8.1 onwards'''
 +
----
 +
<font color="blue">The following script will only work with ParaView versions 3.8.1 and later.
 +
It is now the recommended way for accessing animation scenes and tracks since the updates
 +
are reflected in the GUI when running through the Python shell from the ParaView application.
 +
</font>
  
 
<source lang="python">
 
<source lang="python">
>>> print pm.GetProxy("sources", "elev")
+
>>> Sphere()
<paraview.servermanager.ElevationFilter object at 0x4f4373b0>
+
>>> Show()
 +
>>> Render()
 +
 
 +
# Get the application-wide animation scene
 +
>>> scene = GetAnimationScene()
 +
 
 +
# Get the animation track for animating "StartTheta" on the active source.
 +
# GetAnimationTrack() creates a new track if none exists.
 +
>>> cue = GetAnimationTrack("StartTheta")
 +
 
 +
# Create 2 keyframes for the StartTheta track
 +
>>> keyf0 = CompositeKeyFrame()
 +
>>> keyf0.Interpolation = 'Ramp'
 +
# At time = 0, value = 0
 +
>>> keyf0.KeyTime = 0
 +
>>> keyf0.KeyValues= [0]
 +
 
 +
>>> keyf1 = CompositeKeyFrame()
 +
# At time = 1.0, value = 200
 +
>>> keyf1.KeyTime = 1.0
 +
>>> keyf1.KeyValues= [200]
 +
 
 +
# Add keyframes.
 +
>>> cue.KeyFrames = [keyf0, keyf1]
 +
 
 +
>>> scene.Play()
 +
 
 +
# Some properties you can change
 +
#
 +
# Number of frames used in Sequence mode
 +
# scene.NumberOfFrames = 100
 +
#
 +
# Or you can use real time mode
 +
# scene.PlayMode = 'Real Time'
 +
# scene.Duration = 20
 
</source>
 
</source>
  
This is the easiest way of getting access to an algorithm proxy created using the user interface since it is registered under the group “sources” using the name shown in the pipeline browser.
+
===GetAnimationTrack Usages===
If you only know the group the proxy is registered in, you can get all proxies registered in a group by using introspection.
+
----
  
 
<source lang="python">
 
<source lang="python">
>>> print pm.GetProxiesInGroup("sources")
+
 
{'mysource': <paraview.servermanager.SphereSource object at 0x4d2fad30>, 'elev': <paraview.servermanager.ElevationFilter object at 0x4f4373b0>}
+
# Typical usage
 +
>>> track = GetAnimationTrack("Center", 0, sphere) or
 +
>>> track = GetAnimationTrack(sphere.GetProperty("Radius")) or
 +
 
 +
# this returns the track to animate visibility of the active source in
 +
# all views.
 +
>>> track = GetAnimationTrack("Visibility")
 +
 
 +
# For animating properties on implicit planes etc., use the following
 +
# signatures:
 +
>>> track = GetAnimationTrack(slice.SliceType.GetProperty("Origin"), 0) or
 +
>>> track = GetAnimationTrack("Origin", 0, slice.SliceType)
 +
 
 
</source>
 
</source>
  
Note that GetProxiesInGroup() returns a dictionary that uses the registration name as the key. We can use this method to get our view.
+
==Loading Data Files==
 +
 
 +
As seen throughout this document, you can always load a data file by explicitly creating the reader that can read the data file as follows:
  
 
<source lang="python">
 
<source lang="python">
>>> print pm.GetProxiesInGroup("views")
+
>>> reader = ExodusIIReader(FileName=“.../can.ex2”)
{'RenderView1': <paraview.servermanager.RenderView object at 0x4f4376b0>}
 
 
</source>
 
</source>
  
Here, I made use of the fact that views are registered under “views”. Now we can create a representation for our source.
+
Alternatively, starting with ParaView 3.8, you can use OpenDataFile() function to let ParaView pick a reader using the extension of the file.
  
 
<source lang="python">
 
<source lang="python">
>>> view = pm.GetProxy("views", "RenderView1")
+
>>> reader = OpenDataFile(.../can.ex2”)
>>> print view
 
<paraview.servermanager.RenderView object at 0x4f437610>
 
>>> rep = servermanager.CreateRepresentation(sph, view)
 
>>> print rep
 
<paraview.servermanager.GeometryRepresentation object at 0x4f4376b0>
 
>>> pm.RegisterProxy("representations", "myrep1", rep)
 
 
</source>
 
</source>
  
To make sure that the user interface is notified of this representation, we registered it under the group “representations”.
+
 
If you do not know the group or the name of the proxy, you can iterate over all proxies and search for the one you are interested in.
+
==Writing Data Files (ParaView 3.9 or later)==
 +
 
 +
To create a writer to write the output from a source, one can use the following:
  
 
<source lang="python">
 
<source lang="python">
>>> for proxy in pm:
+
from paraview.simple import *
... print proxy
+
 
 +
# Specifying the source explicitly
 +
>>> writer= CreateWriter("/.../filename.vtk", source)
 +
 
 +
# Using the active source
 +
>>> writer= CreateWriter("/.../filename.vtk")
 +
 
 +
# Writing data from a particular output port
 +
>>> writer= CreateWriter("/.../filename.vtk", servermanager.OutputPort(source, 1))
 +
 
 +
# Now one change change the ivars on the writer
 +
 
 +
# To do the actual writing, use:
 +
>>> writer.UpdatePipeline()
 +
 
 +
</source>
 +
 
 +
==Exporting CSV Data==
 +
 
 +
To export a csv from the cell or point data associated with a source, one can use the following:
 +
 
 +
<source lang="python">
 +
>>> writer = CreateWriter(".../foo.csv", source)
 +
>>> writer.FieldAssociation = "Points" # or "Cells"
 +
>>> writer.UpdatePipeline()
 +
>>> del writer
 +
</source>
 +
 
 +
==Updating View Layout==
 +
 
 +
Starting with ParaView 3.14, Python scripts can be used to update view layout.
 +
 
 +
Every tab in the central frame of the ParaView application is represented by '''layout''' proxy. To obtain a map of layout proxies present, use the GetLayouts().
 +
 
 +
<source lang="python">
 +
>>> GetLayouts()
 +
{('ViewLayout1', '264'): <paraview.servermanager.ViewLayout object at 0x2e5b7d0>}
 +
</source>
 +
 
 +
To get the layout corresponding to the active view (or a particular view), use the GetLayout() function.
 +
 
 +
<source lang="python">
 +
>>> GetLayout()
 +
<paraview.servermanager.ViewLayout object at 0x2e5b7d0>
 +
>>>
 +
>>> GetLayout(GetActiveView())
 +
<paraview.servermanager.ViewLayout object at 0x2e5b7d0>
 +
</source>
 +
 
 +
To split the cell containing a particular view, either horizontally or vertically, use:
 +
 
 +
<source lang="python">
 +
 
 +
>>> layout.SplitViewVertical(view = GetActiveView())
 +
 
 +
>>> layout.SplitViewHorizontal(view = GetActiveView(), fraction = 0.7)
 +
 
 
</source>
 
</source>
  
The methods covered here are enough to accomplish most tasks. For information on other methods, see the ProxyManager, ProxyIterator and vtkSMProxyIterator10 documentation.
+
To resize a cell containing a particular view:
  
=Advanced Concepts=
+
<source lang="python">
  
==Loading State and Manipulating It==
+
>>> location = layout.GetViewLocation(view)
 +
>>> layout.SetSplitFraction(location, 0.3)
  
Let’s say you created a complicated visualization using the paraview application and now you want to make slight changes to it and run it in a loop as a batch script. What do you do? The best way of dealing with this is to save your visualization state and then load it from Python. Let’s say you have a state file saved as myteststate.pvsm:
+
</source>
  
 +
To maximize a particular view
 
<source lang="python">
 
<source lang="python">
>>> from paraview import servermanager
+
 
# Connect to a server running on the localhost
+
>>> location = layout.GetViewLocation(view)
>>> servermanager.Connect("localhost")
+
>>> layout.MaximizeCell(location)
Connection (localhost:11111)
+
 
# Load the state
 
>>> servermanager.LoadState("/Users/berk/myteststate.pvsm")
 
# Use the utility method to get the first render view. We could have
 
# looked in the “views” group instead.
 
>>> view = servermanager.GetRenderView()
 
# Render the scene
 
>>> view.StillRender()
 
 
</source>
 
</source>
  
Once the state is loaded, you can access the new proxies using the Proxy Manager and the introspection methods described in the previous section.
+
There are a host of other methods that are available that can help with layout of the views. Refer to the API exposed by vtkSMViewLayoutProxy. The API is fully accessible through Python.
  
You can also save state.
+
To create a new tab, one can use the following piece of code:
  
 
<source lang="python">
 
<source lang="python">
>>> from paraview import servermanager
+
 
>>> servermanager.Connect()
+
  new_layout = servermanager.misc.ViewLayout(registrationGroup="layouts")
Connection (builtin:5)
+
 
>>> sph = servermanager.sources.SphereSource()
+
</source>
>>> view = servermanager.CreateRenderView()
+
 
>>> rep = servermanager.CreateRepresentation(sph, view)
+
==Multiple Renders==
>>> view.StillRender()
+
 
>>> view.ResetCamera()
+
When working in an interactive python session, the Render() command will open a new graphical window. If this window is closed before a subsequent Render() call, the new Render() call will cause the interactive python session to exit with an error like:
>>> view.StillRender()
+
 
# Make sure proxies are registered; otherwise they won’t show
+
<source lang="bash">
# up in the state.
+
 
>>> pm = servermanager.ProxyManager()
+
XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
>>> pm.RegisterProxy("sources", "sph", sph)
+
 
>>> pm.RegisterProxy("representations", "d1", rep)
 
>>> pm.RegisterProxy("views", "v1", view)
 
>>> servermanager.SaveState("/Users/berk/pythonstate.pvsm")
 
 
</source>
 
</source>
 +
 +
Take away: leave the graphical window open for the duration of your python/paraview session in order for multiple Render() calls to work.
 +
 +
{{ParaView/Template/Footer}}

Latest revision as of 05:58, 2 December 2019

Katie O adding to ParaView Guide LaTex

Note: This document if based on ParaView 3.6 or higher. If you are using 3.4, go to the history page and select the version from May 13, 2009.

ParaView and Python

ParaView offers rich scripting support through Python. This support is available as part of the ParaView client (paraview), an MPI-enabled batch application (pvbatch), the ParaView python client (pvpython), or any other Python-enabled application. Using Python, users and developers can gain access to the ParaView engine called Server Manager.

Note: Server Manager is a library that is designed to make it easy to build distributed client-server applications.

This document is a short introduction to ParaView's Python interface. You may also visit the Python recipes page for some examples.

Quick Start - a Tutorial

Getting Started

To start interacting with the Server Manager, you have to load the "simple" module. This module can be loaded from any python interpreter as long as the necessary files are in PYTHONPATH. These files are the shared libraries located in the paraview binary directory and python modules in the paraview directory: paraview/simple.py, paraview/vtk.py etc. You can also use either pvpython (for stand-alone or client/server execution), pvbatch (for non-interactive, distributed batch processing) or the python shell invoked from Tools|Python Shell using the ParaView client to execute Python scripts. You do not have to set PYTHONPATH when using these.

This tutorial will be using the python integrated development environment IDLE. PYTHONPATH is set to the following:

/Users/berk/work/paraview3-build/lib:/Users/berk/work/paraview3-build/lib/site-packages

Note that depending on your build configuration, your *.libs files may not be under "lib" but under one of its sub-folders, like "lib/Release" or "lib/Debug". In those cases add the correct folder where the *.libs reside:

/Users/berk/work/paraview3-build/lib/Release:/Users/berk/work/paraview3-build/lib/site-packages

Note: For older versions of ParaView this was /Users/berk/work/paraview3-build/bin:/Users/berk/work/paraview3-build/Utilities/VTKPythonWrapping/site-packages --Andy.bauer 24 January 2013, or /Users/berk/work/paraview3-build/bin:/Users/berk/work/paraview3-build/Utilities/VTKPythonWrapping --Andy.bauer 23 July 2010.

You may also need to set your path variable for searching for shared libraries (i.e. PATH on Windows and LD_LIBRARY_PATH on Unix/Linux/Mac). The corresponding LD_LIBRARY_PATH would be:

 /Users/berk/work/paraview3-build/lib (/Users/berk/work/paraview3-build/bin for versions before 3.98)

(Under WindowsXP for a debug build of paraview, set both PATH and PYTHONPATH environment variables to include ${BUILD}/lib/Debug and ${BUILD}/lib/site-packages to make it work.)

When using a Mac to use the build tree in IDLE, start by loading the servermanager module:

>>> from paraview.simple import *

Note: Importing the paraview module directly is deprecated, although still possible for backwards compatibility. This document refers to the simple module alone.

In this example, we will use ParaView in the stand-alone mode. Connecting to a ParaView server running on a cluster is covered later in this document.

Tab-completion

The Python shell in the ParaView Qt client provides auto-completion. One can also use IDLE, for example to enable auto-completion. To use auto-completion in pvpython, one can use the tips provided at [1].

In summary, you need to create a variable PYTHONSTARTUP as (in bash):

 export PYTHONSTARTUP = /home/<username>/.pythonrc

where .pythonrc is:

    # ~/.pythonrc
    # enable syntax completion
    try:
        import readline
    except ImportError:
        print "Module readline not available."
    else:
        import rlcompleter
        readline.parse_and_bind("tab: complete")

That is it. Tab completion works just as in any other shell.

Creating a Pipeline

The simple module contains many functions to instantiate sources, filters, and other related objects. You can get a list of objects this module can create from ParaView's online help (from help menu or here: http://paraview.org/OnlineHelpCurrent/)

Start by creating a Cone object:

>>> cone = Cone()

You can get some documentation about the cone object using help().

>>> help(cone)
Help on Cone in module paraview.servermanager object:

class Cone(SourceProxy)
 |  The Cone source can be used to add a polygonal cone to the 3D scene. The output of the 
 Cone source is polygonal data.
 |  
 |  Method resolution order:
 |      Cone
 |      SourceProxy
 |      Proxy
 |      __builtin__.object
 |  
 |  Methods defined here:
 |  
 |  Initialize = aInitialize(self, connection=None)
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  Capping
 |      If this property is set to 1, the base of the cone will be capped with a filled polygon. 
 Otherwise, the base of the cone will be open.
 |  
 |  Center
 |      This property specifies the center of the cone.
 |  
 |  Direction
 |      Set the orientation vector of the cone.  The vector does not have to be normalized.  The cone 
 will point in the direction specified.
 |  
 |  Height
 |      This property specifies the height of the cone.
 |  
 |  Radius
 |      This property specifies the radius of the base of the cone.
 |  
 |  Resolution
 |      This property indicates the number of divisions around the cone. The higher this number, the 
 closer the polygonal approximation will come to representing a cone, and the more polygons it will 
 contain.
 |  
 |...

This gives you a full list of properties. Check what the resolution property is set to:

>>> cone.Resolution
6

You can increase the resolution as shown below:

>>> cone.Resolution = 32

Alternatively, we could have specified a value for resolution when creating the object:

>>> cone = Cone(Resolution=32)

You can assign values to any number of properties during construction using keyword arguments: You can also change the center.

>>> cone.Center
[0.0, 0.0, 0.0]
>>> cone.Center = [1, 2, 3]

Vector properties such as this one support setting and retrieval of individual elements, as well as slices (ranges of elements):

>>> cone.Center[0:2] = [2, 4]
>>> cone.Center
[2.0, 4.0, 3.0]

Next, apply a shrink filter to the cone:

>>> shrinkFilter = Shrink(cone)
>>> shrinkFilter.Input
<paraview.servermanager.Cone object at 0xaf701f0>

At this point, if you are interested in getting some information about the output of the shrink filter, you can force it to update (which will also cause the execution of the cone source). For details about VTK's demand-driven pipeline model used by ParaView, see one of the VTK books.

>>> shrinkFilter.UpdatePipeline()
>>> shrinkFilter.GetDataInformation().GetNumberOfCells()
33L
>>> shrinkFilter.GetDataInformation().GetNumberOfPoints()
128L

We will cover the DataInformation class in more detail later.

Rendering

Now that you've created a small pipeline, render the result. You will need two objects to render the output of an algorithm in a scene: a representation and a view. A representation is responsible for taking a data object and rendering it in a view. A view is responsible for managing a render context and a collection of representations. Simple creates a view by default. The representation object is created automatically with Show().

>>> Show(shrinkFilter)
>>> Render()

Et voila:

Figure 14.1 Server manager snapshot

In example Figure 14.1, the value returned by Cone() and Shrink() was assigned to Python variables and used to build the pipeline. ParaView keeps track of the last pipeline object created by the user. This allows you to accomplish everything you did above using the following code:

>>> from paraview.simple import *
# Create a cone and assign it as the active object
>>> Cone()
<paraview.servermanager.Cone object at 0x2910f0>
# Set a property of the active object
>>> SetProperties(Resolution=32)
# Apply the shrink filter to the active object
# Shrink is now active
>>> Shrink() 
<paraview.servermanager.Shrink object at 0xaf64050>
# Show shrink
>>> Show() 
<paraview.servermanager.UnstructuredGridRepresentation object at 0xaf57f90>
# Render the active view
>>> Render() 
<paraview.servermanager.RenderView object at 0xaf57ff0>

This was a quick introduction to the paraview.simple module. In the following sections, we will discuss the Python interface in more detail and introduce more advanced concepts.

paraview.simple Module

The simple module is a ParaView component written using Python on top of the Server Manager C++ library. Its purpose is to make it easier to create ParaView data analysis and visualization pipelines using Python. The simple module can be loaded from Python interpreters running in several applications.

  • pvpython: The pvpython application, distributed with the ParaView application suite, is a Python client to the ParaView servers. It supports interactive execution as well as batch execution.
  • pvbatch: The pvbatch application, also distributed with the ParaView application suite, is a Python application designed to run batch scripts on distributed servers. When ParaView is compiled with MPI, pvbatch can be launched as an MPI program. In this mode, the first node will load a Python script specified as a command-line argument and execute it using a special built-in connection on all nodes. This application does not support interactive execution.
  • paraview: Python scripts can be run from the paraview client using the Python shell that is invoked from Tools|Python Shell. The Python shell supports interactive mode as well as loading of scripts from file.
  • External Python interpreter: Any Python-capable application can load the paraview.simple module if the right environment is configured. For this to work, you either have to install the paraview Python modules (including the right shared libraries) somewhere in sys.path or you have to set PYTHONPATH to point to the right locations.

Overview

The paraview.simple module contains several Python classes designed to be Python-friendly, as well as all classes wrapped from the C++ Server Manager library. The following sections cover the usage of this module and occasionally the paraview.servermanager module, which is lower level.

Connecting to a Server

ParaView can run in two modes: stand-alone and client/server where the server is usually a visualization cluster. In this section, we discuss how to establish a connection to a server when using ParaView in the client/server mode. If you are using the ParaView graphical interface, you should use Connect from the File menu to connect to a server. If you are using ParaView from a Python shell (not the Python console that is part of the graphical interface), you need to use servermanager.Connect() to connect a server. Note: you cannot connect to the ParaView application from a stand-alone Python shell. You can only connect to a server. This method takes four arguments, all of which have default values.

def Connect(ds_host=None, ds_port=11111, rs_host=None, rs_port=11111)

When connecting to a server (pvserver), specify only the first two arguments. These are the server name (or IP address) and port number.

When connecting to a data-server/render-server pair, you have to specify all four arguments. The first two are the host name (or IP address) and port number of the data server, the last two those of the render server. Here are some examples:

# Connect to pvserver running on amber1 (first node of our test cluster)
# using the default port 11111
>>> Connect(amber1)

# Connect to pvdataserver running on the amber cluster, pvrenderserver 
# running on Berk’s desktop
>>> Connect(amber1, 12000, kamino, 11111)

Note: Connect() will return None on failure. To be safe, you should check the return value of Connect().

Getting Help

You can access the documentation of all Proxy types by using Python's built-in help.

>>> help(paraview.simple.Cone)
Help on function CreateObject in module paraview.simple:

CreateObject(*input, **params)
    The Cone source can be used to add a polygonal cone to the 3D scene. The output of the 
    Cone source is polygonal data.

To get the full documentation, you have to create an instance.

>>> c = Cone()
>>> help(c)

This documentation is automatically generated from the Server Manager configuration files. It is identical to the class documentation found under the ParaView Help menu, as well as here: http://paraview.org/OnlineHelpCurrent/. Beyond this document and the online help, there are a few useful documentation sources:


If you are interested in learning more about the Visualization Toolkit that is at the foundation of ParaView, visit http://vtk.org.

Proxies and Properties

Proxies

The VTK Server Manager design uses the Proxy design pattern (See Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides for details). Quoting from Wikipedia: “A proxy, in its most general form, is a class functioning as an interface to another thing. The other thing could be anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate”. In the case of Server Manager, a Proxy object acts as a proxy to one-or-more VTK objects. Most of the time, these are server-side objects and are distributed to the server nodes. Proxy objects allow you to interact with these objects as if you directly have access to them, manipulate them, and obtain information about them. When creating visualization pipelines, you create proxies instead of VTK objects.

>>> sphereSource = vtk.vtkSphereSource() # VTK-Python script

>>> sphereSourceP = Sphere() # ParaView script

A proxy also provides an interface to modify the properties of the objects it maintains. For example, instead of:

>>> sphereSource.SetCenter(1.0, 1.0, 0.0)

you can write the following:

>>> sphere.Center = [1.0, 1.0, 0.0]

When a pipeline object proxy is created, it is set as the active object. You can also set an object as the active one. This is equivalent to clicking-on an object in the pipeline browser.

>>> c = Cone()
<paraview.servermanager.Cone object at 0xaf73090>
>>> GetActiveSource()
<paraview.servermanager.Cone object at 0xaf73090>
>>> Shrink()
<paraview.servermanager.Shrink object at 0xb4f8610>
# Make the cone active
>>> SetActiveSource(c)

When dealing with objects created through the graphical interface or by loading a state, it is useful to be able to search through existing pipeline objects. To accomplish this, you can use GetSources() and FindSource(). GetSources() returns a dictionary of (name, id) object pairs. Since multiple objects can have the same name, the (name,id) pair identifies objects uniquely. FindSource() returns an object given its name. If there are more than one objects with the same name, the first one is returned.

>>> Cone()
<paraview.servermanager.Cone object at 0xaf73090>
>>> GetActiveSource()
<paraview.servermanager.Cone object at 0xaf73090>
>>> Shrink()
<paraview.servermanager.Shrink object at 0xb4f8610>
>>> SetActiveSource(c)

To delete pipeline objects, you need to use the Delete() function. Simply letting a Python variable go out of scope is not enough to delete the object. Following the example above:

# Delete the cone source
>>> Delete(c)
# To fully remove the cone from memory, get rid of the
# variable too
>>> del c

If you do not use a Python variable to hold the value returned by the pipeline object proxy constructor, the following is needed to delete the object:

Cone() # not: c = Cone()
# to delete this object:
# First, delete its entry in the ParaView's pipeline GUI or call Delete(FindSource("Cone1"))
# Then, this is needed:
import gc
gc.collect()


Please note that for destructors to be called, calls such as c = FindSource("name"), respecively FindSource("name") will also require the call to del(c), respectively gc.collect() afterward.

Properties

Property objects are used to read and modify the properties of pipeline objects. Each proxy has a list of properties defined in the Server Manager configuration files. The property interface of the Server Manager C++ library is somewhat cumbersome. Here is how you can set the radius property of a sphere source:

>>> rp = sphere.GetProperty("Radius")
>>> rp.SetElement(0, 2)
1
>>> sphere.UpdateProperty("Radius")

The servermanager module makes property access much easier by defining Python property accessors for property objects:

>>> sphere.Radius = 3

Here, Radius is a Python property which, when a value is assigned to it, calls sphere.SetPropertyWithName("Radius",3). Properties can also passed to the function creating the object:

>>> cone = Cone(Radius=0.5, Center=[1, 0.5, 0])
<paraview.servermanager.Cone object at 0xaf73090>

You can also use the SetProperties() function to set property values.

>>> SetProperties(cone, Radius=0.2, Center=[2, 0.5, 0])

If the first argument is not specified, the active object is used. You also use SetDisplayProperties() and SetViewProperties() to set display (representation) and view properties respectively.

All Property classes define the following methods:

  • __len__()
  • __getitem__()
  • __setitem__()
  • __getslice__()
  • __setslice__()
  • GetData()
  • SetData().

Therefore, all of the following are supported:

>>> sphere.Center
[0.0, 0.0, 0.0]
>>> sphere.Center[0] = 1
>>> sphere.Center[0:3] = [1,2,3]
>>> sphere.Center[0:3]
[1.0, 2.0, 3.0]
>>> len(sphere.Center)
3

ProxyProperty and InputProperty also define

  • append()
  • __delitem__()
  • __delslice__()

to support del() and append(), similar to Python list objects.

VectorProperty is used for scalars, vectors and lists of integer and floating point numbers as well as strings. Most properties of this type are simple. Examples include Sphere.Radius (double scalar), Sphere.Center (vector of doubles), a2DGlyph.Filled (boolean), a2DGlyph.GlyphType (enumeration), a3DText.Text (string), and Contour.Isosurfaces (list of doubles). Some properties may be more complicated because they map to C++ methods with mixed argument types. Two good examples of this case are Glyph.Scalars and ExodusIIReader.PointVariables.

>>> reader = ExodusIIReader(FileName='.../can.ex2')
# These variables are currently selected
>>> reader.PointVariables
['DISPL', 'VEL', 'ACCL']
# These are available in the file
>>> reader.PointVariables.Available
['DISPL', 'VEL', 'ACCL']
# Enable the DISPL array only
>>> reader.PointVariables = ['DISPL']
# Force read
>>> reader.UpdatePipeline()
# Now check the output. Note: GlobalNodeId is generated automatically by the reader.
>>> reader.PointData[:]
[Array: GlobalNodeId, Array: PedigreeNodeId, Array: DISPL]

This example demonstrates the use of ExodusIIReader.PointVariables. This is a VectorProperty that represents a list of array names. The underlying C++ function has a signature of SetPointResultArrayStatus(const char* name, int flag). This method is usually called once per array to enable or disable it (i.e. to set whether the reader will read a particular array).

Glyph.Scalars is a bit more complicated. This property allows the developer to select the scalar array with which to scale the glyphs.

>>> sph = Sphere()
>>> elev=Elevation(sph)
# Glyph the points of the sphere with spheres
>>> glyph=Glyph(elev, GlyphType='Sphere')
# Scale the glyph with the Elevation array
>>> glyph.Scalars = 'Elevation'
>>> glyph.Scalars
['POINTS', 'Elevation']
# The above shows the association of the array as well as its name.
# In this case, the array is associated with POINTS as it has to be
# since Glyph cannot scale by cell arrays. We could have done:
>>> glyph.Scalars = ['POINTS', 'Elevation']
# Enable scaling by scalars
>>> glyph.ScaleMode = 'scalar'

Here the property Scalars maps to SetInputArrayToProcess(int idx, int port, int connection, int fieldAssociation, const char *name), which has four integer arguments (some of which are enumeration) and one string argument (see vtkAlgorithm documentation for details).

Properties are either regular (push) or information (pull) properties. Information properties do not have a VTK method associated with them and are responsible for getting information from the server. A good example of an information property is TimestepValues, which returns all time steps available in a file (if the reader supports time).

>>> reader = ExodusIIReader(FileName='.../can.ex2')
>>> reader.TimestepValues
[0.0, 0.00010007373930420727, 0.00019990510190837085, 0.00029996439116075635, 0.00040008654468692839,
 0.00049991923151537776, 0.00059993512695655227, 0.00070004, ...]

You can obtain a list of properties a proxy supports by using help(). However, this does not allow introspection programmatically. If you need to obtain information about a proxy’s properties programmatically, you can use a property iterator:

>>> for prop in glyph:
	print type(prop), prop.GetXMLLabel()

<class 'paraview.servermanager.InputProperty'> Input
<class 'paraview.servermanager.VectorProperty'> Maximum Number of Points
<class 'paraview.servermanager.VectorProperty'> Random Mode
<class 'paraview.servermanager.ArraySelectionProperty'> Scalars
<class 'paraview.servermanager.ArraySelectionProperty'> Vectors
<class 'paraview.servermanager.VectorProperty'> Orient
<class 'paraview.servermanager.VectorProperty'> Set Scale Factor
<class 'paraview.servermanager.EnumerationProperty'> Scale Mode
<class 'paraview.servermanager.InputProperty'> Glyph Type
<class 'paraview.servermanager.VectorProperty'> Mask Points

The XMLLabel is the text display by the graphical user-interface. Note that there is a direct mapping from the XMLLabel to the property name. If you remove all spaces from the label, you get the property name. You can use the PropertyIterator object directly.

>>> it = iter(s)
>>> for i in it:
	print it.GetKey(), it.GetProperty()

Domains

The Server Manager provides information about values that are valid for properties. The main use of this information is for the user-interface to provide good ranges and choices in enumeration. However, some of this information is also very useful for introspection. For example, enumeration properties look like simple integer properties unless a (value, name) pair is associated with them. The Server Manager uses Domain objects to store this information. The contents of domains may be loaded from xml configuration files or computed automatically. For example:

>>> s = Sphere()
>>> Show(s)
>>> dp = GetDisplayProperties(s)
>>> dp.Representation
'Surface'
# The current representation type is Surface. What other types
# are available?
>>> dp.GetProperty("Representation").Available
['Outline', 'Points', 'Wireframe', 'Surface', 'Surface With Edges']
# Choose outline
>>> dp.Representation = 'Outline'

Source Proxies

Source proxies are proxies that represent pipeline objects (For more information about VTK pipelines, see the VTK books: http://vtk.org/buy-books.php). They have special properties to connect them as well as special method to query the meta-data of their output. To connect a source proxy to another, use one of its input properties.

# Either
>>> glyph = Glyph(elev)
# or
>>> glyph.Input = elev

The SourceProxy class provides several additional properties and methods that are specific to pipelines (See vtkSMSourceProxy documentation for a full list).

  • UpdatePipelineInformation(): This method calls UpdateInformation() on the VTK algorithm. It also calls UpdatePropertyInformation() to update any information properties.
  • UpdatePipeline(): This method calls Update() on the VTK algorithm causing a pipeline execution if the pipeline changed. Another way of causing pipeline updates is to render. The render view updates all connected pipelines.
  • GetDataInformation(): This method is used to obtain meta-data about one output. It is discussed further below.
  • PointData and CellData properties discussed below.

There are two common ways of getting meta-data information from a proxy: information properties and DataInformation. Information properties are updated automatically every time UpdatePropertyInformation() and UpdatePipelineInformation() are called. All you have to do is read the data from the property as usual. To get a DataInformation object from a source proxy use GetDataInformation(port=0). By default, this method returns data information for the first output. You can pass an optional port number to get information for another output. You can get detailed documentation on DataInformation by using help() and by reading online documentation for vtkPVDataInformation (http://www.paraview.org/doc/nightly/html/classvtkPVDataInformation.html). Here are the use of some common methods:

>>> di = glyph.GetDataInformation(0)
>>> di
<paraview.servermanager.DataInformation object at 0x2d0920d0>
>>> glyph.UpdatePipeline()
# Get the data type.
>>> di.GetDataClassName()
'vtkPolyData'
# Get information about point data. 
>>> pdi = glyph.PointData
# We are now directly accessing the wrapper for a VTK class
>>> len(pdi)
2
# Get information for a point array
>>> ai = pdi[0]
>>> ai.GetRange(0)
(0.0, 0.5)

When meta-data is not enough and you need access to the raw data, you can use Fetch() to bring it to the client side. Note that this function is provided by the servermanager module. Fetch() has three modes:

  • Append all of the data together and bring it to the client (only available for polygonal and unstructured datasets). Note: Do not do this if data is large otherwise the client will run out of memory.
  • Bring data from a given process to the client.
  • Use a reduction algorithm and bring its output to the client. For example, find the minimum value of an attribute.

Here is a demonstration:

>>> from paraview.simple import *
>>> Connect("kamino")
Connection (kamino:11111)
>>> s = Sphere()
# Get the whole sphere. DO NOT DO THIS IF THE DATA IS LARGE otherwise
# the client will run out of memory.
>>> allsphere = servermanager.Fetch(s)
getting appended
use append poly data filter
>>> allsphere.GetNumberOfPolys()
96
# Get the piece of the sphere on process 0.
>>> onesphere = servermanager.Fetch(s, 0)
getting node 0
>>> onesphere.GetNumberOfPolys()
48
# Apply the elevation filter so that we have a useful scalar array.
>>> elev = Elevation(s)
# We will use the MinMax algorithm to compute the minimum value of
# elevation. MinMax will be first applied on each processor. The results
# will then be gathered to the first node. MinMax will be then applied
# to the gathered results.
# We first create MinMax without an input.
>>> mm = MinMax(None)
# Set it to compute min
>>> mm.Operation = "MIN"
# Get the minimum
>>> mindata = servermanager.Fetch(elev, mm, mm)
applying operation
# The result is a vtkPolyData with one point
>>> mindata.GetPointData().GetNumberOfArrays()
2
>>> a0 = mindata.GetPointData().GetArray(1)
>>> a0.GetName()
'Elevation'
>>> a0.GetTuple1(0)
0.0

Representations and Views

Once a pipeline is created, it can be rendered using representations and views. A view is essentially a “window” in which multiple representations can be displayed. When the view is a VTK view (such as RenderView), this corresponds to a collection of objects including vtkRenderers and a vtkRenderWindow. However, there is no requirement for a view to be a VTK view or to render anything. A representation is a collection of objects, usually a pipeline, that takes a data object, converts it to something that can be rendered, and renders it. When the view is a VTK view, this corresponds to a collection of objects including geometry filters, level-of-detail algorithms, vtkMappers and vtkActors. The simple module automatically creates a view after connecting to a server (including the built-in connection when using the stand-alone mode). Furthermore, the simple module creates a representation the first time a pipeline object is displayed with Show(). It is easy to create new views.

>>> view = CreateRenderView()

CreateRenderView() is a special method that creates the render view appropriate for the ActiveConnection (or for another connection specified as an argument). It returns a sub-class of Proxy. Like the constructor of Proxy, it can take an arbitrary number of keyword arguments to set initial values for properties. Note that ParaView makes the view that was created last the active view. When using Show() without a view argument, the pipeline is shown in the active view. You can get a list of views as well as the active view as follows:

>>> GetRenderViews()
[<paraview.servermanager.RenderView object at 0xaf64ef0>, <paraview.servermanager.RenderView object at 0xaf64b70>]
>>> GetActiveView()
<paraview.servermanager.RenderView object at 0xaf64b70>

You can also change the active view using SetActiveView().

Once you have a render view, you can use pass it to Show in order to select in which view a pipeline object is displayed. You can also pass it to Render() to select which view is rendered.

>>> Show(elev, GetRenderViews()[1])
<paraview.servermanager.GeometryRepresentation object at 0xaf64e30>
>>> Render(GetRenderViews()[1])

Notice that Show() returns a representation object (aka DisplayProperties in the simple module). This object can be used to manipulate how the pipeline object is displayed in the view. You can also access the display properties of an object using GetDisplayProperties().

>>> dp = GetDisplayProperties(elev)
>>> dp
<paraview.servermanager.GeometryRepresentation object at 0xaf649d0>

Display properties and views have a large number of properties some of which are poorly documented. We will cover some them here.

>>> from paraview.simple import *
# Create a simple pipeline
>>> sph = Sphere()
>>> elev = Elevation(sph)
>>> Show(elev)
>>> Render()
# Set the representation type of elev
>>> dp = GetDisplayProperties(elev)
>>> dp.Representation = 'Points'
# Here is how you get the list of representation types
>>> dp.GetProperty("Representation").Available
['Outline', 'Points', 'Wireframe', 'Surface', 'Surface With Edges']
>>> Render()
# Change the representation to wireframe
>>> dp.Representation = 'Wireframe'
>>> Render()
# Let’s get some information about the output of the elevation
# filter. We want to color the representation by one of it’s
# arrays.
# Second array = Elevation. Interesting. Let’s use this one.
>>> ai = elev.PointData[1]
>>> ai.GetName()
'Elevation'
# What is its range?
>>> ai.GetRange()
(0.0, 0.5)
# To color the representation by an array, we need to first create
# a lookup table.  We use the range of the Elevation array
>>> dp.LookupTable = MakeBlueToRedLT(0, 0.5)
>>> dp.ColorAttributeType = 'POINT_DATA'
>>> dp.ColorArrayName = 'Elevation' # color by Elevation
>>> Render()

Here is the result:

Figure 14.2 Object displayed in a view


Once you create a scene, you will probably want to interact with the camera and ResetCamera() is likely to be insufficient. In this case, you can directly get the camera from the view and manipulate it. GetActiveCamera() returns a VTK object (not a proxy) with which you can interact.

>>> camera = GetActiveCamera()
>>> camera
<libvtkCommonPython.vtkCamera vtkobject at 0xe290>
>>> camera.Elevation(45)
>>> Render()

Another common thing to do is to save the view as an image. For this purpose, you can use the WriteImage() method provided by the view:

>> WriteImage("/Users/berk/image.png")

The resulting image.png looks like this. See the documentation for WriteImage() for details on choosing file type, as well as a magnification factor to save images larger than the view size.

Figure 14.3 Saving a view as an image

Advanced Concepts

Dealing with lookup tables

In v4.1 LUT manipulation was simplified so that the LUTs found in the GUI may be assigned to arrays by name. See Lookup tables recipe for more information.

As shown earlier, you can use MakeBlueToRedLt(min, max) to create a lookup table. However, this simply creates a new lookup table that the GUI won't be aware of. In the ParaView Qt application, we have special lookup table management that ensures that the same lookup table is used for all arrays with same name and number of components. To reproduce the same behavior in Python, use GetLookupTableForArray().

def GetLookupTableForArray(arrayname, num_components, **params):
    """Used to get an existing lookuptable for a array or to create one if none
    exists. Keyword arguments can be passed in to initialize the LUT if a new
    one is created. Returns the lookup table."""
    ....

This will create a new lookup table and associate it with that array, if none already exists. Any default arguments to be passed to the lookup table if a new one is created, can be specified as additional parameters. You can always change the properties on the lookup table returned by this function.


# To color the representation by an array, we need to first create
# a lookup table.  We use the range of the Elevation array
>>> dp.LookupTable = GetLookupTableForArray("Elevation", 1,
                       RGBPoints = [min, 0, 0, 1, max, 1, 0, 0],
                       ColorSpace = "HSV")
>>> dp.ColorAttributeType = 'POINT_DATA'
>>> dp.ColorArrayName = 'Elevation' # color by Elevation
>>> Render()

Loading State and Manipulating It

Let’s say you created a complicated visualization using the paraview application and now you want to make slight changes to it and run it in a loop as a batch script. What do you do? The best way of dealing with this is to save your visualization state and then load it from Python. Let’s say you have a state file saved as myteststate.pvsm:

>>> from paraview.simple import *
# Load the state
>>> servermanager.LoadState("/Users/berk/myteststate.pvsm")
# Make sure that the view in the state is the active one
>>> SetActiveView(GetRenderView())
# Now render
>>> Render()
# Get the list of sources
>>> GetSources()
{('Sphere1', '5'): <paraview.servermanager.Sphere object at 0xaf80e30>, 
('Shrink1', '11'): <paraview.servermanager.Shrink object at 0xaf80df0>, 
('Cone1', '8'): <paraview.servermanager.Cone object at 0xaf80cf0>}
# Change the resolution of the cone and render again
>>> FindSource("Cone1").Resolution = 32
>>> Render()

You can also save state.

>>> from paraview.simple import *
>>> sph = Sphere()
>>> Render()
>>> servermanager.SaveState("/Users/berk/pythonstate.pvsm")

Dealing with Time

If a reader or a filter supports time, it is easy to request a certain time step from Python. All time requests are set on views that then propagate them to the representations which then propagate them to the visualization pipeline. Here is an example demonstrating how a time request can be made:

>>> Show(ExodusIIReader(FileName=".../can.ex2"))
>>> Render()
# Get a nice view angle
>>> cam = GetActiveCamera()
>>> cam.Elevation(45)
>>> Render()
# Check the current view time
>>> view = GetActiveView()
>>> view.ViewTime
0.0
>>> reader = GetActiveSource()
>>> reader.TimestepValues
[0.0, 0.00010007373930420727, 0.00019990510190837085, 
0.00029996439116075635, 0.00040008654468692839, 
...]
>>> tsteps = reader.TimestepValues
# Let’s be fancy and use a time annotation filter. This will show the
# current time value of the reader as text in the corner of the view.
>>> annTime = AnnotateTimeFilter(reader)
# Show the filter
>>> Show(annTime)
# Look at a few time steps. Note that the time value is requested not
# the time step index.
>>> view.ViewTime = tsteps[2]
>>> Render()
>>> view.ViewTime = tsteps[4]
>>> Render()

Animating

Server Manager has a complicated animation engine based on keyframes and scenes. This section will introduce a few simple ways of animating your visualization. If you have a time-aware reader, you can animate it with AnimateReader().

>>> reader = ExodusIIReader(FileName=.../can.ex2)
>>> Show(reader)
>>> Render()
>>> c = GetActiveCamera()
>>> c.Elevation(95)
# Animate over all time steps. Note that we are not passing the optional
# 3rd argument here. If you pass a filename as the 3rd argument, 
# AnimateReader will create a movie.
>>> AnimateReader(reader)
# Save the animation to an avi file
>>> AnimateReader(reader, filename=".../movie.avi")

To animate properties other than time, you can use regular keyframes.

ParaView 3.8.0 and earlier


Although the following script will work with 3.8.1 and later, it's not the recommended way since the changes done so will not be reflected in the GUI. Refer to the following sub-section for the recommended style for 3.8.1 and later versions.

>>> Sphere()
>>> Show()
>>> Render()

# Create an animation scene
>>> scene = servermanager.animation.AnimationScene()
# Add one view
>>> scene.ViewModules = [GetActiveView()]

# Create a cue to animate the StartTheta property
>>> cue = servermanager.animation.KeyFrameAnimationCue()
>>> cue.AnimatedProxy = GetActiveSource()
>>> cue.AnimatedPropertyName = "StartTheta"
# Add it to the scene's cues
>>> scene.Cues = [cue]

# Create 2 keyframes for the StartTheta track
>>> keyf0 = servermanager.animation.CompositeKeyFrame()
>>> keyf0.Interpolation = 'Ramp'
# At time = 0, value = 0
>>> keyf0.KeyTime = 0
>>> keyf0.KeyValues= [0]

>>> keyf1 = servermanager.animation.CompositeKeyFrame()
# At time = 1.0, value = 200
>>> keyf1.KeyTime = 1.0
>>> keyf1.KeyValues= [200]

# Add keyframes.
>>> cue.KeyFrames = [keyf0, keyf1]

>>> scene.Play()

# Some properties you can change
#
# Number of frames used in Sequence mode
# scene.NumberOfFrames = 100
#
# Or you can use real time mode
# scene.PlayMode = 'Real Time'
# scene.Duration = 20


ParaView 3.8.1 onwards


The following script will only work with ParaView versions 3.8.1 and later. It is now the recommended way for accessing animation scenes and tracks since the updates are reflected in the GUI when running through the Python shell from the ParaView application.

>>> Sphere()
>>> Show()
>>> Render()

# Get the application-wide animation scene
>>> scene = GetAnimationScene()

# Get the animation track for animating "StartTheta" on the active source.
# GetAnimationTrack() creates a new track if none exists.
>>> cue = GetAnimationTrack("StartTheta")

# Create 2 keyframes for the StartTheta track
>>> keyf0 = CompositeKeyFrame()
>>> keyf0.Interpolation = 'Ramp'
# At time = 0, value = 0
>>> keyf0.KeyTime = 0
>>> keyf0.KeyValues= [0]

>>> keyf1 = CompositeKeyFrame()
# At time = 1.0, value = 200
>>> keyf1.KeyTime = 1.0
>>> keyf1.KeyValues= [200]

# Add keyframes.
>>> cue.KeyFrames = [keyf0, keyf1]

>>> scene.Play()

# Some properties you can change
#
# Number of frames used in Sequence mode
# scene.NumberOfFrames = 100
#
# Or you can use real time mode
# scene.PlayMode = 'Real Time'
# scene.Duration = 20

GetAnimationTrack Usages


# Typical usage
>>> track = GetAnimationTrack("Center", 0, sphere) or
>>> track = GetAnimationTrack(sphere.GetProperty("Radius")) or

# this returns the track to animate visibility of the active source in
# all views.
>>> track = GetAnimationTrack("Visibility")

# For animating properties on implicit planes etc., use the following
# signatures:
>>> track = GetAnimationTrack(slice.SliceType.GetProperty("Origin"), 0) or
>>> track = GetAnimationTrack("Origin", 0, slice.SliceType)

Loading Data Files

As seen throughout this document, you can always load a data file by explicitly creating the reader that can read the data file as follows:

>>> reader = ExodusIIReader(FileName=.../can.ex2)

Alternatively, starting with ParaView 3.8, you can use OpenDataFile() function to let ParaView pick a reader using the extension of the file.

>>> reader = OpenDataFile(.../can.ex2)


Writing Data Files (ParaView 3.9 or later)

To create a writer to write the output from a source, one can use the following:

from paraview.simple import *

# Specifying the source explicitly
>>> writer= CreateWriter("/.../filename.vtk", source)

# Using the active source
>>> writer= CreateWriter("/.../filename.vtk")

# Writing data from a particular output port
>>> writer= CreateWriter("/.../filename.vtk", servermanager.OutputPort(source, 1))

# Now one change change the ivars on the writer 

# To do the actual writing, use:
>>> writer.UpdatePipeline()

Exporting CSV Data

To export a csv from the cell or point data associated with a source, one can use the following:

>>> writer = CreateWriter(".../foo.csv", source)
>>> writer.FieldAssociation = "Points" # or "Cells"
>>> writer.UpdatePipeline()
>>> del writer

Updating View Layout

Starting with ParaView 3.14, Python scripts can be used to update view layout.

Every tab in the central frame of the ParaView application is represented by layout proxy. To obtain a map of layout proxies present, use the GetLayouts().

>>> GetLayouts()
{('ViewLayout1', '264'): <paraview.servermanager.ViewLayout object at 0x2e5b7d0>}

To get the layout corresponding to the active view (or a particular view), use the GetLayout() function.

>>> GetLayout()
<paraview.servermanager.ViewLayout object at 0x2e5b7d0>
>>>
>>> GetLayout(GetActiveView())
<paraview.servermanager.ViewLayout object at 0x2e5b7d0>

To split the cell containing a particular view, either horizontally or vertically, use:

>>> layout.SplitViewVertical(view = GetActiveView())

>>> layout.SplitViewHorizontal(view = GetActiveView(), fraction = 0.7)

To resize a cell containing a particular view:

>>> location = layout.GetViewLocation(view)
>>> layout.SetSplitFraction(location, 0.3)

To maximize a particular view

>>> location = layout.GetViewLocation(view)
>>> layout.MaximizeCell(location)

There are a host of other methods that are available that can help with layout of the views. Refer to the API exposed by vtkSMViewLayoutProxy. The API is fully accessible through Python.

To create a new tab, one can use the following piece of code:

  new_layout = servermanager.misc.ViewLayout(registrationGroup="layouts")

Multiple Renders

When working in an interactive python session, the Render() command will open a new graphical window. If this window is closed before a subsequent Render() call, the new Render() call will cause the interactive python session to exit with an error like:

XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server ":0"

Take away: leave the graphical window open for the duration of your python/paraview session in order for multiple Render() calls to work.



ParaView: [Welcome | Site Map]