vtkPiecewiseGaussianWidget for window/level or CTF editing in 2D

I’m developing a 2D image viewer in VTK.js (using vtkImageSlice + vtkImageMapper) and I’d like to provide an interactive window/level (intensity range) editor.

With given LUT/CTF I’d like to achieve:

  • Let the user adjust the window min/max interactively,

  • Possibly choose a mapping function (e.g. linear or sigmoid),

  • And visualize how the LUT/CTF applies across that range.


What I’ve tried

I’ve been experimenting with the vtkPiecewiseGaussianWidget, since it provides a histogram and looks like a good starting point.

const widget = vtkPiecewiseGaussianWidget.newInstance({
  numberOfBins: 256,
  size: [400, 150],
});
widget.setContainer(widgetContainer);
widget.setColorTransferFunction(ctf);
widget.setDataArray(imageData);
widget.bindMouseListeners();

However, I’m confused about a few points:

  1. What is the purpose of setColorTransferFunction()?

    • I’m not sure whether the CTF is displayed or actually used for something internally.
  2. How is the range determined or shown?

    • I don’t see any numeric labels or clear indication of the scalar range in the widget.

    • It’s unclear how the widget’s histogram aligns with the image’s data range (e.g. when calling setDataArray(imageData, { min, max })).

  3. Is the widget intended only for opacity editing?

    • The interface seems to focus on Gaussian peaks (opacity control), which makes sense for volume rendering — but I’m not sure whether it’s suitable or adaptable for 2D window/level control.

:light_bulb: What I’d like to ask

  1. Is there any existing widget or recommended approach in VTK.js for window/level or CTF editing in 2D images?

  2. Could the vtkPiecewiseGaussianWidget be adapted to this purpose — e.g., to allow moving markers for min/max window or to manipulate the color transfer function directly?

  3. Is there any documentation or example explaining how the widget’s data range, histogram, and color mapping work internally?

I was expecting that the following hook will automatically adjust at least range of CTF based on user input but it does nothing

    widget.onOpacityChange(() => {
      renderWindow.render();
    });