How to get full cell types array with new VTK 9.6 API

GetCellTypesArray is recently deprecated. Using the latest python dev wheels:

>>> import vtk
>>> grid = vtk.vtkUnstructuredGrid()
>>> array = grid.GetCellTypesArray()
DeprecationWarning: Call to deprecated method GetCellTypesArray. (Use GetCellTypes() instead) -- Deprecated since version 9.6.0.

As per the warning, let’s try GetCellTypes instead:

>>> cell_types = vtk.vtkCellTypes()
>>> grid.GetCellTypes(cell_types)
DeprecationWarning: Call to deprecated method GetCellTypes. (Use GetDistinctCellTypes(vtkCellTypes* types) instead.) -- Deprecated since version 9.6.0.

As per the warning, this means I should now use GetDistinctCellTypes.
But, this returns an array with unique cell types, rather than an array with all cell types.
Am I missing something? How can I use the new, non-deprecated API to get the original array that was returned by GetCellTypesArray? Or is it no longer possible to do this in VTK 9.6?

@spyridon97 is this related/fixed by https://gitlab.kitware.com/vtk/vtk/-/merge_requests/12549 ?

yes

1 Like

Fix was just merged. Tomorrow’s nightly wheel should have the fix.

A reminder that wheels are weekly generated and sometimes fails to generate :slight_smile:

Mistakes were made :stuck_out_tongue:

Thanks for the quick fix! Just to clarify: GetCellTypesArray is not being deprecated?

It is. In place of vtkDataArray* GetCellTypes().

Ah ok, so GetCellTypesArray is deprecated, but GetCellTypes is not.Thanks!

  /**
   * Get a list of types of cells in a dataset. The list consists of an array
   * of types (not necessarily in any order), with a single entry per type.
   * For example a dataset with 5 triangles, 3 lines, and 100 hexahedra would
   * result in a list of three entries, corresponding to the types VTK_TRIANGLE,
   * VTK_LINE, and VTK_HEXAHEDRON. This override implements an optimization that
   * recomputes cell types only when the types of cells may have changed.
   *
   * THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND
   * THE DATASET IS NOT MODIFIED
   */
  void GetDistinctCellTypes(vtkCellTypes* types) override;
  VTK_DEPRECATED_IN_9_6_0("Use GetDistinctCellTypes(vtkCellTypes* types) instead.")
  void GetCellTypes(vtkCellTypes* types) override { this->GetDistinctCellTypes(types); }
  ///@}

  /**
   * Get a list of types of cells in a dataset. The list consists of an array
   * of types (not necessarily in any order), with a single entry per type.
   * For example a dataset with 5 triangles, 3 lines, and 100 hexahedra would
   * result in a list of three entries, corresponding to the types VTK_TRIANGLE,
   * VTK_LINE, and VTK_HEXAHEDRON. This override implements an optimization that
   * recomputes cell types only when the types of cells may have changed.
   * This method never returns `nullptr`.
   *
   * THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND
   * THE DATASET IS NOT MODIFIED
   */
  vtkUnsignedCharArray* GetDistinctCellTypesArray();

  ///@{
  /**
   * Get the array of all cell types in the grid. Each single-component
   * tuple in the array at an index that corresponds to the type of the cell
   * with the same index. To get an array of only the distinct cell types in
   * the dataset, use GetDistinctCellTypes().
   */
  vtkDataArray* GetCellTypes() { return this->Types; }
  VTK_DEPRECATED_IN_9_6_0("Use GetCellTypes() instead")
  vtkUnsignedCharArray* GetCellTypesArray();
  ///@}
...

Got it, I think I understand now. Not used to working with C overloads. So GetCellTypes is deprecated, but only for the version where the getter mutates the input and returns nothing. We should use GetCellTypes with no args instead, which returns the cell types directly. And I think. the bug is that this version of GetCellTypes was missing, but has been fixed/added?

I’m just thinking out loud, no need reply to this or add to it. I’ll wait for the new dev wheels and let you know if I’m still having issues with the new API. Thanks again!

You got that right!

You explain in the docs why vtkDataArray is used for GetCellTypes(), but I’m still not sure how well this will work for C++ users.

Documentation/release/dev/vtkDataSet-GetCellTypes-updates.md

vtkUnstructuredGrid’s method vtkUnsignedCharArray* GetCellTypesArray() has been deprecated in favor of vtkDataArray* GetCellTypes(), which can be used to get the correct type as follows:

auto cellTypes = vtkConstantUnsignedCharArray::FastDownCast(input->GetCellTypes())
auto cellTypes = vtkUnsignedCharArray::FastDownCast(input->GetCellTypes())

This was done to enable storing the cell types of meshes with only 1 cell type as vtkConstantUnsignedCharArray instead of vtkUnsignedCharArray, which saves memory.

All the user knows about CellTypes is that it is a vtkDataArray, there seems to be no guarantee that it is either vtkConstantUnsignedCharArray or vtkUnsignedCharArray. So are you suggesting that users try various downcasts an then eventually fall back on the vtkDataArray interface? I’m imagining code like the following, which seems fairly tedious:

void myfunc(vtkUnstructedGrid* input)
{
  auto* cellTypes1 = vtkConstantUnsignedCharArray::FastDownCast(input->GetCellTypes());
  if (cellTypes1 != nullptr)
  {
    // code for when the cell type array is vtkConstantUnsignedCharArray
    return;
  }
  auto* cellTypes2 = vtkUnsignedCharArray::FastDownCast(input->GetCellTypes());
  if (cellTypes2 != nullptr)
  {
    // code for when the cell type array is vtkUnsignedCharArray
    return;
  }
  auto* cellTypes = input->GetCellTypes();
  // code for when we're not sure of the array type
  return;
}

Am I misunderstanding how the downcasts will actually be used?

There are several solutions

  1. Use vtkDataArray::GetComponent(id, 0);
  2. Use vtkDataArray::GetTuple1(id);
  3. Use auto range = vtk::DataArrayValueRange<1. unsigned char>(cellTypes); and auto cellType = range[id];
  4. Dispatch with vtkUnstructuredGrid::CellTypesArrays and use auto range = vtk::DataArrayValueRange<1>(cellTypes); and auto cellType = range[id];

The most efficient is 4, then 1 and 3 are next (equal), and then 2.

Is there a solution #5 that uses FastDownCast? You mention FastDownCast very prominently in the release note.

I mean sure you can use

1. `auto cellTypes = vtkConstantUnsignedCharArray::FastDownCast(input->GetCellTypes())`
2. `auto cellTypes = vtkUnsignedCharArray::FastDownCast(input->GetCellTypes())`

if you already know what it is, but i would not suggest it when you only need to access 1-2 cell type values. I would only suggest it when iterating all cell types.

vtkDataArray::GetVariantValue also works and is very usefull if you know the type of the data but not the type of the array.