Customize Python View with Python plugins

This is an example of how to customize dynamically your Python View by adding parameters in ParaView linked to your Python View through the use of a custom Python Plugin (adding a Python Filter).

In this example, we will manipulate the number of bins of an histogram from our Python View. You may find the full example with the data below.
python_view_scripting.zip (72.8 KB)

Python Plugin

Creating the Python Filter

What you will want to do to add parameters to your Python View is to first create a Python Plugin that you will load in ParaView to get your custom Python Filter. For this, go ahead and create a new Python file declaring a new filter Python Filter with its base structure.

from paraview.util.vtkAlgorithm import *
from vtkmodules.numpy_interface import dataset_adapter as dsa
from vtkmodules.vtkCommonDataModel import vtkDataSet

@smproxy.filter(name="PythonViewHelperFilter")
@smproperty.input(name="Input")
@smdomain.datatype(dataTypes=["vtkDataSet"], composite_data_supported=False)
class PythonViewHelperFilter(VTKPythonAlgorithmBase):
    def __init__(self):
        super().__init__(nInputPorts=1, nOutputPorts=1, inputType="vtkDataSet", outputType="vtkDataSet")
        self._arrayName = None
        self._arrayValue = 0


    def RequestDataObject(self, request, inInfo, outInfo):
        inData = self.GetInputData(inInfo, 0, 0)
        outData = self.GetOutputData(outInfo, 0)
        assert inData is not None
        if outData is None or (not outData.IsA(inData.GetClassName())):
            outData = inData.NewInstance()
            outInfo.GetInformationObject(0).Set(outData.DATA_OBJECT(), outData)
        return super().RequestDataObject(request, inInfo, outInfo)

    def RequestData(self, request, inInfo, outInfo):
        input = dsa.WrapDataObject(vtkDataSet.GetData(inInfo[0]))
        output = dsa.WrapDataObject(self.GetOutputData(outInfo, 0))

        output.ShallowCopy(input.VTKObject)

        return 1

Here we are declaring a simple filter that takes a vtkDataSet and returns the exact same input. You can see that I added two parameters that we will want to manipulate when applying this filter. But for now, they don’t appear in ParaView.

python_filter_no_params

Let’s add the necessary to make them editable from ParaView before to explain their use.

    @smproperty.stringvector(name="ArrayName", default_values="bins")
    def SetArrayName(self, fname):
        if self._arrayName != fname:
            self._arrayName = fname
            self.Modified()


    @smproperty.intvector(name="ArrayValue", default_values=32)
    def SetArrayValue(self, value):
        if self._arrayValue != value:
            self._arrayValue = value
            self.Modified()

Now, we have two parameters we can modify inside ParaView. The first one is optional, it’s the name of the array we will create to pass our parameters to the Python View. It can be useful to expose it though in order to allow quick modification in the Python View script. The second parameter is the actual value we want to pass to the Python View, in this case the number of bins of an histogram.

python_filter_params

The last thing needed to make it work is adding the logic in the RequestData method. Using numpy interface, it’s easy to add tables to the output. Simply add the following before the return.

        output.PointData.append(self._arrayValue, self._arrayName)

Using the plugin

To use our freshly created plugin in ParaView, we have to import it. For this, open ParaView and click on Tools / Manage Plugins... on the menu bar. From there, you can Load New... and look for your Python file.

You now have loaded you Python Plugin. You can apply it on your data. Here, I will apply it on the blow.vtk dataset that you can find in ParaView Examples, or in the archive available at the top of the topic. After applying the filter, you should still see your dataset unchanged. Go in the Information panel and see your new Data Array being displayed.

python_filter_applied

Python View

The next step is to create our Python View. After applying your custom filter on your data, you may split the render screen and create a new Python View. Then, you can add your own script to the view. Here is an example of a simple Python View displaying an histogram of the displacement6 data array available on the given dataset.

from paraview import python_view
import paraview.vtk.util.numpy_support as ns
from vtkmodules.numpy_interface import dataset_adapter as dsa
from vtkmodules.vtkCommonDataModel import vtkDataSet

def setup_data(view):
  for i in range(view.GetNumberOfVisibleDataObjects()):
    view.DisableAllAttributeArrays()
    view.SetAttributeArrayStatus(i, dsa.ArrayAssociation.POINT, "displacement6", 1)


def render(view, width, height):
  figure = python_view.matplotlib_figure(width, height)
  figure.set_facecolor('white')

  plot = figure.add_subplot(2,1,1)
  plot.set_title('Displacement histogram')

  for i in range(view.GetNumberOfVisibleDataObjects()):
    dataObject = view.GetVisibleDataObjectForRendering(i)

    if not isinstance(dataObject, vtkDataSet):
      continue

    disp = dataObject.GetPointData().GetArray("displacement6")
    npDisp = ns.vtk_to_numpy(disp)

    nbBins = 32
    plot.hist(npDisp, bins=nbBins)

  vtk_image = python_view.figure_to_image(figure)
  return vtk_image

At this point, your Python View should look like this.

python_view_unchanged

An optional thing you can do for quick modifications and a better legibility is to declare at the top of your script a variable that will keep the name of your array. This will avoid repeating your array’s name in the script. Here I declare the name of the array right after the imports to be able to see it easily in the script text area.

BINS_ARRAY_NAME = "bins"

At this point, you should be able to make match names easily.

python_view_script

Lastly, we will make use of this variable and allows passing our data array to the Python View. First, setup your array in the setup_data method in the loop.

    view.SetAttributeArrayStatus(i, dsa.ArrayAssociation.POINT, BINS_ARRAY_NAME, 1)

And then, you can retrieve your information in the variable storing the number of bins.

    bins = dataObject.GetPointData().GetArray(BINS_ARRAY_NAME)
    if bins is not None:
      nbBins = bins.GetValue(0)

Congratulations! You just customized your Python View with a simple Python Plugin =)
You can now change the value in your filter and the change should appear in your Python View when you apply it. Try setting the number of bins to 4 and here is what you should see.

python_view_changed

Do not hesitate to download the archive to get the full code explained here. It comes with comments to guide you.

4 Likes

Hey,

I had a question about this code. Is there a way to do this for a text file or a csv file instead of vtk format, and also I was wondering where you extract the raw data from the file as what I want to do is print out the data into the output messages box, but can only get it to print random stuff.

Hey,

In this example, I’m using a file in the vtk format, but of course you could open any file format that is supported by ParaView. It will use the right vtk reader for you.

In the script field, you can use the print command to display messages on the Output Message panel.

Hope this helps! :slight_smile:

Thank You for the reply. I am confused on how to get the script field to show up, and what to put inside the print statement, because I don’t know where all the data is being stored in the code. When I load both the plugins into Paraview, the PythonViewHelperFilter shows up but only displays the attached image


I was also wondering if there was a way to print directly in the code and where I should put the print statement if I wanted to get the data from the pipeline browser and print it to the output messages.

Once again, Thank You So Much and have a great day :smiley:

Hello again!

Just to be sure you understood the purpose of this article, this is an example of how to customize a Python View, and not an example of how to use Python in ParaView. If you just want to see some of your data or manipulate it through Python, you could use the Python Shell. See this for more information.

If the Python View is really what you’re looking for, you may want to read this if you haven’t yet. Once you’re all set, make sure to create a Python View in ParaView. For this, you can remove your current Render View, or split it. Then, you will find the Script field in the Properties panel (your screenshot shows the Information panel). From there, you can add print instructions that will display information in the Output Message panel. The input from your pipeline will be available for you to display any information. To know how to access properties and arrays, my previous links should be enough. Do not hesitate if you need further information.

1 Like