Correctly using vtkDataArraySelection in Python algorithm custom filter


I’m trying to implement a simple custom filter using the VTKPythonAlgorithmBase. I’d like to include a vtkDataArraySelection and am now struggling with how to correctly use it.
Following the tutorials (VTK Python algorithm and Python algorithm examples), in RequestData() I can simply write

input0 = dsa.WrapDataObject(vtkDataSet.GetData(inInfo[0]))

and directly inspect all the arrays from there and add them to my ArraySelection. However, it seems reasonable that array selection should be done before the actual computation. So I though of moving that functionality into the RequestInformation method. However, it appears that GetData does not work there, I get an error in that line.
So I wanted to ask if I can inspect data array names and add them to the selection at that point of pipeline execution at all and if so, how to do it. I’m really sorry if this is obvious, but I’m not that familiar with VTK and could not find information on how to do this.

Thanks in advance!

Your observations are indeed correct: RequestInformation is the space to fill up meta-data in things like vtkDataArraySelection; RequestInformation does have valid input data available.

vtkDataArraySelection is intended for readers and data-sources and not filters. Since data sources don’t have inputs, they can glean enough meta-data in RequestInformation to fill up vtkDataArraySelection.

For selection of array on filters, we instead let ParaView populate the list of available arrays in the input. This is done through domains. Before I point to an example, can you elaborate what kind of selection are you interested in? Are you letting user select a single array or choose multiple arrays? If you point to an existing filter in ParaView that supports what you want, it’d be easy to demonstrate how to do that in PythonAlgorithms.

Thank you very much for the response! I had no idea vtkDataArraySelection is only used in readers and sources.

I’d like the user to be able to select multiple arrays. Knowing all data array names in the filter’s input would be enough information. However I’d like to also be able to adjust the names of the arrays shown in the selection; these should not necessarily be identical to those in the input.
Is that possible?

Thanks in advance!

@utkarsh.ayachit could you send me a link to such an example you mentioned above? That would be great!

Here’s a modified version of the NumpyWriter in the that adds API to let user choose input arrays to write. The callbacks don’t actually do anything here, but you you make that update/clear the vtkDataArraySelection object you’re holding to track which arrays are chosen.

# A writer example.
@smproxy.writer(extensions="npz", file_description="NumPy Compressed Arrays", support_reload=False)
@smproperty.input(name="Input", port_index=0)
@smdomain.datatype(dataTypes=["vtkTable"], composite_data_supported=False)
class NumpyWriter(VTKPythonAlgorithmBase):
    def __init__(self):
        VTKPythonAlgorithmBase.__init__(self, nInputPorts=1, nOutputPorts=0, inputType='vtkTable')
        self._filename = None

    @smproperty.stringvector(name="FileName", panel_visibility="never")
    def SetFileName(self, fname):
        """Specify filename for the file to write."""
        if self._filename != fname:
            self._filename = fname

    @smproperty.stringvector(name="Arrays", number_of_elements_per_command=1, \
                             repeat_command=1, clean_command="ClearChosenArrays")
        <ArrayListDomain attribute_type="Scalars" name="array_list">
            <Property function="Input" name="Input" />
    def ChooseArray(self, name):
        print("choosing array", name)

    def ClearChosenArrays(self):

    def RequestData(self, request, inInfoVec, outInfoVec):
        from vtkmodules.vtkCommonDataModel import vtkTable
        from vtkmodules.numpy_interface import dataset_adapter as dsa

        table = dsa.WrapDataObject(vtkTable.GetData(inInfoVec[0], 0))
        kwargs = {}
        for aname in table.RowData.keys():
            kwargs[aname] = table.RowData[aname]

        import numpy
        numpy.savez_compressed(self._filename, **kwargs)
        return 1

    def Write(self):

I do not follow this part. Can you elaborate what do you mean please?