VTK  9.1.0
Python Wrappers

The Python wrappers for VTK are produced algorithmically from the VTK header files, and using VTK through Python is very much like using VTK through C++. Nearly all of the same functionality is available, with Python types converted automatically to C++ types and vice-versa. This document assumes that you are already familiar with VTK itself, and want to know more details about how to use VTK through Python.

Installation

The most convenient way to install VTK for Python is with pip, which is a package manager that comes with Python:

pip install vtk

This will provide a basic installation of VTK that includes all core functionality, but which will not include some of the specialized VTK modules that rely on external libraries. Binary packages for VTK can also be downloaded directly from https://www.vtk.org/download/.

Instructions for building VTK from source code are given in the file Documentation/dev/build.md within the source repository.

Importing

VTK is comprised of over one hundred individual modules. Programs can import just the modules that are needed, in order to reduce load time.

from vtkmodules.vtkCommonCore import vtkObject
from vtkmodules.vtkFiltersSources import vtkConeSource, vtkSphereSource
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkDataSetMapper,
    vtkRenderer,
    vtkRenderWindow
)
import vtkmodules.vtkRenderingOpenGL2

When getting started, however, it is hard to know what modules you will need. So if you are experimenting with VTK in a Python console, or writing a quick and dirty Python script, it is easiest to simply import everything. There is a special module called 'all' that allows this to be done:

from vtkmodules.all import *

After importing the VTK classes, you can check to see which module each of the classes comes from:

for c in vtkObject, vtkConeSource, vtkRenderWindow:
    print(f"from {c.__module__} import {c.__name__}")

The output is as follows:

from vtkmodules.vtkCommonCore import vtkObject
from vtkmodules.vtkFiltersSources import vtkConeSource
from vtkmodules.vtkRenderingCore import vtkRenderWindow

Factories and Implementation Modules

In the first 'import' example above, you might be wondering about this line:

import vtkmodules.vtkRenderingOpenGL2

This import is needed because vtkRenderingOpenGL2 provides the OpenGL implementations of the classes in vtkRenderingCore. To see this in action, open a new Python console and do the following:

>>> from vtkmodules.vtkRenderingCore import vtkRenderWindow
>>> renwin = vtkRenderWindow()
>>> type(renwin)
<class 'vtkmodules.vtkRenderingCore.vtkRenderWindow'>
>>>
>>> import vtkmodules.vtkRenderingOpenGL2
>>> renwin2 = vtkRenderWindow()
>>> type(renwin2)
<class 'vtkmodules.vtkRenderingOpenGL2.vtkXOpenGLRenderWindow'>

After vtkRenderingOpenGL2 has been imported, the vtkRenderWindow() constructor magically starts returning a different type of object. This occurs because vtkRenderWindow is a factory class, which means that the kind of object it produces can be overridden by an implementation class. In order for the implementation class to do the override, all that is necessary is that its module is imported. To make things even more confusing, vtkRenderingOpenGL2 is not the only module that contains implementations for the factory classes in vtkRenderingCore. The following modules are often needed, as well:

import vtkmodules.vtkInteractionStyle
import vtkmodules.vtkRenderingFreeType

Although you only need implementations for the factory classes that you use, it can be hard to know which classes are factory classes, or what modules contain implementations for them. Also, it can be difficult to even know what classes you are using, since many VTK classes make use of other VTK classes. An example of this is vtkDataSetMapper, which internally uses vtkPolyDataMapper to do the rendering. So even though vtkDataSetMapper is not a factory class, it needs an OpenGL implmentation for vtkPolyDataMapper.

The simplest approach is to import all the important implementation modules into your program, even if you are not certain that you need them.

  • For vtkRenderingCore, import vtkRenderingOpenGL2, vtkRenderingFreeType, vtkInteractionStyle
  • For vtkRenderingVolume, import vtkRenderingVolumeOpenGL2
  • For vtkCharts, import vtkContextOpenGL2

Obsolete VTK Import

There are many VTK programs that still use the old 'vtk' module, instead of using the 'vtkmodules' package introduced in VTK 8.2:

import vtk

Although this works, it is not recommended. The 'vtk' module is only for backwards-compatibility and is, in fact, just the 'vtkmodules.all' with a different name. Because of the details of how the renaming is done, the 'import vtk' statement can confuse IDEs like PyCharm and make them unable to index the module. Instead, if you desire a module named 'vtk', either for personal preference or a need for backwards compatibility, then use this:

import vtkmodules.all as vtk

This will make it clear to people who read your code that 'vtk' is simply a different name for 'vtkmodules.all'. It will also keep your IDE from becoming confused about what exactly the 'vtk' module is.

VTK Classes and Objects

Classes Derived from vtkObjectBase

In C++, classes derived from vtkObjectBase are instantiated by calling ::New(). In Python, these classes are instantiated by simply calling the constructor:

o = vtkObject()

For factory classes, the returned object's type might be a subtype of the class. This occurs because the Python wrappers are actually calling ::New() for you, which allows the VTK factory overrides to occur:

