Support `vtkBitArray` creation in `vtk.util.numpy_support.numpy_to_vtk`
Description
When attempting to create a vtkBitArray
by specifying array_type=vtk.VTK_BIT
, the resulting array is invalid.
Specifically, boolean values in the original NumPy array are not accurately preserved in the VTK array:
import numpy as np
import vtk
narray = np.array([True, False, True])
vtk_array = vtk.util.numpy_support.numpy_to_vtk(narray, array_type=vtk.VTK_BIT)
assert vtk_array.GetValue(0) == 1, "Expected value at index 0 to be 1"
assert vtk_array.GetValue(1) == 0, "Expected value at index 1 to be 0"
assert vtk_array.GetValue(2) == 1, "Expected value at index 2 to be 1"
Traceback (most recent call last):
File "<string>", line 7, in <module>
AssertionError: Expected value at index 0 to be 1
The above assertions currently fail because vtk_array
does not store the correct bit values.
Suggested Approach
A possible solution is to enhance numpy_to_vtk
to properly handle boolean arrays by packing bits.
The snippet below demonstrates a concept for handling VTK_BIT
:
import numpy as np
import vtk
def _numpy_to_vtk(narray, deep=False, array_type=None):
if array_type == vtk.VTK_BIT:
packed_bits = np.packbits(narray)
result_array = vtk.util.numpy_support.create_vtk_array(array_type)
result_array.SetNumberOfComponents(1)
shape = narray.shape
result_array.SetNumberOfTuples(shape[0])
result_array.SetVoidArray(packed_bits, shape[0], 1)
# Since packed_bits is a standalone object with no references from the caller.
# As such, it will drop out of this scope and cause memory issues if we
# do not deep copy its data.
copy = result_array.NewInstance()
copy.DeepCopy(result_array)
result_array = copy
return result_array
return numpy_support.numpy_to_vtk(narray, deep=deep, array_type=array_type)
# Test the modified function
vtk_array_2 = _numpy_to_vtk(narray, array_type=vtk.VTK_BIT)
assert vtk_array_2.GetValue(0) == 1, "Expected value at index 0 to be 1"
assert vtk_array_2.GetValue(1) == 0, "Expected value at index 1 to be 0"
assert vtk_array_2.GetValue(2) == 1, "Expected value at index 2 to be 1"
Additional Context
- By using
np.packbits
, the boolean array is converted into a bit-packed representation suitable forvtkBitArray
. - A deep copy is required to avoid memory reference issues once
packed_bits
goes out of scope. - Integrating similar logic into
numpy_to_vtk
would allow easy creation ofvtkBitArray
from boolean NumPy arrays.
Edited by Jean-Christophe Fillion-Robin