Render Cell Scalars from vtkXMLPolyData?

Seems like this should be simple? I most often read files and write files, and then use ParaView to examine my data - but this time I am trying to render it.

I have a collection of vtkXMLPolyData files that have three CellData arrays, and I’d like to show “Temperature” in the vtkRenderWindow. I know from ParaView that the data is basically 0 to 400 K. This is the code that tries to show the temperature (below). I was hoping to see a black-and-white image, but all I see is just a regular shaded body?

    r = vtkXMLPolyDataReader()
    r.SetFileName(fname)
    r.Update()

    lut = vtkLookupTable()
    lut.SetNumberOfTableValues(256)
    lut.SetTableRange(0, 400)
    lut.SetHueRange(0, 0)
    lut.SetValueRange(0, 1)
    lut.SetSaturationRange(0, 0)
    lut.Build()

    m = vtkPolyDataMapper()
    m.SetInputConnection(r.GetOutputPort())
    m.SetScalarModeToUseCellData()
    m.SetArrayName("Temperature")
    m.SetColorModeToMapScalars()
    m.SetScalarRange(0, 400)
    m.SetScalarVisibility(True)
    m.SetLookupTable(lut)

    a = vtkActor()
    a.SetMapper(m)
    a.RotateX(-20)
    a.RotateY(50)

    ren = vtkRenderer()
    ren.AddActor(a)
    renWin = vtkRenderWindow()
    renWin.AddRenderer(ren)

    iren = vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
    style = vtkInteractorStyleTrackballCamera()
    iren.SetInteractorStyle(style)

    renWin.SetSize(300, 300)
    renWin.SetWindowName("Solid Body")
    iren.Initialize()
    ren.ResetCamera()
    renWin.Render()
    iren.Start()

Hello,

The following setup works for me (C++):


    (...)

    size_t tableSize = 32; //32 colors, you may want to increase this to a larger number of shades.
    double min = 0.0; //0K min temperature
    double max = 400.0; //400K max temperature

    //create a color interpolator object
    vtkSmartPointer<vtkColorTransferFunction> ctf =
            vtkSmartPointer<vtkColorTransferFunction>::New();
    ctf->SetColorSpaceToRGB();
    double delta = max - min;
    ctf->AddRGBPoint(min               , 0.000, 0.000, 1.000);
    ctf->AddRGBPoint(min + delta * 0.25, 0.000, 1.000, 1.000);
    ctf->AddRGBPoint(min + delta * 0.50, 0.000, 1.000, 0.000);
    ctf->AddRGBPoint(min + delta * 0.75, 1.000, 1.000, 0.000);
    ctf->AddRGBPoint(max               , 1.000, 0.000, 0.000);
    return ctf;

    //create the color table object
    vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    lut->SetTableRange(min, max);
    lut->SetNumberOfTableValues(tableSize);
    for(size_t i = 0; i < tableSize; ++i)
    {
        double *rgb;
        rgb = ctf->GetColor(static_cast<double>(i)/tableSize);
        lut->SetTableValue(i, rgb[0], rgb[1], rgb[2]);
    }
    lut->SetRampToLinear();
    lut->Build();

    // Create a visualization parameters object
    vtkSmartPointer<vtkPolyDataMapper> mapper =
      vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(r->GetOutputPort());
    mapper->SetLookupTable(lut);
    mapper->SetScalarModeToUseCellData();
    mapper->SetColorModeToMapScalars();
    mapper->SelectColorArray("Radiance"); //<-- are you sure the temperature field is called "Radiance"?
    mapper->SetScalarRange(min, max);

    (...)

This shouldn’t be difficult to port to Python/Javascript since the API is much like the same.

I hope this helps,

PC

Still gives me just one color - I changed m.SetArrayName("Temperature") to m.SelectColorArray("Temperature").

I’m pretty sure that the vtkLookupTable is configured correctly. I stopped in the debugger after the table was built and checked values:

a = [0, 0, 0]
lut.GetColor(0, a); a
# prints [0.0, 0.0, 0.0]
lut.GetColor(200, a); a
# prints[0.5, 0.5, 0.5] (well, close to it anyhow)
lut.GetColor(400, a); a
# prints[1.0, 1.0, 1.0]

The shape of the geometry shows up, so I don’t think I’m missing an Update anywhere … my vtkPolyDataMapper is essentially the same as yours, with the change I made to match mine to yours (unless the order of the calls matters??)

Is there some setting I need to set on the vtkActor?

I believe we need to take a look at the code used to make the actor as well as reading the XML data to build the vtkXMLPolyData object. Sharing the source XML file is also helpful.

The code for the actor was in the block above, but I’ll reproduce it here:

    a = vtkActor()
    a.SetMapper(m)
    a.RotateX(-20)
    a.RotateY(50)

    ren = vtkRenderer()
    ren.AddActor(a)
    renWin = vtkRenderWindow()
    renWin.AddRenderer(ren)

    iren = vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
    style = vtkInteractorStyleTrackballCamera()
    iren.SetInteractorStyle(style)

    renWin.SetSize(300, 300)
    renWin.SetWindowName("Solid Body")
    iren.Initialize()
    ren.ResetCamera()
    renWin.Render()
    iren.Start()

The code for reading the file also reproduced:

    r = vtkXMLPolyDataReader()
    r.SetFileName(fname)
    r.Update()

I’ll see if I can find a suitable XML file to share, but the one I am working on now is customer’s data, and I’m not sure I can share. However, it does show up fine in ParaView.

Ok - I have a datafile that shows temperature in ParaView, but does NOT show it with my script.
hot_tetra.vtp (2.6 KB)

Below is the entire script:

#!/usr/bin/env python3
import vtkmodules.vtkRenderingOpenGL2

from glob import glob
from vtkmodules.vtkCommonCore import vtkLookupTable
from vtkmodules.vtkIOImage import vtkPNGWriter
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkPolyDataMapper,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer)
from vtkmodules.vtkIOXML import vtkXMLPolyDataReader

MAX_TEMPERATURE = 400

def debug_view(fname):
    import sys
    from vtkmodules.vtkInteractionStyle import vtkInteractorStyleTrackballCamera

    r = vtkXMLPolyDataReader()
    r.SetFileName(fname)
    r.Update()

    lut = vtkLookupTable()
    lut.SetNumberOfTableValues(256)
    lut.SetTableRange(0, MAX_TEMPERATURE)
    lut.SetHueRange(0, 0)
    lut.SetValueRange(0, 1)
    lut.SetSaturationRange(0, 0)
    lut.Build()

    m = vtkPolyDataMapper()
    m.SetInputConnection(r.GetOutputPort())
    m.SetLookupTable(lut)
    m.SetColorModeToMapScalars()
    m.SetScalarModeToUseCellData()
    m.SetScalarRange(0, MAX_TEMPERATURE)
    m.SelectColorArray("Temperature")
    m.SetScalarVisibility(True)

    a = vtkActor()
    a.SetMapper(m)
    a.RotateX(-20)
    a.RotateY(50)

    ren = vtkRenderer()
    ren.AddActor(a)
    renWin = vtkRenderWindow()
    renWin.AddRenderer(ren)

    iren = vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
    style = vtkInteractorStyleTrackballCamera()
    iren.SetInteractorStyle(style)

    renWin.SetSize(300, 300)
    renWin.SetWindowName("Tetra")
    iren.Initialize()
    ren.ResetCamera()
    renWin.Render()
    iren.Start()

if __name__ == "__main__":
    debug_view("hot_tetra.vtp")

Hello,

I fear it isn’t yet. Your code is missing the vtkColorTransferFunction part and how this object is used to correctly build the color lookup table. It is in the C++ working example I posted earlier.

best,

PC

Changed my table code to mimic your C++ example, and still don’t get coloring. :frowning:

    ctf = vtkColorTransferFunction()
    ctf.SetColorSpaceToRGB()
    ctf.AddRGBPoint(0, 1.0, 0.0, 0.0)
    ctf.AddRGBPoint(MAX_RADIANCE, 0.0, 1.0, 1.0)

    lut = vtkLookupTable()
    lut.SetNumberOfTableValues(TABLE_SIZE)
    for i in range(TABLE_SIZE):
        rgb = ctf.GetColor(i/TABLE_SIZE)
        lut.SetTableValue(i, *rgb)
    lut.SetRampToLinear()
    lut.Build()

Not quite, yet. This call is still missing in your code:

    lut.SetTableRange(0, MAX_RADIANCE)

Same result: no color

    ctf = vtkColorTransferFunction()
    ctf.SetColorSpaceToRGB()
    ctf.AddRGBPoint(0, 1.0, 0.0, 0.0)
    ctf.AddRGBPoint(MAX_RADIANCE, 0.0, 1.0, 1.0)

    lut = vtkLookupTable()
    lut.SetNumberOfTableValues(TABLE_SIZE)
    lut.SetTableRange(0, MAX_RADIANCE)
    for i in range(TABLE_SIZE):
        rgb = ctf.GetColor(i/TABLE_SIZE)
        lut.SetTableValue(i, *rgb)
    lut.SetRampToLinear()
    lut.Build()

How does it appear in ParaView?

Try to configure your mapper this way (no more, no less):

    m = vtkPolyDataMapper()
    m.SetInputConnection(r.GetOutputPort())
    m.SetLookupTable(lut)
    m.SetScalarModeToUseCellData()
    m.SetColorModeToMapScalars()
    m.SelectColorArray("Temperature")
    m.SetScalarRange(0, MAX_TEMPERATURE)

Still no color … edited script below.

#!/usr/bin/env python3
import vtkmodules.vtkRenderingOpenGL2