>>> a = vtkActor()
>>> type(a)
<class 'vtkmodules.vtkRenderingOpenGL2.vtkOpenGLActor'>

When you create a VTK object in Python, you are in fact creating two objects: a C++ object, and a Python object that holds a pointer to the C++ object. The repr() of the object shows the memory address of the C++ object (in parentheses) and of the Python object (after the 'at'):

>>> a = vtkFloatArray()
>>> a
<vtkmodules.vtkCommonCore.vtkFloatArray(0x5653a6a6f700) at 0x7f0e7aecf5e0>

If you call str() or print() on these objects, the wrappers will call the C++ PrintSelf() method. The printed information can be useful for debugging:

>>> o = vtkObject()
>>> print(o)
vtkObject (0x55858308a210)
  Debug: Off
  Modified Time: 85
  Reference Count: 1
  Registered Events: (none)

Other Classes (Special Types)

VTK also uses several classes that aren't derived from vtkObjectBase. The most important of these is vtkVariant, which can hold any type of object:

>>> v1 = vtkVariant('hello')
>>> v1
vtkmodules.vtkCommonCore.vtkVariant('hello')
>>> v2 = vtkVariant(3.14)
>>> v2
vtkmodules.vtkCommonCore.vtkVariant(3.14)

The wrapping of these classes is fully automatic, but is done in a slightly different manner than vtkObjectBase-derived classes. First, these classes have no ::New() method, and instead the public C++ constructors are wrapped to create an equivalent Python contructor. Second, the Python object contains its own copy of the C++ object, rather than containing just a pointer to the C++ object. The vast majority of these classes are lightweight containers and numerical types. For example, vtkQuaterniond, vtkRectf, vtkColor4ub, etc. Many of them are actually class templates, which are discussed below.

When you apply print() or str() to these objects, the operator<< of the underlying C++ object is used to print them. For repr(), the name of the type name is printed, followed by the str() output in prentheses. The result looks similar to a constructor, though it might look strange depending on what operator<< produces.

>> v = vtkVariant()
>> print(repr(v))
vtkmodules.vtkCommonCore.vtkVariant((invalid))

Class Templates

There are several C++ templates in VTK, which can be tricky to use from the wrappers since the Python language has no real concept of templates. The the wrappers wrap templates as dictionary-like objects that map the template parameters to template instantiations:

>>> vtkSOADataArrayTemplate
<template vtkCommonCorePython.vtkSOADataArrayTemplate>
>>> vtkSOADataArrayTemplate.keys()
['char', 'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int',
'uint', 'int64', 'uint64', 'float32', 'float64']
>>> c = vtkSOADataArrayTemplate['float64']
>>> c
<class 'vtkmodules.vtkCommonCore.vtkSOADataArrayTemplate_IdE'>

The wrappers instantiate the C++ template for a few useful types, as indicated by the keys() of the template. The Python type name also has a suffix (the 'IdE') that indicates the template parameters in a compressed form according to IA64 C++ ABI name mangling rules, even when VTK is built with a compiler that does not use the IA64 ABI natively.

Objects are created by first instantiating the template, and then instantiating the class:

>>> a = vtkSOADataArrayTemplate['float32']()
>>> a.SetNumberOfComponents(3)

In the case of multiple template parameters, the syntax can look rather complicated, but really it isn't all that bad. For example, constructing a vtkTuple<double,4> in Python looks like this, with the template args in square brackets and the constructor args in parentheses:

>>> vtkTuple['float64',4]([1.0, 2.0, 3.0, 4.0])
vtkmodules.vtkCommonMath.vtkTuple_IdLi4EE([1.0, 2.0, 3.0, 4.0])

The type names are the same as numpy's dtypes: bool, int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, and float64. Since int64 is 'long long', int is used for long. Also see Template Keys in Advanced Topics.

Method Calls

When VTK methods are called from Python, conversion of all parameters from Python to C++ occurs automatically. That is, if the C++ method signature expects an integral type, you can pass a Python int, and if C++ expects a floating-point type, you can pass a Python float (or any type that allows implicit conversion to float).

For C++ 'char' parameters, which are rarely used in VTK, you must pass a string with a length of 1 or 0 bytes. This restricts the value to ASCII, since non-ASCII characters require at least 2 bytes in utf-8. An empty string signifies a null byte, and '\0' can also be used.

A Python tuple, list, or any other Python sequence can be passed to a VTK method that requires an array or std::vector in C++:

>>> a = vtkActor()
>>> p = (100.0, 200.0, 100.0)
>>> a.SetPosition(p)

If the method is going to modify the array that you pass as a parameter, then you must pass a Python list that has the correct number of slots to accept the returned values. If you try this with a tuple, you will get a TypeError because tuple is immutable.

>>> z = [0.0, 0.0, 0.0]
>>> vtkMath.Cross((1,0,0),(0,1,0),z)
>>> print(z)
[0.0, 0.0, 1.0]

