Different pipeline behavior in ParaView vs straight VTK

Hello,

I am working on a small ParaView plugin to read a custom data object and implement some filters on this data. My data objects extend vtkDataObject and my filters extend vtkAlgorithm. I am completely new to VTK and ParaView but I have managed to put together a small framework that allows ParaView to create my custom VTK object, read my data, and render the data on the screen.

Here is the snag. My custom VTK object contains member data that I would like to use down the pipeline. However, when my object is passed from my reader to my first filter I can see that the memory address has changed and the member data is no longer initialized and I have to perform an expensive re-initilization of the data before continuing. BUT when I recreate the same pipeline by hand in a simple C++ executable, the pipeline seems to work as I expected with the memory addresses matching and of course all member data is correct. I assumed that there may be a shallow copy happening so I even re-implemented the ShallowCopy method to copy my member data, only to later realize that the ShallowCopy was never called.

So my question is what does ParaView do differently between pipeline connections to pass data between filters and what can I do to make sure my data objects are correctly propagated?

I’m attempting to create a minimal example to reproduce this but this minimal plugin is not wrapped correctly by the client/server yet and ParaView cannot load it. (a problem I already fixed with my working plugin, I’m confident it is something I left out by mistake.)

Is that a custom vtkDataSet ? Which do you inherit ?

In any case, creating a new type of dataset correctly is really hard, although possible.

What kind of data are you trying to transfer ?

Hi Mathieu

Thanks for your reply. The object being passed through the pipeline is a class that inherits from vtkDataObject. The member data is not a VTK type. In fact, to make things simpler I created a dummy member variable that is simply an integer. I can initialize it to some known value like 3 when my VTK object is intialized during the RequestDataObject call and after it is passed down the pipeline in ParaView I can see that the member integer is no longer initialized. However, again the behavior in my standlone executable is working as expected with the data object coming into the first filter with the same memory address and member data.

I should also add that the vtkDataArrays associated with my custom VTK data object are transfered correctly, it’s only the additional member data that is not.

Yes but you cant know that VTK will keep creating an object of the right type when it applies filter on it, especially if you inherit from vtkDataObject directly.

Take this:

your reader → clip → your filter

Clip with create a vtkUnstructuredGrid even if your reader produce a specific type.

Even if you consider that you are using only your own filters with your own type, you need at least DeepCopy to be safe, but any filters relying on vtkDataObjectTypes::NewDataObject will not be able to create your type.

ParaView is doing many more things with the data, even between filters. I’d not suggest using such a design pattern.

Once again, if you want to associate some data with your dataset, do not inherit but use actual field form dataset. You could just store the adress of your member as field data converted to int and manager the memory yourself.

This is the core of my original question. The pipeline works as expected in my executable, I am asking what ParaView is doing between filters and it seems that it is performing some copy that is unaware of my data type and therefore also my member data. Fine.

So, my understanding is the only pratical way to propagate information not native to VTK through the pipeline in ParaView is to use the FieldData array. Is this correct? If so, it seems clunky at best when the VTK pipeline without ParaView works nicely with my data object and no additional tricks are needed.

Thank you for your time Mathieu

As a follow-up to this, I followed your suggestion of adding the pointer address to the FieldData as a 64bit integer array and I was able to successfully use the address within my filter. It doesn’t feel great but it does work.

1 Like