from glob import glob
from vtkmodules.vtkCommonCore import vtkLookupTable
from vtkmodules.vtkIOImage import vtkPNGWriter
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkColorTransferFunction,
    vtkPolyDataMapper,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer)
from vtkmodules.vtkIOXML import vtkXMLPolyDataReader

MAX_TEMP = 400
TABLE_SIZE = 256

def debug_view(fname):
    import sys
    from vtkmodules.vtkInteractionStyle import vtkInteractorStyleTrackballCamera

    r = vtkXMLPolyDataReader()
    r.SetFileName(fname)
    r.Update()

    ctf = vtkColorTransferFunction()
    ctf.SetColorSpaceToRGB()
    ctf.AddRGBPoint(0, 1.0, 0.0, 0.0)
    ctf.AddRGBPoint(MAX_TEMP, 0.0, 1.0, 1.0)

    lut = vtkLookupTable()
    lut.SetNumberOfTableValues(TABLE_SIZE)
    lut.SetTableRange(0, MAX_TEMP)
    for i in range(TABLE_SIZE):
        rgb = ctf.GetColor(i/TABLE_SIZE)
        lut.SetTableValue(i, *rgb)
    lut.SetRampToLinear()
    lut.Build()

    m = vtkPolyDataMapper()
    m.SetInputConnection(r.GetOutputPort())
    m.SetLookupTable(lut)
    m.SetScalarModeToUseCellData()
    m.SetColorModeToMapScalars()
    m.SelectColorArray("Temperature")
    m.SetScalarRange(0, MAX_TEMP)

    a = vtkActor()
    a.SetMapper(m)
    a.RotateX(-20)
    a.RotateY(50)

    ren = vtkRenderer()
    ren.AddActor(a)
    renWin = vtkRenderWindow()
    renWin.AddRenderer(ren)

    iren = vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
    style = vtkInteractorStyleTrackballCamera()
    iren.SetInteractorStyle(style)

    renWin.SetSize(300, 300)
    renWin.SetWindowName("Tetra")
    iren.Initialize()
    ren.ResetCamera()
    renWin.Render()
    iren.Start()

if __name__ == "__main__":
    debug_view("hot_tetra.vtp")

Take a look at this example: https://examples.vtk.org/site/Python/Visualization/AssignCellColorsFromLUT/

1 Like

That was the missing clue, I think. There was a note in there that mentioned SetScalars … I guess I had naively assumed that storing arrays would make them available to use for the mapper. I guess in ParaView, it figures it out, but in raw VTK, there is a difference between an array in the cell data, and a scalar in the cell data.

The change that needed to be made was to set the temperature array as the scalars for the cell data.

Here’s the script that works now:

#!/usr/bin/env python3
import vtkmodules.vtkRenderingOpenGL2

from glob import glob
from vtkmodules.vtkCommonCore import vtkLookupTable
from vtkmodules.vtkIOImage import vtkPNGWriter
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkColorTransferFunction,
    vtkPolyDataMapper,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer)
from vtkmodules.vtkIOXML import vtkXMLPolyDataReader

MAX_TEMP = 300
TABLE_SIZE = 256

def debug_view(fname):
    import sys
    from vtkmodules.vtkInteractionStyle import vtkInteractorStyleTrackballCamera

    r = vtkXMLPolyDataReader()
    r.SetFileName(fname)
    r.Update()

    pd = r.GetOutput()
    t = pd.GetCellData().GetArray("Temperature")
    pd.GetCellData().SetScalars(t)

    ctf = vtkColorTransferFunction()
    ctf.SetColorSpaceToRGB()
    ctf.AddRGBPoint(0, 1.0, 0.0, 0.0)
    ctf.AddRGBPoint(MAX_TEMP, 0.0, 0.0, 1.0)

    lut = vtkLookupTable()
    lut.SetNumberOfTableValues(TABLE_SIZE)
    lut.SetTableRange(0, MAX_TEMP)
    lut.SetRampToLinear()
    lut.Build()

    m = vtkPolyDataMapper()
    m.SetInputData(pd)
    m.SetLookupTable(lut)
    m.SetScalarModeToUseCellData()
    m.SetColorModeToMapScalars()
    m.SelectColorArray("Temperature")
    m.SetScalarRange(0, MAX_TEMP)

    a = vtkActor()
    a.SetMapper(m)
    a.RotateX(-20)
    a.RotateY(50)

    ren = vtkRenderer()
    ren.AddActor(a)
    renWin = vtkRenderWindow()
    renWin.AddRenderer(ren)

    iren = vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
    style = vtkInteractorStyleTrackballCamera()
    iren.SetInteractorStyle(style)

    renWin.SetSize(300, 300)
    renWin.SetWindowName("Tetra")
    iren.Initialize()
    ren.ResetCamera()
    renWin.Render()
    iren.Start()

if __name__ == "__main__":
    debug_view("hot_tetra.vtp")

1 Like