For multi-dimensional array parameters, you can either use a nested list, or you can use numpy array with the correct shape.

If the C++ method returns a pointer to an array, then in Python the method will return a tuple if the wrappers know the size of the array. In most cases, the size is hinted in the header file.

>>> a = vtkActor()
>>> print(a.GetPosition())
(0.0, 0.0, 0.0)

Finally, Python None is treated the same as C++ nullptr, which allows you to pass null objects and null strings:

>>> a = vtkActor()
>>> a.SetMapper(None)
>>> print(a.GetMapper())
None

Wrappable and Unwrappable Methods

A method cannot be used from Python if its C++ parameters or return type cannot be converted to or from Python by the wrappers, or if the method is templated. Common non-convertible types include std::ostream, std::istream, and all STL container types except for std::vector (see below), and any non-trivial pointer type or any pointer to an object whose class is not derived from vtkObjectBase.

The wrappable parameter types are:

  • char, wrapped as a single ASCII character in a Python str
  • signed char and unsigned char, wrapped as Python int
  • short, int, long and long long, wrapped as Python int
  • unsigned short to unsigned long long, wrapped as Python int
  • float and double, wrapped as Python float
  • size_t and ssize_t, wrapped as Python int
  • std::string, wrapped as Python str via utf-8 encoding/decoding
  • typedefs of all the above, for any typedef defined in a VTK header file
  • std::vector<T> where T is one of the above, as Python tuple or list
  • const T& where T is any of the above, wrapped as described above
  • T[N] where T is a fundamental type, as Python tuple or list
  • T[N][M] where T is a fundamental type, as nested tuple or list
  • T* where T is a fundamental type, as tuple or list
  • vtkObjectBase* and derived types, as their respective Python type
  • other wrapped classes (like vtkVariant), but not pointers to these types
  • char*, as Python str via utf-8 encoding/decoding
  • void*, as Python buffer (e.g. bytes or bytearray)
  • the parameter list (void (*f)(void*), void*) as a Python callable type

References like int& and std::string& are wrapped via a reference proxy type as described in the Pass by Reference section below. Non-const references to std::vector<T> and other mutable types do not use a proxy, but instead require that a mutable Python object is passed, for example a list rather than a tuple.

A void* parameter can accept a pointer in two different ways: either from any Python object that supports the Python buffer protocol (this includes all numpy arrays along with the Python bytes and bytearray types), or from a string that contains a mangled pointer of the form '_hhhhhhhhhhhh_p_void' where 'hhhhhhhhhhhh' is the hexadecimal address. Return-value void* will always be a string containing the mangled pointer.

Also, a T* parameter for fundamental type T can accept a buffer object, if and only if it is annotated with the VTK_ZEROCOPY hint in the header file. With this hint, a numpy array of T can be passed to a T* parameter and the VTK method will directly access the memory buffer of the array. Hence the name 'zerocopy', which indicates no copying is done, and that direct memory access is used.

The vtkObject::AddObserver() method has a special wrapping, as discussed in the Observer Callbacks section below.

Conversion Constructors

If a wrapped type has constructor that takes one parameter, and if that constructor is not declared 'explicit', then the wrappers will automatically use that constructor for type conversion to the parameter type. The wrappers ensure that this conversion occurs in Python in the same manner that it is expected to occur in C++.

For example, vtkVariantArray has a method InsertNextItem(v:vtkVariant), and vtkVariant has a constructor vtkVariant(x:int). So, you can do this:

>>> variantArray.InsertNextItem(1)

The wrappers will automatically construct a vtkVariant from '1', and will then pass it as a parameter to InsertNextItem(). This is a feature that most C++ programmers will take for granted, but Python users might find it surprising.

Overloaded Methods

If you call a VTK method that is overloaded, the Python wrappers will choose the overload that best matches the supplied arguments. This matching takes into account all allowed implicit conversions, such as int to float or any conversion constructors that are defined for wrapped objects.

Some overloads will be unavailable (not wrapped) either because they are unwrappable as per the criteria described above, or because they are shadowed by another overload that is always perferable. A simple example of this is any methods that is overloaded on C++ float and double. The Python float type is a perfect match C++ double, therefore the float overload is not wrapped.

Static Methods

A static method can be called without an instance. For example,

vtkObject.SetGlobalWarningDisplay(1)

Some VTK classes, like vtkMath, consist solely of static methods. For others, like vtkMatrix4x4, most of the non-static methods have static overloads. Within Python, the only way to tell if a VTK method is static (other than trying it) is to look at its docstring.

Unbound Methods

When a non-static method is called on the class, rather than on an instance, it is called an unbound method call. An unbound method call must provide 'self' as the first argument, where 'self' is an instance of either the class or a subclass.

w = vtkRenderWindow()
vtkWindow.Render(w)

In other words, the wrappers translate Python unbound method calls into C++ unbound method calls. These are useful when deriving a Python class from a wrapped VTK class, since they allow you to call any base class methods that have been overridden in the subclass.

