This module provides utility functions that can be used to expose a VTKPythonAlgorithmBase derived Pythonic vtkAlgorithm subclass in ParaView.
VTK provides a convenient Python-friendly mechanism to add new algorithms, such as data sources, filters, readers, and writers via vtkPythonAlgorithm. In this approach, developers can write subclasses of VTKPythonAlgorithmBase and then implement the vtkAlgorithm API in Python.
from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase
class ContourShrink(VTKPythonAlgorithmBase):
def __init__(self):
VTKPythonAlgorithmBase.__init__(self)
def RequestData(self, request, inInfo, outInfo):
inp = vtk.vtkDataSet.GetData(inInfo[0])
opt = vtk.vtkPolyData.GetData(outInfo)
cf = vtk.vtkContourFilter()
cf.SetInputData(inp)
cf.SetValue(0, 200)
sf = vtk.vtkShrinkPolyData()
sf.SetInputConnection(cf.GetOutputPort())
sf.Update()
opt.ShallowCopy(sf.GetOutput())
return 1
Such VTKPythonAlgorithmBase-based algorithms act as any other vtkAlgorithm and can be used directly in VTK pipelines. To use them in ParaView, however, one has to make ParaView aware of the capabilities of the algorithm. For vtkAlgorithm subclasses in C++, this is done by writing an XML description of the algorithm. For Python-based algorithms, this module provides us a mechanism to build the ParaView-specific XML via decorators.
from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase
from paraview.util.vtkAlgorithm import smproxy, smproperty, smdomain
@smproxy.filter(label="Contour Shrink")
@smproperty.input(name="Input")
@smdomain.datatype(dataTypes=["vtkDataSet"], composite_data_supported=False)
class ContourShrink(VTKPythonAlgorithmBase):
def __init__(self):
VTKPythonAlgorithmBase.__init__(self)
def RequestData(self, request, inInfo, outInfo):
...
return 1
Note
ParaView’s XML description provides a wide gamut of features. The decorators available currently only expose a small subset of them. The plan is to have complete feature parity in the future. If you encounter a missing capability, please raise an issue or better yet, a merge-request to address the same.
There are four main classes currently available: smproxy, smproperty, smdomain, and smhint. Each provides a set of decorators to declare a proxy, property, domain or a hint, respectively.
All available decorators exhibit the following characteristics:
@smproperty.intvector(name="Radius", default_values=[0])
@smdomain.intrange(min=0, max=10)
@smhint.xml("<SomeHint/>")
def SetRadius(self, radius):
...
Note, since domains can't have nested hints, the hint specified after the
`smdomain.intrange` invocation is intended for the `smproperty` and not the
`smdomain`.
When chaining `smproperty` decorators under a `smproxy`, the order in which
the properties are shown in ParaView UI is reverse of the order in the
Python code e.g. the in following snippets the UI will show "PolyDataInput"
above "TableInput".
@smproxy.filter(...)
@smproperty.input(name="TableInput", port_index=1, ...)
@smdomain.datatype(dataTypes=["vtkTable"])
@smproperty.input(name="PolyDataInput", port_index=0, ...)
@smdomain.datatype(dataTypes=["vtkPolyData"])
class MyFilter(VTKPythonAlgorithmBase):
...
To make VTKPythonAlgorithmBase subclass available in ParaView as a data-source, filter, reader, or writer, one must use of the decorators in the smproxy class.
The following keyword parameters are supported by all smproxy decorators:
As mentioned before, any keyword arguments passed any decorator that is not processed by the decorator simply gets added to the generated XML node as attribute.
This decorator can be used to declare data sources. Data sources don’t have any inputs, but provide 1 or more outputs. While technically a reader is a source, smproxy.reader is preferred way of adding readers.
This decorator can be used to declare filters that have one or more inputs and one or more outputs. The inputs themselves must be declared using smproperty.input decorators.
This decorator is used to declare reader. This is same as smproxy.source, except it adds the appropriate hints to make ParaView aware that this is a reader.
It takes the following keyword parameters, in addition to the standard ones:
Either extensions or filename_patterns must be provided.
This decorator is used to declare a writer. Similar to smproxy.reader, one provides file_description and extensions keyword parameters to indicate which file extensions the writer supports.
Decorators in smproperty are used to add properties to the proxies declared using smproxy decorators. These can be added either to class methods or to class objects. Multiple smproperty decorators may be chained when adding to class objects.
The following keyword parameters are supported by all smproperty decorators:
This is a catch-all decorator. One can use this to add arbitrary XML to the proxy definition.
@smproperty.xml(xmlstr="<IntVectorProperty name=..> .... </IntVectorProperty>")
def MyMethod(self, ...):
...
These are used to declare various types of vector properties. The arguments are simply the XML attributes.
This decorator can be used for adding a ProxyProperty, i.e. a method that takes another VTK object as argument.
This decorator can be used to add inputs to a vtkAlgorithm. Since vtkAlgorithm provides the appropriate API to set an input, often one doesn’t have custom methods in Python in the VTKPythonAlgorithmBase subclass. Hence, this decorator is often simply added to the class definition rather than a particular method.
@smproxy.filter(...)
@smproperty.input(name="TableInput", port_index=0, multiple_input=True)
@smdomain.datatype(dataTypes=["vtkTable"], composite_data_supported=False)
class MyFilter(VTKPythonAlgorithmBase):
...
This a convenience decorator that can be used to decorate a method that returns a vtkDataArraySelection object often used to array selection in data sources and readers. The decorator adds appropriate ParaView ServerManager XML components to expose the array selection to the user.
These decorators are used to add domains to smproperty. Domains often guide the UI that ParaView generated for the specific property. The current set of available domains, includes smdomain.intrange, smdomain.doublerange, smdomain.filelist, and smdomain.datatype. More will be added as needed. Additionally, one can use the smdomain.xml catch-all decorator to add XML definition for the domain.
These add elements under <Hints/> for smproxy and/or smproperty elements. Currently smhint.filechooser and the generic smhint.xml are provided with more to be added as needed.
PythonAlgorithmExamples.py provides a working example that demonstrates how several of the decorators described here may be used.