vtkCalculator on a Volume

I’m new to vtk.js but making progress. I ultimately want to compare two volumes and I’ve found vtkCalculator and it’s example as a useful starting place for Planes but having trouble extending it to a Volume. I think it should work but I get “Uncaught TypeError TypeError: x.getPoints is not a function”. I’m reading VTI data and rendering volumes just fine but trying to use the following isn’t working. Maybe you can point in the direction of an appropriate example, or maybe vtkCalculator isn’t the way to go for what I’m ultimately attempting to do.

const reader = vtkXMLImageDataReader.newInstance({ fetchGzip: true });

const simpleFilter = vtkCalculator.newInstance();

simpleFilter.setFormula({

getArrays: (inputDataSets) => ({

  input: [{ location: FieldDataTypes.CELL }], // Require point coordinates as input

  output: [

    // Generate two output arrays:

    {

      location: FieldDataTypes.POINT, // This array will be point-data ...

      name: 'orientation', // ... with the given name ...

      dataType: 'Float32Array', // ... of this type ...

      numberOfComponents: 3, // ... with this many components ...

    },

    {

      location: FieldDataTypes.POINT, // This array will be field data ...

      name: 'match', // ... with the given name ...

      dataType: 'Float32Array', // ... of this type ...

      attribute: AttributeTypes.SCALARS, // ... and will be marked as the default scalars.

      numberOfComponents: 1, // ... with this many components ...

    },

  ],

}),

evaluate: (arraysIn, arraysOut) => {

  // Convert in the input arrays of vtkDataArrays into variables

  // referencing the underlying JavaScript typed-data arrays:

  const [coords] = arraysIn.map((d) => d.getData());

  const [orient, match] = arraysOut.map((d) => d.getData());

  // Since we are passed coords as a 3-component array,

  // loop over all the points and compute the point-data output:

  for (let i = 0, sz = coords.length / 3; i < sz; ++i) {

    orient[i * 3] =

      (coords[3 * i] - 0.5) * (coords[3 * i] - 0.5) +

      (coords[3 * i + 1] - 0.5) * (coords[3 * i + 1] - 0.5);

    orient[i * 3 + 1] =

      (coords[3 * i] - 0.5) * (coords[3 * i] - 0.5) +

      (coords[3 * i + 1] - 0.5) * (coords[3 * i + 1] - 0.5);

    orient[i * 3 + 2] = 1.0;

    match[i] = coords[3 * i + 1];

 

  }

  // Mark the output vtkDataArray as modified

  arraysOut.forEach((x) => x.modified());

},

});
simpleFilter.setInputConnection(reader.getOutputPort());

Not entirely sure, but I think your input location should be points, since imagedata is stored as points.

Getting back to this and it looks like this falls into issue #2257 - can’t get points from imagedata. There doesn’t seem to be much activity which leads me to believe I’m going down the wrong path trying to do math on two different volumes? Maybe someone can point me to an appropriate example?

It looks like vtkCalculator expects explicit points, where as vtkImageData provides implicit points (since it’s a regularly spaced grid). Hence, there is no getPoints() on an image data.

If you want to still use the vtkCalculator, you may have success generating a polydata with points on the image data implicit grid, and then doing calculations that way. Otherwise, you will have to use your own loop for computing coord and populating your orient and match arrays, while setting those on the imagedata object.

I will have to check to see if vtkCalculator should work with vtkImageData. In the meantime, the two alternatives above should be something to try.

Thanks for your quick response. I will give those suggestions a try and report back.