Commit 4787c7a4 authored by Berk Geveci's avatar Berk Geveci

Added documentation and testing to vtkPythonAlgorithm.

Also added a Python superclass to make algorithm
development easier.

Conflicts:
	Filters/Python/module.cmake

Change-Id: I23fbee8b39d10c4fa75faa7704153a8d58df9445
parent 20c2e44c
vtk_add_test_python(
NO_DATA NO_VALID NO_OUTPUT
TestPythonAlgorithm.py
)
import vtk
from vtk.util import vtkAlgorithm as vta
from vtk.test import Testing
class TestPythonAlgorithm(Testing.vtkTest):
def testSource(self):
class MyAlgorithm(vta.VTKAlgorithm):
def __init__(self):
vta.VTKAlgorithm.__init__(self)
self.NumberOfInputPorts = 0
self.OutputType = 'vtkImageData'
self.Wavelet = vtk.vtkRTAnalyticSource()
def RequestInformation(self, vtkself, request, inInfo, outInfo):
self.Wavelet.UpdateInformation()
wOutInfo = self.Wavelet.GetOutputInformation(0)
vtkSDDP = vtk.vtkStreamingDemandDrivenPipeline
outInfo.GetInformationObject(0).Set(vtkSDDP.WHOLE_EXTENT(), wOutInfo.Get(vtkSDDP.WHOLE_EXTENT()), 6)
return 1
def RequestData(self, vtkself, request, inInfo, outInfo):
self.Wavelet.Update()
out = self.GetOutputData(outInfo, 0)
out.ShallowCopy(self.Wavelet.GetOutput())
return 1
ex = vtk.vtkPythonAlgorithm()
ex.SetPythonObject(MyAlgorithm())
ex.Update()
w = vtk.vtkRTAnalyticSource()
w.Update()
output = ex.GetOutputDataObject(0)
self.assertEqual(output.GetPointData().GetScalars().GetRange(),\
w.GetOutput().GetPointData().GetScalars().GetRange())
vtkSDDP = vtk.vtkStreamingDemandDrivenPipeline
self.assertEqual(ex.GetOutputInformation(0).Get(vtkSDDP.WHOLE_EXTENT()),\
w.GetOutputInformation(0).Get(vtkSDDP.WHOLE_EXTENT()))
def testFilter(self):
class MyAlgorithm(vta.VTKAlgorithm):
def RequestData(self, vtkself, request, inInfo, outInfo):
inp = self.GetInputData(inInfo, 0, 0)
out = self.GetOutputData(outInfo, 0)
out.ShallowCopy(inp)
return 1
sphere = vtk.vtkSphereSource()
ex = vtk.vtkPythonAlgorithm()
ex.SetPythonObject(MyAlgorithm())
ex.SetInputConnection(sphere.GetOutputPort())
ex.Update()
output = ex.GetOutputDataObject(0)
ncells = output.GetNumberOfCells()
self.assertNotEqual(ncells, 0)
self.assertEqual(ncells, sphere.GetOutput().GetNumberOfCells())
self.assertEqual(output.GetBounds(), sphere.GetOutput().GetBounds())
if __name__ == "__main__":
Testing.main([(TestPythonAlgorithm, 'test')])
......@@ -9,5 +9,7 @@ if (VTK_WRAP_PYTHON)
vtkWrappingPythonCore
EXCLUDE_FROM_TCL_WRAPPING
EXCLUDE_FROM_JAVA_WRAPPING
TEST_DEPENDS
vtkTestingCore
)
endif ()
......@@ -12,10 +12,24 @@
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// .NAME vtkPythonAlgorithm - a user-programmable filter
// .NAME vtkPythonAlgorithm - algorithm that can be implemented in Python
// .SECTION Description
// vtkPythonAlgorithm is a filter that calls a Python object to do the actual
// vtkPythonAlgorithm is an algorithm that calls a Python object to do the actual
// work.
// It defers the following methods to Python:
// - ProcessRequest()
// - FillInputPortInformation()
// - FillOutputPortInformation()
//
// Python signature of these methods is as follows:
// - ProcessRequest(self, vtkself, request, inInfo, outInfo) : vtkself is the vtk object, inInfo is a tuple of information objects
// - FillInputPortInformation(self, vtkself, port, info)
// - FillOutputPortInformation(self, vtkself, port, info)
// - Initialize(self, vtkself)
//
// In addition, it calls an Initialize() method when setting the Python
// object, which allows the initialization of number of input and output
// ports etc.
// .SECTION See Also
// vtkProgrammableFilter
......@@ -37,15 +51,20 @@ public:
// Description:
// Specify the Python object to use to operate on the data. A reference will
// be taken on the object.
// be taken on the object. This will also invoke Initialize() on the Python
// object, which is commonly used to set the number of input and output
// ports as well as perform tasks commonly performed in the constructor
// of C++ algorithm subclass.
void SetPythonObject(PyObject* obj);
// Description:
// Set the number of input ports used by the algorithm.
// This is made public so that it can be called from Python.
virtual void SetNumberOfInputPorts(int n);
// Description:
// Set the number of output ports provided by the algorithm.
// This is made public so that it can be called from Python.
virtual void SetNumberOfOutputPorts(int n);
protected:
......
......@@ -178,6 +178,7 @@ if(PYTHON_EXECUTABLE)
vtk/util/vtkVariant
vtk/util/colors
vtk/util/numpy_support
vtk/util/vtkAlgorithm
)
# vtk.test package
......
import vtk
class VTKAlgorithm(object):
"""This is a superclass which can be derived to implement
Python classes that work with vtkPythonAlgorithm. It implements
Initialize(), ProcessRequest(), FillInputPortInformation() and
FillOutputPortInformation().
Initialize() sets the input and output ports based on data
members.
ProcessRequest() calls RequestXXX() methods to implement
various pipeline passes.
FillInputPortInformation() and FillOutputPortInformation() set
the input and output types based on data members.
"""
def __init__(self):
"""Sets up default NumberOfInputPorts, NumberOfOutputPorts,
InputType and OutputType that are used by various initialization
methods."""
self.NumberOfInputPorts = 1
self.NumberOfOutputPorts = 1
self.InputType = 'vtkDataSet'
self.OutputType = 'vtkPolyData'
def Initialize(self, vtkself):
"""Sets up number of input and output ports based on
NumberOfInputPorts and NumberOfOutputPorts."""
vtkself.SetNumberOfInputPorts(self.NumberOfInputPorts)
vtkself.SetNumberOfOutputPorts(self.NumberOfOutputPorts)
def GetInputData(self, inInfo, i, j):
"""Convenience method that returns an input data object
given a vector of information objects and two indices."""
return inInfo[i].GetInformationObject(j).Get(vtk.vtkDataObject.DATA_OBJECT())
def GetOutputData(self, outInfo, i):
"""Convenience method that returns an output data object
given an information object and an index."""
return outInfo.GetInformationObject(i).Get(vtk.vtkDataObject.DATA_OBJECT())
def RequestDataObject(self, vtkself, request, inInfo, outInfo):
"""Overwritten by subclass to manage data object creation.
There is not need to overwrite this class if the output can
be created based on the OutputType data member."""
return 1
def RequestInformation(self, vtkself, request, inInfo, outInfo):
"""Overwritten by subclass to provide meta-data to downstream
pipeline."""
return 1
def RequestUpdateExtent(self, vtkself, request, inInfo, outInfo):
"""Overwritten by subclass to modify data request going
to upstream pipeline."""
return 1
def RequestData(self, vtkself, request, inInfo, outInfo):
"""Overwritten by subclass to execute the algorithm."""
return 1
def ProcessRequest(self, vtkself, request, inInfo, outInfo):
"""Splits a request to RequestXXX() methods."""
if request.Has(vtk.vtkDemandDrivenPipeline.REQUEST_DATA_OBJECT()):
return self.RequestDataObject(vtkself, request, inInfo, outInfo)
elif request.Has(vtk.vtkDemandDrivenPipeline.REQUEST_INFORMATION()):
return self.RequestInformation(vtkself, request, inInfo, outInfo)
elif request.Has(vtk.vtkStreamingDemandDrivenPipeline.REQUEST_UPDATE_EXTENT()):
return self.RequestUpdateExtent(vtkself, request, inInfo, outInfo)
elif request.Has(vtk.vtkDemandDrivenPipeline.REQUEST_DATA()):
return self.RequestData(vtkself, request, inInfo, outInfo)
return 1
def FillInputPortInformation(self, vtkself, port, info):
"""Sets the required input type to InputType."""
info.Set(vtk.vtkAlgorithm.INPUT_REQUIRED_DATA_TYPE(), self.InputType)
return 1
def FillOutputPortInformation(self, vtkself, port, info):
"""Sets the default output type to OutputType."""
info.Set(vtk.vtkDataObject.DATA_TYPE_NAME(), self.OutputType)
return 1
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment