# volume not rendering using react

**URL:** https://discourse.vtk.org/t/volume-not-rendering-using-react/10291
**Category:** Web
**Created:** [December 21, 2022, 9:17pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291 "2022-12-21T21:17:19Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![jilei-hao](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jilei-hao/32/5581_2.png) [@jilei-hao](https://discourse.vtk.org/u/jilei-hao)
#### Post date: [December 21, 2022, 9:17pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/1 "2022-12-21T21:17:19Z")

</div>

I’m trying to combine the time series example with volume rendering in react. But following code renders nothing on the screen.

The code downloads one frame of volume, and uses the vtkImageData-vtkVolumeMapper-vtkVolume combo for the rendering. The result is an empty render window with background and control panel.

When troubleshooting, I can see the data is loaded to the mapper (with correct bounds). But resizing window gave me errors like this:

 ![Screen Shot 2022-12-21 at 4.12.33 PM](https://discourse.vtk.org/uploads/default/original/2X/1/1a11a915a78579202cfdaca4b943be67bfc27ef5.png)

Can any vtk-js and react expert spot any issues in my code? Thanks!

```auto

import { useState, useRef, useEffect } from 'react';

// Load the rendering pieces we want to use (for both WebGL and WebGPU)
import '@kitware/vtk.js/Rendering/Profiles/Geometry';

// Force DataAccessHelper to have access to various data source
import vtkHttpDataAccessHelper from '@kitware/vtk.js/IO/Core/DataAccessHelper/HttpDataAccessHelper';
import '@kitware/vtk.js/IO/Core/DataAccessHelper/HtmlDataAccessHelper';
import '@kitware/vtk.js/IO/Core/DataAccessHelper/JSZipDataAccessHelper';

import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
import vtkVolume from '@kitware/vtk.js/Rendering/Core/Volume';
import vtkVolumeMapper from '@kitware/vtk.js/Rendering/Core/VolumeMapper';
import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction';
import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunction';

import vtkHttpDataSetReader from '@kitware/vtk.js/IO/Core/HttpDataSetReader';
import vtkXMLImageDataReader from '@kitware/vtk.js/IO/XML/XMLImageDataReader';
import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';

import styles from '../../app.module.css'

export default function Example() {
  console.log("Render App");
  const vtkContainerRef = useRef(null);
  const context = useRef(null); // vtk related objects
  const hasDownloadingStarted = useRef(false);
  const timeData = useRef([]);
  const [currentTP, setCurrentTP] = useState(1);

  //const BASE_URL = 'http://192.168.50.37:8000'
  const BASE_URL = 'http://10.102.180.67:8000'

  const { fetchBinary } = vtkHttpDataAccessHelper;

  function setVisibleDataset(ds) {
    console.log("[setVisibleDataset] timeData.length=", timeData.current.length);
    if (context.current) {
      const { renderWindow, mapper, renderer, actor } = context.current;
      mapper.setInputData(ds);
      console.log("-- input data set", ds);

      mapper.setSampleDistance(1.1);
      mapper.setPreferSizeOverAccuracy(true);
      mapper.setBlendModeToComposite();
      mapper.setIpScalarRange(0.0, 1.0);

      const opacityFunction = vtkPiecewiseFunction.newInstance();
      opacityFunction.addPoint(-3024, 0.1);
      opacityFunction.addPoint(-637.62, 0.1);
      opacityFunction.addPoint(700, 0.5);
      opacityFunction.addPoint(3071, 0.9);
      actor.getProperty().setScalarOpacity(0, opacityFunction);

      const colorTransferFunction = vtkColorTransferFunction.newInstance();
      colorTransferFunction.addRGBPoint(0, 0, 0, 0);
      colorTransferFunction.addRGBPoint(1, 1, 1, 1);
      actor.getProperty().setRGBTransferFunction(0, colorTransferFunction);

      actor.getProperty().setScalarOpacityUnitDistance(0, 3.0);
      actor.getProperty().setInterpolationTypeToLinear();
      actor.getProperty().setShade(true);
      actor.getProperty().setAmbient(0.1);
      actor.getProperty().setDiffuse(0.9);
      actor.getProperty().setSpecular(0.2);
      actor.getProperty().setSpecularPower(10.0);

      renderer.resetCamera();
      renderer.getActiveCamera().elevation(-70);
      renderWindow.render();
    }
  }

  function downloadData() {
    console.log("[downloadData] started");
    const files = [
      'dist/img3d_bavcta008_baseline_00.vti'
    ];
    return Promise.all(
      files.map((fn) => 
        fetchBinary(`${BASE_URL}/${fn}`).then((binary) => {
          const reader = vtkXMLImageDataReader.newInstance();
          reader.parseAsArrayBuffer(binary);
          return reader.getOutputData(0);
        })
      )
    )
  };

  function downloadSample() {
    console.log("[downloadSample] started");
    const files = [
      'sample/headsq.vti'
    ];
    const httpReader = vtkHttpDataSetReader.newInstance({ fetchGzip: true });
    return Promise.all(
      files.map((fn) => 
        httpReader.setUrl(`${BASE_URL}/${fn}`).then(() => {
          return httpReader.getOutputData(0);
        })
      )
    );
  }

  /* Initialize renderWindow, renderer, mapper and actor */
  useEffect(() => {
    if (!context.current) {
      const fullScreenRenderWindow = vtkFullScreenRenderWindow.newInstance({
        rootContainer: vtkContainerRef.current, // html element containing this window
        background: [0.1, 0.1, 0.1],
      });

      const mapper = vtkVolumeMapper.newInstance();
      mapper.setInputData(vtkImageData.newInstance());

      const renderWindow = fullScreenRenderWindow.getRenderWindow();
      const renderer = fullScreenRenderWindow.getRenderer();
      const interactor = renderWindow.getInteractor();
      interactor.setDesiredUpdateRate(15.0);

      const actor = vtkVolume.newInstance();
      actor.setMapper(mapper);
      renderer.addVolume(actor);

      if (!hasDownloadingStarted.current) {
        hasDownloadingStarted.current = true;
        downloadSample().then((downloadedData) => {
          console.log("Data Downloaded: ", downloadedData);
          timeData.current = downloadedData;
          setVisibleDataset(timeData.current[currentTP - 1]);
        });
      }
      
      context.current = {
        fullScreenRenderWindow,
        renderWindow,
        renderer,
        actor,
        mapper
      };

      window.vtkContext = context.current;
    }

    return () => {
      if (context.current) {
        const { 
          fullScreenRenderWindow, actor, mapper, renderer
        } = context.current;

        actor.delete();
        mapper.delete();
        renderer.delete();
        fullScreenRenderWindow.delete();
        context.current = null;
      }
    };
  }, [vtkContainerRef]);

  function onRenderClicked() {
    if (context.current) {
      console.log("[onRenderClicked] timeData: ", timeData);
      const {renderWindow } = context.current;
      setVisibleDataset(timeData.current[currentTP - 1]);
      renderWindow.render();
    }
  }

  return (
    <div>
      <div ref={vtkContainerRef} />
      <div className={styles.control_panel}>
        <button onClick={onRenderClicked}>
          Manual Render
        </button>
      </div>
    </div>
  );
}

```

---

<div class="post-metadata">

### Author: ![jilei-hao](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jilei-hao/32/5581_2.png) [@jilei-hao](https://discourse.vtk.org/u/jilei-hao)
#### Post date: [December 21, 2022, 9:47pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/2 "2022-12-21T21:47:55Z")

</div>

More information:

“dependencies”: {  
“@kitware/vtk.js”: “^25.13.1”,  
“localforage”: “^1.10.0”,  
“match-sorter”: “^6.3.1”,  
“react”: “^18.2.0”,  
“react-dom”: “^18.2.0”,  
“react-router-dom”: “^6.4.3”,  
“sort-by”: “^1.2.0”  
},

The render window can render a simple cone without problem using vtkConeSource-vtkMapper-vtkActor combo. Issue only occurs when trying to render volume.

---

<div class="post-metadata">

### Author: ![jilei-hao](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jilei-hao/32/5581_2.png) [@jilei-hao](https://discourse.vtk.org/u/jilei-hao)
#### Post date: [December 21, 2022, 10:23pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/3 "2022-12-21T22:23:54Z")

</div>

I just realized that I probably should have imported `Volume` rendering profile instead of `Geometry`.

So changed  
`import '@kitware/vtk.js/Rendering/Profiles/Geometry';`  
to  
`import '@kitware/vtk.js/Rendering/Profiles/Volume';`

And after the change, now I’m getting this error:

 ![image](https://discourse.vtk.org/uploads/default/original/2X/a/ac779e05d61434cd265b3816e27af3f91cf2d206.png)

---

<div class="post-metadata">

### Author: ![jilei-hao](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jilei-hao/32/5581_2.png) [@jilei-hao](https://discourse.vtk.org/u/jilei-hao)
#### Post date: [December 22, 2022, 4:32pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/4 "2022-12-22T16:32:09Z")

</div>

I kind of solved it by changing the data reading method.

In the code sample I was reading data into an array of `vtkImageData` and set the image to mapper when a time frame became “active”.

I changed it to reading binaries using `fetchBinary` from `vtkHttpDataAccessHelper`, and store them into an array. When a time frame become “active”, I set the corresponding binary using `parseAsArrayBuffer` to a reader connected with mapper. Then the it started to render.

And I suspect parsing binary every time when a frame becomes active might bring extra performance cost. So I might need to have an array of readers instead. Any idea why the mapper’s `setInputData` is not working in this case?

---

<div class="post-metadata">

### Author: ![Forrest](https://discourse.vtk.org/user_avatar/discourse.vtk.org/forrest/32/300_2.png) [@Forrest](https://discourse.vtk.org/u/Forrest)
#### Post date: [January 3, 2023, 5:08pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/5 "2023-01-03T17:08:16Z")

</div>

Have you verified that you are passing in vtkImageData into `mapper.setInputData`?

---

<div class="post-metadata">

### Author: ![jilei-hao](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jilei-hao/32/5581_2.png) [@jilei-hao](https://discourse.vtk.org/u/jilei-hao)
#### Post date: [January 3, 2023, 6:29pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/6 "2023-01-03T18:29:53Z")

</div>

Yes, I checked the data in console just before passing it to the mapper. It’s a vtkImageData with correct dimension, spacing and data.

---

<div class="post-metadata">

### Author: ![Forrest](https://discourse.vtk.org/user_avatar/discourse.vtk.org/forrest/32/300_2.png) [@Forrest](https://discourse.vtk.org/u/Forrest)
#### Post date: [January 9, 2023, 8:15pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/7 "2023-01-09T20:15:25Z")

</div>

Oh, it’s your usage of `mapper.setInputData(vtkImageData.newInstance())`. A new instance of vtkImageData has no pixel storage allocated for it. You’re better off deferring adding your actor to the scene until your data is available.

---

<div class="post-metadata">

### Author: ![jilei-hao](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jilei-hao/32/5581_2.png) [@jilei-hao](https://discourse.vtk.org/u/jilei-hao)
#### Post date: [January 12, 2023, 7:24pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/8 "2023-01-12T19:24:07Z")

</div>

Thanks for the reply! The newInstance was a placeholder indeed, but are setting new image to the mapper expected to overwrite the existing data? Or should I call a function like `update()` to refresh the rendering pipeline?

I did check using console using mapper.getInputData() and the data looks correctly replaced, but was still not rendered.

---

<div class="post-metadata">

### Author: ![Kalsyc](https://discourse.vtk.org/user_avatar/discourse.vtk.org/kalsyc/32/5715_2.png) [@Kalsyc](https://discourse.vtk.org/u/Kalsyc)
#### Post date: [January 13, 2023, 9:01am UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/9 "2023-01-13T09:01:59Z")

</div>

Hmm… it seems like you didn’t set it properly. Here’s a simplified version of how I did it for a simple volume. Also, I created my own custom proxy class to help me with this and you should look into it if you can.

```
//Load your data first, then pass it as an ArrayBuffer and setup the pipeline
function setupPipeline(content: ArrayBuffer) {
    const reader = vtkXMLImageDataReader.newInstance();
    const piecewiseFunction = vtkPiecewiseFunction.newInstance();
    const colorTransferFunction = vtkColorTransferFunction.newInstance();
    const volumeMapper = vtkVolumeMapper.newInstance();
    const volume = vtkVolume.newInstance();
    const cropFilter = vtkImageCropFilter.newInstance();

    reader.parseAsArrayBuffer(content);
    cropFilter.setInputConnection(this.reader.getOutputPort());
    volumeMapper.setInputConnection(this.cropFilter.getOutputPort());
    volume.setMapper(this.volumeMapper);

    const dataArray: vtkDataArray = this.reader.getOutputData().getPointData().getScalars();

    colorTransferFunction.applyColorMap(vtkColorMaps.getPresetByName('jet'));
    colorTransferFunction.setMappingRange(...dataArray.getRange());
    colorTransferFunction.updateRange();
    volume.getProperty().setRGBTransferFunction(0, this.colorTransferFunction);
    volume.getProperty().setScalarOpacity(0, this.piecewiseFunction);

    return ({ reader, piecewiseFunction, colorTransferFunction, volumeMapper, volume, cropFilter});
}

    // In your onMount useEffect (with [] empty array as dependency), 
    // Instantiate your renderer, renderwindow, interactor and setContainer onto a HTMLDivElement with useRef 

//Run this function to manually render
function main() {
    const data = load(file); //Load file here
    // You may store the below objects you have created in some state so you can access them later
    const { reader, piecewiseFunction, colorTransferFunction, volumeMapper, volume, cropFilter } = setupPipeline(data);
    renderer.addVolume(volume);
    renderer.resetCamera();
    renderWindow.render();
}

```

---

<div class="post-metadata">

### Author: ![jilei-hao](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jilei-hao/32/5581_2.png) [@jilei-hao](https://discourse.vtk.org/u/jilei-hao)
#### Post date: [January 13, 2023, 3:25pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/10 "2023-01-13T15:25:18Z")

</div>

Hi @Kalsyc , Thanks so much for the reply and sharing your code! And connecting reader’s `OutputPort` to mapper’s `InputConnection` worked in my case.

But if we want to render a time series of volumes, and want to change them frequently, like every 50 ms, is it possible for us to keep only one rendering pipeline and only change data to the pipeline for memory saving purpose. Currently I have 20 time points in my series. To make it work, I have 20 rendering pipelines setup and enable/disable visibility to create a “4d playing” feature. Is there any more efficient way to do this?

Thanks!

---

<div class="post-metadata">

### Author: ![jilei-hao](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jilei-hao/32/5581_2.png) [@jilei-hao](https://discourse.vtk.org/u/jilei-hao)
#### Post date: [January 13, 2023, 3:37pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/11 "2023-01-13T15:37:44Z")

</div>

So this will go back to my original question. In this vanilla js time series example: [vtk.js](https://kitware.github.io/vtk-js/examples/TimeSeries.html) following code seems to work

```javascript
function setVisibleDataset(ds) {
  mapper.setInputData(ds);
  renderer.resetCamera();
  renderWindow.render();
}

```

But it’s not working for my rewrite in React for volumes.

---

<div class="post-metadata">

### Author: ![JohnSkinner](https://discourse.vtk.org/user_avatar/discourse.vtk.org/johnskinner/32/6197_2.png) [@JohnSkinner](https://discourse.vtk.org/u/JohnSkinner)
#### Post date: [January 13, 2023, 3:51pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/12 "2023-01-13T15:51:14Z")

</div>

Maybe my experience with Angular may be helpful for React.  
In my use of Angular, I sometimes found missing .d.ts for certain classes in vtk.js (macro?)  
As a stop-gap, I would wrap my vtk.js functionality in a javascript class, and add a typescript declaration (a .d.ts file) to gain access to the javascript class/methods from the Angular typescript code.

---

<div class="post-metadata">

### Author: ![Kalsyc](https://discourse.vtk.org/user_avatar/discourse.vtk.org/kalsyc/32/5715_2.png) [@Kalsyc](https://discourse.vtk.org/u/Kalsyc)
#### Post date: [January 17, 2023, 8:23am UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/13 "2023-01-17T08:23:54Z")

</div>

As far as I know, you can use the same reader since I am assuming that all the volumes carry the same dataset (aka they were parsed from the same file). I think having the same mapper could work as well.

---

<div class="post-metadata">

### Author: ![Kalsyc](https://discourse.vtk.org/user_avatar/discourse.vtk.org/kalsyc/32/5715_2.png) [@Kalsyc](https://discourse.vtk.org/u/Kalsyc)
#### Post date: [January 17, 2023, 8:26am UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/14 "2023-01-17T08:26:01Z")

</div>

Could you share more snippets of your code with volumes?

---

<div class="post-metadata">

### Author: ![Forrest](https://discourse.vtk.org/user_avatar/discourse.vtk.org/forrest/32/300_2.png) [@Forrest](https://discourse.vtk.org/u/Forrest)
#### Post date: [January 17, 2023, 2:17pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/15 "2023-01-17T14:17:55Z")

</div>

One other thing you could check: you have a call to `renderer.getActiveCamera().elevation(-70);`. Comment that out and see if the dataset shows up in the view, as `resetCamera()` should bring it into view.

---

<div class="post-metadata">

### Author: ![jilei-hao](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jilei-hao/32/5581_2.png) [@jilei-hao](https://discourse.vtk.org/u/jilei-hao)
#### Post date: [January 20, 2023, 10:54pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/16 "2023-01-20T22:54:25Z")

</div>

It indeed worked. I now can confirm my original problem was caused by adding a `vtkImageData.newInstance()` placeholder to the mapper. My solution is deferring adding image data until real data is loaded. Thanks so much for all the suggestions!

---

<div class="post-metadata">

### Author: ![jilei-hao](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jilei-hao/32/5581_2.png) [@jilei-hao](https://discourse.vtk.org/u/jilei-hao)
#### Post date: [January 20, 2023, 10:57pm UTC](https://discourse.vtk.org/t/volume-not-rendering-using-react/10291/17 "2023-01-20T22:57:24Z")

</div>

I did a recheck of my code again and can confirm setting the placeholder was the cause of my issue. An error occurred before I set new data to the mapper. That’s probably why setting new data was not working. It is now working fine. Thanks so much for the solution!
