Python Plugin Filter Reading Info from Python Plugin Source

I’m using Paraview 5.8.0 on Ubuntu 20.04.

I’ve created a python plugin that acts as a source with two vtkPolyData outputs (spheres). The source is called “CR3BP System” and inherits the VTKPythonAlgorithmBase class

class PythonCR3BPSystemSource(VTKPythonAlgorithmBase):

I’ve added a slider bar to the GUI for a parameter “mu” that determines the placement of the two spheres. I would like to create another source called “CR3BP Traj” that reads in the “mu” parameter from the CR3BP system. How can I go about doing this?

My first idea is to create a filter with one input and define the expected input as the “CR3BP System”. I’m not sure how to do this.

Here’s my current code for the"CR3BP System" object

from vtkmodules.vtkCommonDataModel import vtkDataSet
from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase
from vtkmodules.numpy_interface import dataset_adapter as dsa
from paraview.util.vtkAlgorithm import smproxy , smproperty , smdomain
import numpy as np

# mu = 1

# to add a source, instead of a filter, use the ‘smproxy.source‘ decorator.
@smproxy.source(label="CR3BP System")
class PythonCR3BPSystemSource(VTKPythonAlgorithmBase):
    def __init__(self):
        VTKPythonAlgorithmBase.__init__(self,
            nInputPorts=0,
            nOutputPorts=2,
            outputType='vtkPolyData')
        from vtkmodules.vtkFiltersSources import vtkSphereSource

        self.prim = vtkSphereSource()
        self.prim.SetThetaResolution(20)
        self.prim.SetPhiResolution(20)
        self.prim.SetStartTheta(1e-5)
        self.sec = vtkSphereSource()
        self.sec.SetThetaResolution(20)
        self.sec.SetPhiResolution(20)
        self.sec.SetStartTheta(1e-5)

    def RequestData(self, request , inInfo , outInfo):
        from vtkmodules.vtkCommonDataModel import vtkPolyData
        self.prim.Update()
        self.sec.Update()
        output0 = vtkPolyData.GetData(outInfo , 0)
        output0.ShallowCopy(self.prim.GetOutput())
        output1 = vtkPolyData.GetData(outInfo , 1)
        output1.ShallowCopy(self.sec.GetOutput())
        return 1


    @smproperty.doublevector(name="mu", default_values=2.528017682687079e-05)
    @smdomain.doublerange(min=0, max=0.5)
    def SetMu(self, mu):
        self.mu = mu
        self.sec.SetCenter(1-mu,0,0)
        self.prim.SetCenter(-mu,0,0)
        self.Modified()

    @smproperty.doublevector(name="R1", default_values=0.1041737445984205)
    def SetPrimRadius(self, R1):
        self.prim.SetRadius(R1)
        self.Modified()

    @smproperty.doublevector(name="R2", default_values=0.0023257338697660556)
    def SetSecRadius(self, R2):
        self.sec.SetRadius(R2)
        self.Modified()

You could attach mu as a FieldData array to your output and read it in the second filter from its input.

Thanks! That works for me. I’ve attached my code change below.

    def RequestData(self, request , inInfo , outInfo):
        from vtkmodules.vtkCommonDataModel import vtkPolyData, vtkFieldData
        from vtkmodules.vtkCommonCore import vtkDoubleArray

        # from vtkmodules.vtkCommonDataModel import *

        data = vtkDoubleArray()
        data.SetNumberOfComponents(1)
        data.SetNumberOfTuples(1)
        data.SetName("mu")
        data.SetComponent(0,0,42)

        field = vtkFieldData()
        field.AddArray(data)

        self.prim.Update()
        self.sec.Update()
        output0 = vtkPolyData.GetData(outInfo , 0)
        output0.ShallowCopy(self.prim.GetOutput())

        output0.SetFieldData(field)

As a followup question, this field data is assigned to one of the sphere objects, not the CR3BPSystem object. Could I add the fielddata to the CR3BPSystem object and have that be the input to my filter? I’m going to have other parameters associated with both spheres that I want to pass on.

Answering my own question, I could make a multiBlockDataSet that has the spheres as blocks. I’ll try that.

OK, my MultiBlockDataSet looks great. I can animate the spheres moving around each other.

Now I would like to create a new source that reads in the FieldData and outputs a new PolyLineSource(). I’m getting stuck reading in the MultiBlockDataSet.

I’ve tried creating the following source from the example filter that keeps the input type

from vtkmodules.vtkCommonDataModel import vtkDataSet
from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase
from vtkmodules.numpy_interface import dataset_adapter as dsa
from paraview.util.vtkAlgorithm import smproxy , smproperty , smdomain
import numpy as np

@smproxy.source(label="CR3BP Traj")
@smproperty.input(name="Input")
@smdomain.datatype(dataTypes=["vtkMultiBlockDataSet"], composite_data_supported=True)
class PreserveInputTypeFilter(VTKPythonAlgorithmBase):
    """
    Example filter demonstrating how to write a filter that preserves the input
    dataset type.
    """
    def __init__(self):
        VTKPythonAlgorithmBase.__init__(self,
                                        nInputPorts=1,
                                        nOutputPorts=1,
                                        outputType='vtkMultiBlockDataSet')
    def RequestData(self, request, inInfo, outInfo):
        input0 = dsa.WrapDataObject(vtkDataSet.GetData(inInfo[0]))
        inData = self.GetInputData(inInfo, 0, 0)
        outData = self.GetOutputData(outInfo, 0)
        print("input type =", inData.GetClassName())
        print("output type =", outData.GetClassName())
        assert outData.IsA(inData.GetClassName())
        return 1