Operator Methods

For special classes (the ones not derived from vtkObjectBase), some useful C++ operators are wrapped in python. The '[]' operator is wrapped for indexing and item assignment, but because it relies on hints to guess which indices are out-of-bounds, it is only wrapped for vtkVector and related classes.

The comparison operators '<' '<=' '==' '>=' '>' are wrapped for all classes that have these operators in C++. These operators allow sorting of vtkVariant objects with Python.

The '<<' operator for printing is wrapped and is used by the python print() and str() commands.

Strings and Bytes

VTK uses both char* and std::string for strings. As far as the wrappers are concerned, these are equivalent except that the former can be nullptr (None in Python). For both, the expected encoding is ASCII or utf-8.

In Python, either str or bytes can be used to store strings, and both of these can be passed to VTK methods that require char* or std::string (or the legacy vtkStdString). A str object is passed to VTK as utf-8, while a bytes object is passed as-is.

When a VTK method returns a string, it is received in Python as a str object if it is valid utf-8, or as a bytes object if not. The caller should check the type of the returned object (str, bytes, or perhaps None) if there is any reason to suspect that non-utf-8 text might be present.

STL Containers

VTK provides conversion between std::vector and Python sequences such as tuple and list. If the C++ method returns a vector, the Python method will return a tuple:

C++: const std::vector<std::string>& GetPaths()
C++: std::vector<std::string> GetPaths()
Python: GetPaths() -> Tuple[str]

If the C++ method accepts a vector, then the Python method can be passed any sequence with compatible values:

C++: void SetPaths(const std::vector<std::string>& paths)
C++: void SetPaths(std::vector<std::string> paths)
Python: SetPaths(paths: Sequence[str]) -> None

Furthermore, if the C++ method accepts a non-const vector reference, then the Python method can be passed a mutable sequence (e.g. list):

C++: void GetPaths(std::vector<std::string>& paths)
Python: GetPaths(paths: MutableSequence[str]) -> None

The value type of the std::vector<T> must be std::string or a fundamental numeric type such as double or int (including signed char and unsigned char but excluding char).

Pass by Reference

Many VTK methods use pass-by-reference to return values back to the caller. Calling these methods from Python requires special consideration, since Python's str, tuple, int, and float types are immutable. The wrappers provide a 'reference' type, which is a simple container that allows pass-by-reference.

For example, consider the following C++ method that uses pass-by-reference:

void GetCellAtId(vtkIdType cellId, vtkIdType& cellSize, vtkIdType const*& cellPoints)

It requires a reference to vtkIdType (a Python int), and to vtkIdType const* (a tuple of ints). So we can call this method as follows:

>>> from vtkmodules.vtkCommonCore import reference
>>> from vtkmodules.vtkCommonDataModel import vtkCellArray
>>>
>>> # Build a cell array
>>> a = vtkCellArray()
>>> a.InsertNextCell(3, (1, 3, 0))
>>>
>>> # Create the reference objects
>>> n = reference(0)
>>> t = reference((0,))
>>>
>>> # Call the pass-by-reference method
>>> a.GetCellAtId(0, n, t)
>>>
>>> n.get()
3
>>> t.get()
(1, 3, 0)

Some important notes when using pass-by-reference:

  1. The reference constructor must be given a value of the desired type. The method might use this value or might ignore it.
  2. Calling the get() method of the reference is usually unnecessary, because the reference already supports the interface protocols of the object that it contains.

Preconditions

One very real concern when using VTK from Python is that the parameters that you pass to a method might cause the program to crash. In particular, it is very easy to pass an index that causes an out-of-bounds memory access, since the C++ methods don't do bounds checking. As a safety precaution, the wrappers perform the bounds check before the C++ method is called:

