ImageData/PolyData XML writer: how save a lookup table associated to a cell data array

I associated a simple lookup table to the cellarray of an image data.

After generating a vtkPolyData from the vtkImageData using vtkImageDataGeometryFilter, it is possible to write the resulting output either to a legacy vtk file using vtkPolyDataWriter or to an XML file using vtkXMLPolyDataWriter.

The legacy vtk file saves the associated lookup table, while XML file does not. Thus, when loading the former in ParaView, it shows the coloring as intended, unlike the latter.

Is there a way to write a “composite” XML file that associates a .vtp file with a .vtt file directly? Or maybe even a .vti file with a .vtt file… Edit: I checked the doxygen more carefully. .vtt files are for vtkTable, not lookup tables. Nvm. Only post I’ve found is an archived post of someone who managed to use a .json file for the lookup table, which I don’t know how to use.

The python script below is a MWE that generates the .vtk and .vtp files. A png image of the output is shown here after the script (the code with the pngwriter is not in the script, for brevity).

import numpy as np
from vtk.util.numpy_support import numpy_to_vtk
import vtk

def main():
    colors = vtk.vtkNamedColors()

    # create color lookup table
    lut = vtk.vtkLookupTable()
    lut.SetNumberOfTableValues(2)
    yellow = colors.GetColor3d("light_goldenrod")
    blue = colors.GetColor3d("royal_blue")
    lut.SetTableValue(0, yellow[0], yellow[1], yellow[2], 0.8)
    lut.SetTableValue(1, blue[0], blue[1], blue[2], 1.0)

    # Create an image
    myMesh = vtk.vtkImageData()
    myMesh.SetOrigin(0., 0., 0.)
    myMesh.SetSpacing(0.01, 0.01, 0.)
    nx = 10
    ny = 5
    myMesh.SetExtent(0, nx, 0, ny, 0, 0)
    # solid or void
    scalarsnp = np.ones(nx*ny, dtype=np.int32)  # all solids
    scalarsnp[[nx-1, nx*ny-1]] = 0  # two voids

    scalarsvtk = numpy_to_vtk(scalarsnp, deep=1, array_type=vtk.VTK_LONG)
    scalarsvtk.SetName("colorsArray")

    scalarsvtk.SetLookupTable(lut)  # associate lookup table to array

    # allocate the scalars to the vtkImageData object
    myMesh.GetCellData().SetScalars(scalarsvtk)

    # create a filter object
    myMeshPolyData = vtk.vtkImageDataGeometryFilter()
    myMeshPolyData.SetInputData(myMesh)

    # write polygonal dataset to legacy vtk
    # this saves the associated lookup table
    vtkWriter = vtk.vtkPolyDataWriter()
    vtkWriter.SetInputConnection(myMeshPolyData.GetOutputPort())
    vtkWriter.SetFileTypeToASCII()
    vtkWriter.SetFileName("./mesh.vtk")
    vtkWriter.SetHeader("Simple colored ImageData")
    vtkWriter.Write()

    # write polygonal dataset to XML vtp file
    # this does not
    vtpWriter = vtk.vtkXMLPolyDataWriter()
    vtpWriter.SetInputConnection(myMeshPolyData.GetOutputPort())
    vtpWriter.SetDataModeToAscii()
    vtpWriter.SetFileName("./mesh.vtp")
    vtpWriter.Write()


if __name__ == '__main__':
    main()

Following the suggestions in this post, using the /Utilities/SaveSceneToFieldData example, I’ve managed to write the lookuptable by getting it via lut.GetTable() and associating it to the vtkImageData's vtkFieldData. The code is simply:

lut.GetTable().SetName("colorsArray")
myMesh.GetFieldData().AddArray(lut.GetTable())

But I still cannot make, for instance, ParaView, use this fielddata as the lookuptable to map the cell scalars.
Interestingly, an issue on this was opened in 2004, but never solved.

The XML Reader and Writer are meant to save data sets while the lookup table is a matters of representation. If you want to save both the data sets and the representation, you may want to export the scene. This can be done using a vtkExporter. Take the implementation of this class that suits your need and use SetRenderWindow to give it the scene to save, it should take the light, camera position and LUT into account if the format accept it.

Thank you for the suggestion. I wanted to avoid using vtkExporter because of the added information being stored, since it is much further down the visualization pipeline.

Instead, I’ve settled for using the field data method. The user has to read the .vti XML file and manually set the field data array as the lookup table for the cell data array.

Suppose the data is written as a .vti file, for simplicity, and continuing the example written in the OP:

    # write polygonal dataset to XML vtp file
    # this does not
    # vtpWriter = vtk.vtkXMLPolyDataWriter()
    # vtpWriter.SetInputConnection(myMeshPolyData.GetOutputPort())
    # vtpWriter.SetDataModeToAscii()
    # vtpWriter.SetFileName("./mesh.vtp")
    # vtpWriter.Write()

    lut.GetTable().SetName("colorsArray")
    myMesh.GetFieldData().AddArray(lut.GetTable())

    vtiWriter = vtk.vtkXMLImageDataWriter()
    vtiWriter.SetInputData(myMesh)
    vtiWriter.SetFileName("./mesh.vti")
    vtiWriter.Write()

    vtiReader = vtk.vtkXMLImageDataReader
    vtiReader.SetFileName("./mesh.vti")
    vtiReader.Update()

    myMesh2 = vtiReader.GetOutput()
    vtiReader.FastDelete()  # is this safe?
    lut2 = vtk.vtkLookupTable()
    lut2.SetTable(myMesh2.GetFieldData().GetArray(0))
    myMesh2.GetCellData().GetArray(0).SetLookupTable(lut2)

It would be great if this could be done implicitly, as in the legacy .vtk files.