Commit f03b9c63 authored by Berk Geveci's avatar Berk Geveci Committed by Code Review

Merge topic 'python-algorithm-2' into master

adf3b4d8 pythonalg: raise an error in RequestData by default
0b1ca3a0 pythonalg: use keyword arguments rather than members
4787c7a4 Added documentation and testing to vtkPythonAlgorithm.
parents 3ae631e6 adf3b4d8
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, nInputPorts=0, 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, nInputPorts=1, inputType='vtkDataSet',
nOutputPorts=1, outputType='vtkPolyData'):
"""Sets up default NumberOfInputPorts, NumberOfOutputPorts,
InputType and OutputType that are used by various initialization
methods."""
self.NumberOfInputPorts = nInputPorts
self.NumberOfOutputPorts = nOutputPorts
self.InputType = inputType
self.OutputType = outputType
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."""
raise NotImplementedError('RequestData must be implemented')
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