>>> a = vtkFloatArray()
>>> a.GetValue(10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: expects 0 <= id && id < GetNumberOfValues()

All precondition checks raise a ValueError if they fail, since they are checks on the values of the parameters. The wrappers don't know if C++ is using the parameter as an index, so IndexError is not used.

Currently the only way to find out if a method has preconditions is to look at the declaration of the method in the C++ header file to see if it has a VTK_EXPECTS hint.

Observer Callbacks

Similar to what can be done in C++, a Python function can be called each time a VTK event is invoked on a given object. In general, the callback function should have the signature func(obj:vtkObject, event:str), or func(self, obj:vtkObject, event:str) if it is a method of a class.

>>> def onObjectModified(object, event):
>>>     print('object: %s - event: %s' % (object.GetClassName(), event))
>>>
>>> o = vtkObject()
>>> o.AddObserver(vtkCommand.ModifiedEvent, onObjectModified)
1
>>> o.Modified()
object: vtkObject - event: ModifiedEvent

Call Data

In case there is a 'CallData' value associated with an event, in C++, you have to cast it from void* to the expected type using reinterpret_cast. The equivalent in python is to add a CallDataType attribute to the associated python callback method. The supported CallDataType values are VTK_STRING, VTK_OBJECT, VTK_INT, VTK_LONG, VTK_DOUBLE, and VTK_FLOAT.

The following example uses a function as a callback, but a method or any callable object can be used:

>>> from vtkmodules.vtkCommonCore import vtkCommand, VTK_INT
>>>
>>> def onError(object, event, calldata):
>>>     print('object: %s - event: %s - msg: %s' % (object.GetClassName(), event, calldata))
>>>
>>> onError.CallDataType = VTK_INT
>>>
>>> lt = vtkLookupTable()
>>> lt.AddObserver(vtkCommand.ErrorEvent, onError)
1
>>> lt.SetTableRange(2,1)
object: vtkLookupTable - event: ErrorEvent - msg: ERROR:
In /home/user/VTK/Common/Core/vtkLookupTable.cxx, line 122
vtkLookupTable (0x6b40b30): Bad table range: [2, 1]

For convenience, the CallDataType can also be specified where the function is first declared with the help of the @calldata_type decorator:

>>> from vtkmodules.util.misc import calldata_type
>>>
>>> @calldata_type(VTK_INT)
>>> def onError(object, event, calldata):
>>>     print('object: %s - event: %s - msg: %s' % (object.GetClassName(),
                                                    event, calldata))

Other Wrapped Entities

Constants

Most of the constants defined in the VTK header files are available in Python, and they can be accessed from the module in which they are defined. Many of these are found in the vtkCommonCore module, where they were defined as preprocessor macros.

>>> from vtkmodules.vtkCommonCore import VTK_DOUBLE_MAX
>>> VTK_DOUBLE_MAX
1.0000000000000001e+299

Others are defined as enums, often within a class namespace. If the enum is anonymous, then its values are int.

>>> vtkCommand.ErrorEvent
39

Constants in the header files are wrapped if they are enums, or if they are const variables of a wrappable scalar type, or if they are preprocessor symbols that evaluate to integer, floating-point, or string literal types.

Enum Types

Each named enum type is wrapped as a new Python type, and members of the enum are instances of that type. This allows type checking for enum types:

>>> from vtkmodules.vtkCommonColor import vtkColorSeries
>>> vtkColorSeries.COOL
2
>>> isinstance(vtkColorSeries.ColorSchemes, vtkColorSeries.COOL)
>>> cs = vtkColorSeries()
>>> cs.SetColorScheme(vtkColorSeries.COOL)

Enum classes are wrapped in a manner similar to named enums, except that the enum values are placed within the enum class namespace. For example, vtkEventDataAction is an enum class, with 'Press' as a member:

>>> from vtkmodules.vtkCommonCore import vtkEventDataAction
>>> vtkEventDataAction.Press
1
>>> isinstance(vtkEventDataAction.Press, vtkEventDataAction)
True

In the first example, the ColorSchemes enum type and the COOL enum value were both defined in the vtkColorSeries namespace. In the second example, the vtkEventDataAction enum class was defined in the module namespace, and the Press value was defined in the enum class namespace.

Note that the VTK enum types behave like C++ enums, and not like the Python enums types provided by the Python 'enum' module. In particular, all VTK enum values can be used anywhere that an int can be used.

Namespaces

Namespaces are currently wrapped in a very limited manner. The only namespace members that are wrapped are enum constants and enum types. There is no wrapping of namespaced classes or functions, or of nested namespaces. Currently, the wrappers implement namespaces as Python module objects.

Docstrings

The wrappers automatically generate docstrings from the doxygen comments in the header files. The Python help() command can be used to print the documentation to the screen, or the __doc__ attributes of the classes and methods can be accessed directly.

Method Docstrings

The method docstrings are formatted with the method signatures first, followed by doxygen comments. The Python method signatures have type annotations, and are followed by the C++ method signatures for completeness.

InvokeEvent(self, event:int, callData:Any) -> int
C++: int InvokeEvent(unsigned long event, void* callData)
InvokeEvent(self, event:str, callData:Any) -> int
C++: int InvokeEvent(const char* event, void* callData)
InvokeEvent(self, event:int) -> int
C++: int InvokeEvent(unsigned long event)
InvokeEvent(self, event:str) -> int
C++: int InvokeEvent(const char* event)
This method invokes an event and returns whether the event was
aborted or not. If the event was aborted, the return value is 1,
otherwise it is 0.

Some Python IDEs will automatically show the docstring as soon as you type the name of the method.

Class Docstrings

The class docstrings include a brief description of the class, followed by the name of the superclass, and then the full doxygen documentation, including doxygen markup:

vtkMatrix4x4 - represent and manipulate 4x4 transformation matrices
Superclass: vtkObject
vtkMatrix4x4 is a class to represent and manipulate 4x4 matrices.
Specifically, it is designed to work on 4x4 transformation matrices
found in 3D rendering using homogeneous coordinates [x y z w]. Many
of the methods take an array of 16 doubles in row-major format. Note
that OpenGL stores matrices in column-major format, so the matrix
contents must be transposed when they are moved between OpenGL and
VTK.
@sa
vtkTransform

If the class is not derived from vtkObjectBase, then it will have one or more public constructors, and these will be included before the comments:

vtkSimpleCriticalSection() -> vtkSimpleCriticalSection
C++: vtkSimpleCriticalSection()
vtkSimpleCriticalSection(isLocked:int) -> vtkSimpleCriticalSection
C++: vtkSimpleCriticalSection(int isLocked)
vtkSimpleCriticalSection - Critical section locking class
vtkCriticalSection allows the locking of variables which are accessed
through different threads.

Template Docstrings

Class templates are documented similar to classes, except that they include a 'Provided Types' section that lists the available template instantiations and the C++ template arguments that they correspond to.

vtkSOADataArrayTemplate - Struct-Of-Arrays implementation of
vtkGenericDataArray.
Superclass: vtkGenericDataArray[vtkSOADataArrayTemplate[ValueTypeT],ValueTypeT]
vtkSOADataArrayTemplate is the counterpart of vtkAOSDataArrayTemplate.
Each component is stored in a separate array.
@sa
vtkGenericDataArray vtkAOSDataArrayTemplate
Provided Types:
vtkSOADataArrayTemplate[char] => vtkSOADataArrayTemplate<char>
vtkSOADataArrayTemplate[int8] => vtkSOADataArrayTemplate<signed char>
vtkSOADataArrayTemplate[uint8] => vtkSOADataArrayTemplate<unsigned char>
vtkSOADataArrayTemplate[int16] => vtkSOADataArrayTemplate<short>
vtkSOADataArrayTemplate[uint16] => vtkSOADataArrayTemplate<unsigned short>
vtkSOADataArrayTemplate[int32] => vtkSOADataArrayTemplate<int>
vtkSOADataArrayTemplate[uint32] => vtkSOADataArrayTemplate<unsigned int>
vtkSOADataArrayTemplate[int] => vtkSOADataArrayTemplate<long>
vtkSOADataArrayTemplate[uint] => vtkSOADataArrayTemplate<unsigned long>
vtkSOADataArrayTemplate[int64] => vtkSOADataArrayTemplate<long long>
vtkSOADataArrayTemplate[uint64] => vtkSOADataArrayTemplate<unsigned long long>
vtkSOADataArrayTemplate[float32] => vtkSOADataArrayTemplate<float>
vtkSOADataArrayTemplate[float64] => vtkSOADataArrayTemplate<double>

Unlike classes, the template documentation is formatted similarly regardless of whether the the class template derives from vtkObjectBase or not:

vtkVector - templated base type for storage of vectors.
Superclass: vtkTuple[T,Size]
This class is a templated data type for storing and manipulating fixed
size vectors, which can be used to represent two and three dimensional
points. The memory layout is a contiguous array of the specified type,
such that a float[2] can be cast to a vtkVector2f and manipulated. Also
a float[6] could be cast and used as a vtkVector2f[3].
Provided Types:
vtkVector[float64,4] => vtkVector<double, 4>
vtkVector[float32,4] => vtkVector<float, 4>
vtkVector[int32,4] => vtkVector<int, 4>
vtkVector[float64,2] => vtkVector<double, 2>
vtkVector[float32,2] => vtkVector<float, 2>
vtkVector[int32,2] => vtkVector<int, 2>
vtkVector[float64,3] => vtkVector<double, 3>
vtkVector[float32,3] => vtkVector<float, 3>
vtkVector[int32,3] => vtkVector<int, 3>

Internals and Advanced Topics

Special Attributes

Classes and objects derived from vtkObjectBase have special attributes, which are only used in very special circumstances.

The __vtkname__ attribute of the class provides the same string that the GetClassName() method returns. With the exception of classes that are template instantiations, it is identical to the __name__ attribute. For template instantiations, however, GetClassName() and __vtkname__ return the result of calling typeid(cls).name() from C++, which provides a platform specific result:

>>> vtkSOADataArrayTemplate['float32'].__vtkname__
'23vtkSOADataArrayTemplateIfE'

This can be used to get the VTK ClassName when you don't have an instantiation to call GetClassName() on. It is useful for checking the type of a C++ VTK object against a Python VTK class.

The __this__ attribute of the objects is a bit less esoteric, it provides a pointer to the C++ object as a mangled string:

>>> a = vtkFloatArray()
>>> a.__this__
'_00005653a6a6f700_p_vtkFloatArray'

The string provides the hexadecimal address of 'this', followed by 'p' (shorthand for pointer), and the type of the pointer. You can also contruct a Python object directly from the C++ address, if the address is formatted as described above:

>>> a = vtkFloatArray('_00005653a6a6f700_p_vtkFloatArray')
>>> a
<vtkmodules.vtkCommonCore.vtkFloatArray(0x5653a6a6f700) at 0x7f0e7aecf5e0>

If you call the constructor on the string provided by __this__, you will get exactly the same Python object back again, rather than a new object. But this constructor can be useful if you have some VTK code that has been wrapped with a different wrapper tool, for example with SWIG. If you can get the VTK pointer from SWIG, you can use it to construct Python object that can be used with the native VTK wrappers.

Wrapper Hints

A wrapper hint is an attribute that can be added to a class, method, or parameter declaration in a C++ header file to give extra information to the wrappers. These hints are defined in the vtkWrappingHints.h header file.

The following hints can appear before a method declaration:

  • VTK_WRAPEXCLUDE excludes a method from the wrappers
  • VTK_NEWINSTANCE passes ownership of a method's return value to the caller

For convenience, VTK_WRAPEXCLUDE can also be used to exclude a whole class. The VTK_NEWINSTANCE hint is used when the return value is a vtkObjectBase* and the caller must not increment the reference count upon acceptance of the object (but must still decrement the reference count when finished with the object).

The following hints can appear after a method declaration:

For VTK_EXPECTS(cond), the precondition must be valid C++ code, and can use any of the parameter names or this. Even without this, any public names in the class namespace (including method names) will be resolved. See the Preconditions section for additional information.

For sized array parameters, such as func(int x[10]), the wrappers will automatically check the size of the Python sequence that is passed to the method. For bare T* pointers (with T as a basic integer or float type), The wrappers will only check the size if a VTK_SIZEHINT is present. Also, return values of type T* will not return a tuple unless there is a size hint for the return value. They will, instead, return a string that provides a mangled pointer of the form '_hhhhhhhhhhhh_p_void' where 'hhhhhhhhhhhh' is the hexadecimal address.

The following hints can appear before a parameter declaration:

  • VTK_FILEPATH marks a parameter that accepts a pathlib.Path object
  • VTK_ZEROCOPY marks a parameter that accepts a buffer object

More specifically, VTK_FILEPATH is used with char* and std::string parameters to indicate that the method also accepts any object with a __fspath__() method that returns a path string. And VTK_ZEROCOPY is used with T* parameters, for basic integer or float type T, to indicate that the Python buffer protocol will be used to access the values, rather than the Python sequence protocol that is used by default.

Deprecation Warnings

In addition to the wrapping hints, the Python wrappers are also aware of the deprecation attributes that have been applied to classes and methods. When a deprecated method is called, a DeprecationWarning is generated and information about the deprecation is printed, including the VTK version for the deprecation.

To ignore these warnings, use the following code:

import warnings
warnings.filterwarnings('ignore', category=DeprecationWarning)

To see each deprecation warning just once per session,

warnings.filterwarnings('once', category=DeprecationWarning)

Template Keys

The following is a table of common template key names, which are the same as the numpy dtype names. Note that you can actually use numpy dtypes as keys, as well as the native Python types bool, int, and float. There is some danger in using int, however, because it maps to C++ long which has a platform-dependent size (either 32 bits or 64 bits). Finally, the char codes from the Python array module can be used as keys, but they should be avoided since more programmers are familiar with numpy than with the much older array module.

C++ Type Template Key Type Key Char Key IA64 ABI Code
bool 'bool' bool '?' IbE
char 'char' 'c' IcE
signed char 'int8' 'b' IaE
unsigned char 'uint8' 'B' IhE
short 'int16' 'h' IsE
unsigned short 'uint16' 'H' ItE
int 'int32' 'i' IiE
unsigned int 'uint32' 'I' IjE
long 'int' int 'l' IlE
unsigned long 'uint' 'L' ImE
long long 'int64' 'q' IxE
unsigned long long 'uint64' 'Q' IyE
float 'float32' 'f' IfE
double 'float64' float 'd' IdE

Since the size of 'long' and 'unsigned long' is platform-dependent, these types should generally be avoided.

Exception Handling

There are times when an observer might generate a Python exception. Since the observers are called from C++, there is no good way to catch these exceptions from within Python. So, instead, the wrappers simply print a traceback to stderr and then clear the error indicator. The Python program will continue running unless the exception was a KeyboardInterrupt (Ctrl-C), in which case the program will exit with an error code of 1.

Deleting a vtkObject

There is no direct equivalent of VTK's Delete() method, since Python does garbage collection automatically. The Python object will be deleted when there are no references to it within Python, and the C++ object will be deleted when there are no references to it from within either Python or C++. Note that references can hide in unexpected places, for example if a method of an object is used as an observer callback, the object will not be deleted until the observer is disconnected.

The DeleteEvent can be used to detect object deletion, but note that the observer will receive a None for the object, since the observer is called after (not before) the deletion occurs:

>>> o = vtkObject()
>>> o.AddObserver('DeleteEvent', lambda o,e: print(e, o))
1
>>> del o
DeleteEvent None

If you need to know what object is deleted, the identifying information must be extracted before the deletion occurs:

>>> o = vtkObject()
>>> o.AddObserver('DeleteEvent',lambda x,e,r=repr(o): print(e, r))
1
>>> del o
DeleteEvent <vtkmodules.vtkCommonCore.vtkObject(0x55783870f970) at 0x7f1e61678be0>

In cases where you need to track down tricky memory issues, you might find it useful to call the SetReferenceCount() and GetReferenceCount() methods of the object directly. Of course, direct manipulation of the reference count should never be done in production code.

Ghosts

A wrapped VTK object (derived from vtkObjectBase) is a Python object that holds a pointer to a C++ object (specifically, a vtkObjectBase*). The Python object can have attributes that the C++ object knows nothing about. So, what happens to these attributes if the Python object is deleted, but the C++ object lives on? Consider this simple example of storing the C++ object in an array and then deleting the Python object:

obj = vtkObject()
obj.tag = 'FirstObject'
va = vtkVariantArray()
va.InsertNextValue(obj)
del obj

When we retrieve the object from the array, we want it to have the 'tag' attributes that it had we stored it. But you might wonder, aren't all Python-specific attributes deleted along with the Python object? The answer is, no they aren't, they're saved until until the C++ object itself is deleted.

The wrappers have a special place, which we will call the graveyard, where 'ghosts' of objects are stored when the objects are deleted. The ghost is not an object, but rather a container for the Python attributes of a deceased object. If the object ever reappears within Python, usually as a return value from a C++ method call, then the ghost is resurrected as a new Python object that has all the attributes of the original Python object.

The graveyard is only used for objects that have unfinished business. If a Python object has an empty dict and no other special attributes, then it will not go to the graveyard. Also, if the C++ object is deleted at the same time as the Python object, then the graveyard will not be used. Each ghost in the graveyard holds a weak pointer to its C++ object and will vanish when the C++ object is deleted (not immediately, but the next time the graveyard garbage collector runs).

Subclassing a VTK Class

It is possible to subclass a VTK class from within Python, but this is of limited use because the C++ virtual methods are not hooked to the Python methods. In other words, if you make a subclass of vtkPolyDataAlgorithm and override override the Execute() method, it will not be automatically called by the VTK pipeline. Your Execute() method will only be called if the call is made from Python.

The addition of virtual method hooks to the wrappers has been proposed, but currently the only way for Python methods to be called from C++ code is via callbacks. The vtkProgrammableSource and vtkProgrammableFilter are examples of VTK algorithm classes that use callbacks for execution, while vtkInteractionStyleUser can use observer callbacks for event handling.

Wrapping External VTK Modules

If you have your own C++ classes that are based on VTK, and if they are placed with a VTK module with a vtk.module file, then they can be wrapped as shown in the Module Wrapping Example. You will also find the cmake documentation on VTK modules to be useful.

Experimental Features

Stub Files for Type Hinting

VTK includes a script called vtk_generate_pyi.py that will generate pyi stub files for each wrapped VTK module. The purpose of these files, as explained in PEP 484, is to provide type information for all constants, classes, and methods in the modules. Each of these files contain blocks like this:

VTK_DOUBLE:int
VTK_DOUBLE_MAX:float
VTK_DOUBLE_MIN:float
...

class vtkObject(vtkObjectBase):
    def AddObserver(self, event:int, command:Callback, priority:float=0.0) -> int: ...
    def GetMTime(self) -> int: ...
    @staticmethod
    def GetNumberOfGenerationsFromBaseType(type:str) -> int: ...
    @overload
    def HasObserver(self, event:int, __b:'vtkCommand') -> int: ...
    @overload
    def HasObserver(self, event:str, __b:'vtkCommand') -> int: ...

class vtkAbstractArray(vtkObject):
    class DeleteMethod(int): ...
    VTK_DATA_ARRAY_ALIGNED_FREE:'DeleteMethod'
    VTK_DATA_ARRAY_DELETE:'DeleteMethod'
    VTK_DATA_ARRAY_FREE:'DeleteMethod'
    VTK_DATA_ARRAY_USER_DEFINED:'DeleteMethod'
    def Allocate(self, numValues:int, ext:int=1000) -> int: ...

Python consoles like ipython and IDEs like PyCharm can use the information in these files to provide hints while you edit the code. In upcoming versions of VTK, these files will probably be included in the Python packages for VTK. But for now, they must be built by executing the vtk_generate_pyi.py script. To do so, execute the script with the vtkpython executable (or with the regular python executable, if its paths are set for VTK):

vtkpython vtk_generate_pyi.py

This will place build the pyi files and place them inside the vtkmodules package, where ipython and PyCharm should automatically find them. The help for this script is as follows:

usage: python vtk_generate_pyi.py [-p package] [-o output_dir] [module ...]
options:
  -p NAME        Package name [vtkmodules by default].
  -o OUTPUT      Output directory [package directory by default].
  -e EXT         Output file suffix [.pyi by default].
  module         Module or modules to process [all by default].

The pyi files are syntactically correct python files, so it is possible to load them as such in order to test them and inspect them.