I create a CR3BPSystem object, select it, then try to create this CR3BPTraj object. I get the following errors

 Input port 0 of algorithm vtkPythonAlgorithm(0x9a3b240) has 0 connections but is not optional.
ERROR: In /home/buildslave/dashboards/buildbot/paraview-pvbinsdash-linux-shared-release_superbuild/build/superbuild/paraview/src/VTK/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 668
vtkPVCompositeDataPipeline (0x9ed5260): Input port 0 of algorithm vtkPythonAlgorithm(0x9a3b240) has 0 connections but is not optional.

 Algorithm vtkPVGeometryFilter(0xbd369c0) returned failure for request: vtkInformation (0xbd344b0)   Debug: Off   Modified Time: 1792682   Reference Count: 1   Registered Events: (none)   Request: REQUEST_DATA_OBJECT   FROM_OUTPUT_PORT: 0   ALGORITHM_AFTER_FORWARD: 1   FORWARD_DIRECTION: 0
ERROR: In /home/buildslave/dashboards/buildbot/paraview-pvbinsdash-linux-shared-release_superbuild/build/superbuild/paraview/src/VTK/Common/ExecutionModel/vtkExecutive.cxx, line 753
vtkCompositeDataPipeline (0xc006ce0): Algorithm vtkPVGeometryFilter(0xbd369c0) returned failure for request: vtkInformation (0xbd344b0)
  Debug: Off
  Modified Time: 1792682
  Reference Count: 1
  Registered Events: (none)
  Request: REQUEST_DATA_OBJECT
  FROM_OUTPUT_PORT: 0
  ALGORITHM_AFTER_FORWARD: 1
  FORWARD_DIRECTION: 0

vtkMultiBlockDataSet is not derived from vtkDataSet, so you probably need these adjustments:

  • set inputType='vtkMultiBlockDataSet' in your VTKPythonAlgorithmBase.__init__ call (it defaults to vtkDataSet)
  • use vtkMultiBlockDataSet.GetData(inInfo[0]) in RequestData

I’m still getting the same error. I’ve pared down my code to the bare minimum.

from vtkmodules.vtkCommonDataModel import vtkDataSet
from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase
from vtkmodules.numpy_interface import dataset_adapter as dsa
from paraview.util.vtkAlgorithm import smproxy , smproperty , smdomain
import numpy as np

@smproxy.source(label="CR3BP Traj")
@smproperty.input(name="Input")
# @smdomain.datatype(dataTypes=["vtkMultiBlockDataSet"], composite_data_supported=True)
class PythonCR3BPTrajSource(VTKPythonAlgorithmBase):
    def __init__(self):
        VTKPythonAlgorithmBase.__init__(self,
                                        nInputPorts=1,
                                        inputType='vtkMultiBlockDataSet',
                                        nOutputPorts=1,
                                        outputType='vtkMultiBlockDataSet')

    def RequestData(self, request, inInfo, outInfo):
        input0 = vtkMultiBlockDataSet.GetData(inInfo[0])
        input1 = dsa.WrapDataObject(vtkMultiBlockDataSet.GetData(inInfo[0]))
        input2 = self.GetInputData(inInfo, 0, 0)
        return 1
 Input port 0 of algorithm vtkPythonAlgorithm(0x7f1454010af0) has 0 connections but is not optional.
ERROR: In /home/buildslave/dashboards/buildbot/paraview-pvbinsdash-linux-shared-release_superbuild/build/superbuild/paraview/src/VTK/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 668
vtkPVCompositeDataPipeline (0xa2cbc90): Input port 0 of algorithm vtkPythonAlgorithm(0x7f1454010af0) has 0 connections but is not optional.

This is what ended up working

from vtkmodules.vtkCommonDataModel import vtkDataSet
from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase
from vtkmodules.numpy_interface import dataset_adapter as dsa
from paraview.util.vtkAlgorithm import smproxy , smproperty , smdomain
import numpy as np

@smproxy.filter(name="CR3BP Traj")
@smproperty.input(name="Input")
@smdomain.datatype(dataTypes=["vtkMultiBlockDataSet"], composite_data_supported=True)
class PythonCR3BPTrajSource(VTKPythonAlgorithmBase):
    """
    Example filter demonstrating how to write a filter that preserves the input
    dataset type.
    """
    def __init__(self):
        super().__init__(nInputPorts=1, inputType="vtkMultiBlockDataSet", nOutputPorts=1, outputType="vtkMultiBlockDataSet")
        from vtkmodules.vtkFiltersSources import vtkPolyLineSource

    def RequestData(self, request, inInfo, outInfo):
        inData = self.GetInputData(inInfo, 0, 0)
        self.mu = inData.GetFieldData().GetArray('mu').GetComponent(0,0)
        print(self.mu)
        return 1