How to Show() a simple vtkImageData object

How does one create a simple 2D mesh plot using ParaView from a vtkImageData object. This type of object is mentioned in the ParaView Guide in “3. Understanding data”, but it is never shown how to use use it directly.

import numpy as np
from paraview import vtk, simple
from paraview.vtk.util.numpy_support import numpy_to_vtk
from vtk import vtkImageDataGeometryFilter  # this isn't in paraview.vtk

# Create an image (this is a data object)
myMesh = vtk.vtkImageData()
myMesh.SetOrigin(0., 0., 0.)
myMesh.SetSpacing(0.01, 0.01, 0.)
myMesh.SetExtent(0, 100, 0, 50, 0, 0)

# coloring
blue = np.array([15, 82, 186], dtype=np.ubyte)
# numpy colors
scalarsnp = np.tile(blue, (myMesh.GetNumberOfCells(), 1))
# vtk array colors. Organized as 50 tuples of 3
scalarsvtk = numpy_to_vtk(scalarsnp, deep=1, array_type=vtk.VTK_UNSIGNED_CHAR)

# allocate the scalars to the vtkImageData object
# Not sure why the following line is not necessary (tested using VTK)
# myMesh.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 3)  # set 3 scalars per cell
myMesh.GetCellData().SetScalars(scalarsvtk)

# generate a vtkPolyData from the vtkImageData
myMeshPD = vtkImageDataGeometryFilter()
myMeshPD.SetInputData(myMesh)

# more code...

simple.Show(??)
simple.Interact()  # or simple.Render()

Now if I were to use pure VTK, I’d create a mapper, an actor and render everything to a window.

The question is, at which point of the above pipeline is it possible to use Paraview, if at all?

From my very limited understanding on the subject, I think it is possible to generate a proxy out one of the aforementioned objects (using paraview.servermanager maybe?) and then use paraview.simple.Show. But I am not sure and am completely lost in the Paraview documentation.

You need to “send” your image data to the paraview server. This is only possible in builtin mode uising a TrivialProducer and GetClientSideObject.

1 Like

Thank you Mathieu!

I’ve successfully rendered the mesh in ParaView! Instead of vtkImageDataGeometryFilter, I can use vtkTextureMapToPlane, or rather TextureMaptoPlane from paraview.simple.

Though, I think I might have found a bug in version 5.9.1.

You see, if I use, from the above example:

myMesh.GetCellData().SetScalars(scalarsvtk)

then ParaView cannot see the colors array.

Instead, the following has to be done (taken from this VTK pipermail vtkusers):

scalarsvtk = numpy_to_vtk(scalarsnp, deep=1, array_type=vtk.VTK_UNSIGNED_CHAR)
scalarsvtk.SetName("colorsArray")
colorArrayID = myMesh.GetCellData().AddArray(scalarsvtk)
myMesh.GetCellData().SetActiveScalars(scalarsvtk.GetName())

Edit: in other words, I changed from using SetScalars to using AddArray and SetActiveScalars. Then ParaView managed to access the array.

A minimum working example (which could be used for a github/paraview/examples page, sort of like VTK):

from paraview import simple as ps
from paraview import vtk
from paraview.vtk.util.numpy_support import numpy_to_vtk
import numpy as np

def main():
    # Create an image (this is a data object)
    myMesh = vtk.vtkImageData()
    myMesh.SetOrigin(0., 0., 0.)
    myMesh.SetSpacing(0.1, 0.1, 0.)
    myMesh.SetExtent(0, 10, 0, 5, 0, 0)

    # coloring
    blue = np.array([15, 82, 186], dtype=np.ubyte)
    # numpy colors
    scalarsnp = np.tile(blue, (myMesh.GetNumberOfCells(), 1))
    scalarsnp[[9, 49]] = np.array([255, 255, 0], dtype=np.ubyte)  # yellow

    # vtk array colors. Organized as 50 tuples of 3
    scalarsvtk = numpy_to_vtk(scalarsnp, deep=1, array_type=vtk.VTK_UNSIGNED_CHAR)
    scalarsvtk.SetName("colorsArray")
    # allocate the scalars to the vtkImageData object
    # myMesh.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 3)  # set 3 scalars per cell
    # myMesh.GetCellData().SetScalars(scalarsvtk)  # do not use this in ParaView!!
    colorArrayID = myMesh.GetCellData().AddArray(scalarsvtk)
    myMesh.GetCellData().SetActiveScalars(scalarsvtk.GetName())

    # TrivialProducer to interface ParaView to serverside objects
    tp_mesh = ps.TrivialProducer(registrationName="tp_mesh")
    myMeshClient = tp_mesh.GetClientSideObject()
    # link the vtkImageData object to the proxy manager
    myMeshClient.SetOutput(myMesh)
    tp_mesh.UpdatePipeline()

    # Filter for showing the ImageData to a plane
    mapTexture2Plane = ps.TextureMaptoPlane(registrationName="TM2P_mesh", Input=tp_mesh)

    renderViewMesh = ps.CreateView("RenderView")
    renderViewMesh.Background = [1, 1, 1]
    renderViewMesh.OrientationAxesVisibility = 0
    display = ps.Show(proxy=mapTexture2Plane, view=renderViewMesh)
    display.SetRepresentationType("Surface")
    display.MapScalars = 0  # necessary so as to not generate a colormap
    ps.Interact()  # or just ps.Render()


if __name__ == "__main__":
    main()

Edited to disable scalar mapping. Also hid the orientation axes.

Output:
untitled

Before I close this issue, though, it seems that the yellow cells from the above minimum working example are being shown as red instead of yellow. Is there something more to the array orders that I have missed?

untitled

Please share the faulty data

After some testing, it seems that the data is not faulty. I am just not using the ParaView filters correctly. It seems to automatically apply a color map instead of assigning the given RGB colors as the face color for each cell. A legacy ASCII VTK file of the imagedata can be found attached. I simplified the blue color to be [0 0 255] for an easier read.
ImageData.vtk (519 Bytes)

From what I’ve read in the VTK doxygen, I have to enable the creation of a lookuptable based on the CellData, for the colors. I’m not sure which method I should use for this. And whether it is in the vtkImageData itself, or in the object obtained after applying the filter in ParaView. The class that has this functionality seems to be vtkMapper. Not sure how to use it.

Uncheck the Map Scalars option in the properties panel.

2 Likes

Thank you Kenneth! That does the job. I had to Toggle advanced properties to find that option.