From 437ec50f88fd3c57e7e0f91daca6b914efecf127 Mon Sep 17 00:00:00 2001
From: Jean Fechter <jean.fechter@kitware.com>
Date: Thu, 13 Feb 2025 15:03:05 +0100
Subject: [PATCH] Add python support for vtkBitArray

---
 Common/Core/Testing/Python/TestNumpySupport.py | 18 ++++++++++--------
 .../release/dev/bit-array-numpy-support.md     |  4 ++++
 .../Python/vtkmodules/util/numpy_support.py    | 10 +++++-----
 3 files changed, 19 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/release/dev/bit-array-numpy-support.md

diff --git a/Common/Core/Testing/Python/TestNumpySupport.py b/Common/Core/Testing/Python/TestNumpySupport.py
index ede24fde9b5..de7e81cc0ad 100644
--- a/Common/Core/Testing/Python/TestNumpySupport.py
+++ b/Common/Core/Testing/Python/TestNumpySupport.py
@@ -83,6 +83,16 @@ class TestNumpySupport(Testing.vtkTest):
                 self.assertEqual(len(z1.shape), 1)
             self.assertEqual(sum(numpy.ravel(z) - numpy.ravel(z1)), 0)
 
+        vtk_arr = vtkBitArray()
+        bits = [0, 1, 0, 1, 1, 1, 0, 0, 1, 0]
+        for bit in bits:
+            vtk_arr.InsertNextValue(bit)
+
+        res = vtk_to_numpy(vtk_arr)
+        self._check_arrays(res, vtk_arr)
+        vtk_arr = numpy_to_vtk(res)
+        self._check_arrays(res, vtk_arr)
+
     def testNumpyView(self):
         "Test if the numpy and VTK array share the same data."
         # ----------------------------------------
@@ -105,14 +115,6 @@ class TestNumpySupport(Testing.vtkTest):
         a[0] = [10.0, 20.0, 30.0]
         self.assertEqual(vtk_arr.GetTuple3(0), (1., 2., 3.))
 
-    def testExceptions(self):
-        "Test if the right assertion errors are raised."
-        # Test if bit arrays raise an exception.
-        vtk_arr = vtkBitArray()
-        vtk_arr.InsertNextValue(0)
-        vtk_arr.InsertNextValue(1)
-        self.assertRaises(AssertionError, vtk_to_numpy, vtk_arr)
-
     def testNonContiguousArray(self):
         "Test if the non contiguous array are supported"
         a = numpy.array(range(1, 19), 'd')
diff --git a/Documentation/release/dev/bit-array-numpy-support.md b/Documentation/release/dev/bit-array-numpy-support.md
new file mode 100644
index 00000000000..7ff4d9408a7
--- /dev/null
+++ b/Documentation/release/dev/bit-array-numpy-support.md
@@ -0,0 +1,4 @@
+## Add `vtkBitArray` support to `numpy_support`
+
+Array conversion between vtk and numpy (using `vtk_to_numpy`) now supports `vtkBitArray`.
+Converting a `vtkBitArray` to numpy results in an array of uint8.
diff --git a/Wrapping/Python/vtkmodules/util/numpy_support.py b/Wrapping/Python/vtkmodules/util/numpy_support.py
index 1ecfacc554a..118ab215193 100644
--- a/Wrapping/Python/vtkmodules/util/numpy_support.py
+++ b/Wrapping/Python/vtkmodules/util/numpy_support.py
@@ -71,7 +71,7 @@ def get_vtk_array_type(numpy_array_type):
 
 def get_vtk_to_numpy_typemap():
     """Returns the VTK array type to numpy array type mapping."""
-    _vtk_np = {vtkConstants.VTK_BIT:numpy.uint8, # conversion not implemented
+    _vtk_np = {vtkConstants.VTK_BIT:numpy.uint8,
                 vtkConstants.VTK_CHAR:numpy.int8,
                 vtkConstants.VTK_SIGNED_CHAR:numpy.int8,
                 vtkConstants.VTK_UNSIGNED_CHAR:numpy.uint8,
@@ -204,8 +204,6 @@ def vtk_to_numpy(vtk_array):
     appropriate numpy array containing the same data -- it actually
     points to the same data.
 
-    WARNING: This does not work for bit arrays.
-
     Parameters
 
     vtk_array
@@ -215,7 +213,6 @@ def vtk_to_numpy(vtk_array):
     typ = vtk_array.GetDataType()
     assert typ in get_vtk_to_numpy_typemap().keys(), \
            "Unsupported array type %s"%typ
-    assert typ != vtkConstants.VTK_BIT, 'Bit arrays are not supported.'
 
     shape = vtk_array.GetNumberOfTuples(), \
             vtk_array.GetNumberOfComponents()
@@ -223,7 +220,10 @@ def vtk_to_numpy(vtk_array):
     # Get the data via the buffer interface
     dtype = get_numpy_array_type(typ)
     try:
-        result = numpy.frombuffer(vtk_array, dtype=dtype)
+        if typ != vtkConstants.VTK_BIT:
+            result = numpy.frombuffer(vtk_array, dtype=dtype)
+        else:
+            result = numpy.unpackbits(vtk_array, count=shape[0])
     except ValueError:
         # http://mail.scipy.org/pipermail/numpy-tickets/2011-August/005859.html
         # numpy 1.5.1 (and maybe earlier) has a bug where if frombuffer is
-- 
GitLab