Scalar range widget

Hello,

I am building a React app and I need to visualize some vtkjs scenes, and I want to add a scalar range widget like the one you can find on the Calculator example (https://kitware.github.io/vtk-js/examples/Calculator.html)

In my case the scene is loaded with vtkHttpSceneLoader, and I tried attaching a mapper with a lookupTable that I could update like in the example with lookupTable.updateMappingRange, but even though the mapping range is updated there is no effect on my scene, as if the scene just ignores the lookup table. I have tried several ways, including changing the lookupTable of all the mappers of my renderer but no success, the visualization doesn’t change. I have also tried to attach a vtkColorTransferFunction to the mapper as lookup table.

I think I am missing something here, maybe a simple concept I didn’t understand.

Here is my code:

class VtkViewer extends Component {
    constructor(props) {
        super(props);

        this.fullScreenRenderer = null;
        this.container = React.createRef();
        this.updateScalarRange = this.updateScalarRange.bind(this);
    }

    componentDidMount() {
        const { vtk } = window;

        this.fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
            rootContainer: this.container.current,
            containerStyle: {},
        });
        this.renderer = this.fullScreenRenderer.getRenderer();
        this.renderWindow = this.fullScreenRenderer.getRenderWindow();

        // One of the tests: create a lookupTable from vtkColorTransferFunction
        // I also tried with a regular vtkLookupTable instance
        // this.lookupTable = vtkColorTransferFunction.newInstance();
        // const preset = vtkColorMaps.getPresetByName('erdc_rainbow_bright');
        // const dataRange = [0, 255];
        // this.lookupTable.applyColorMap(preset);
        // this.lookupTable.setMappingRange(...dataRange);
        // this.lookupTable.updateRange();

        this.mapper = vtkMapper.newInstance({
            interpolateScalarsBeforeMapping: true,
            useLookupTableScalarRange: false,
            // lookupTable: this.lookupTable,
        });
        this.actor = vtkActor.newInstance();

        // Add scalar range controller
        this.addControlPanel();

        if (_.isEmpty(vtk)) {
            return;
        }

        // Step 1: only display the first vtk
        const dataAccessHelper = DataAccessHelper.get('zip', {
            zipContent: vtk[0],
            callback: () => {
                const sceneImporter = vtkHttpSceneLoader.newInstance({
                    renderer: this.renderer,
                    dataAccessHelper,
                }, {
                    actor: this.actor,
                    mapper: this.mapper,
                    // lookupTable: this.lookupTable,
                });
                sceneImporter.setUrl('index.json');
                this.onReady(sceneImporter);
            },
        });
    }

    onReady(sceneImporter) {
        sceneImporter.onReady(() => {
            this.renderWindow.render();
        });

        window.addEventListener('dblclick', () => {
            sceneImporter.resetScene();
            this.renderWindow.render();
        });
    }

    addControlPanel() {
        const { intl } = this.props;

        this.fullScreenRenderer.addController(`
            <table>
                <tr><td>${intl.formatMessage({ id: 'labels.vtk.scalarRange' })}</td></tr>
                <tr>
                    <td data-children-count="1">
                        <input class="min" type="text" style="width: 100%;" value="0">
                    </td>
                    <td data-children-count="1">
                        <input class="max" type="text" style="width: 100%;" value="1">
                    </td>
                </tr>
            </table>
        `);

        document.querySelector('.min').addEventListener('input', this.updateScalarRange);
        document.querySelector('.max').addEventListener('input', this.updateScalarRange);
    }

    updateScalarRange() {
        const min = Number(document.querySelector('.min').value);
        const max = Number(document.querySelector('.max').value);

        if (!Number.isNaN(min) && !Number.isNaN(max)) {
            // this.lookupTable.setMappingRange(min, max);
            // this.mapper.updateLookupTable();
            this.renderer.getActors().forEach((actor) => {
                actor.getMapper().getLookupTable().setMappingRange(min, max);
                if (actor.getMapper().getLookupTable().updateRange) { // for vtkColorTransferFunction
                    actor.getMapper().getLookupTable().updateRange();
                }
            });
            this.renderer.getActors().forEach((actor) => {
                console.log(actor.getMapper().getLookupTable().getMappingRange());
            });
            this.renderWindow.render();
        }
    }

    render() {
        return <div className={style.container} ref={this.container} />;
    }
}

You are missing that, in your example, you’ve set it to false rather than true.

Thank you for your answer

Actually I also tried to set it to true, and add or not a lookup table manually instanciated, but no changes on the view when I update the min/max values

Oh, I think I know why. How did you get the scene? From the macro? If so, the macro compute the RGB and therefore no more color adjustment. :wink:

I have a better exporter in the work that truly export the array for the scene loader but I didn’t get a chance to finish its integration in ParaView… But it is available in VTK/C++…

Ah yes indeed the scene is exported from the macro! Thank you!

I think we will change the way we get the scene I don’t know yet, but anyway thank you for your help to find the origin of the problem :slight_smile:

Here is the other code that you can use to export the scene. https://github.com/Kitware/VTK/blob/master/Web/Python/vtkmodules/web/vtkjs_helper.py

Hi Jourdain, As per the above mentioned, we can’t change the scalar range in VTKJS Scene which is exported from the macro. Could you please share the updated python macro which export the array for the scene loader. I am stuck with color adjustment in vtkjs scene. Thanks

If you use ParaView 5.7 or 5.8, you can directly use the scene export function of ParaView without the need of the macro to get the vtkjs file that the macro was producing.

Thanks Jourdian for your quick response… I have been facing some issues( which i haven’t faced with the macro) when vtkjs Scene is directly exported from ParaView 5.7. I will check it in 5.8 and let you know if i face the same issue. Thanks

Hey @Sebastien_Jourdain,
I see that one can only download this vtkjs_helper.py module from github. Correct me if I am wrong but this module is not part of the vtk python package. I am wondering how can we reference this module in our package?

it should be part of vtk assuming that module (web) was enabled inside your vtk build. But based on what you are doing, I don’t think you need it unless you want to use the .vtkjs format rather than .vtp. The benefit of .vtkjs is that you get the rendering settings capture as well.

I looked into the vtk package on my system and I didn’t see “web”. Can you please share how to enable web inside vtk build? I am using vtkjs for a subset of our workflow.

Which version of VTK did you build? In the listing of the modules via ccmake or cmake-gui, search for “web” and enable it.

I am using 9.0.1. I installed this package by simply doing pip install vtk not sure if that’s called a build.

I bet the wheel was not generated with that module on. In which case, it might be easier to just put that file somewhere in your Python and use it as-is.

1 Like