Skip to content

Commit bfe0e80

Browse files
tbirdsothewtex
authored andcommitted
BUG: Use NumPy dtypes for type mapping
Updates Python wrappings and extras to primarily use `np.dtype` objects for mapping from NumPy to ITK types. Follows discussion in SimpleITK/SimpleITK#1685 and addresses #3544 .
1 parent d1867dd commit bfe0e80

File tree

5 files changed

+57
-51
lines changed

5 files changed

+57
-51
lines changed

Modules/Bridge/NumPy/wrapping/PyBuffer.i.init

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,29 @@ else:
2929
loads = dask_deserialize.dispatch(np.ndarray)
3030
return NDArrayITKBase(loads(header, frames))
3131

32-
def _get_numpy_pixelid(itk_Image_type):
32+
def _get_numpy_pixelid(itk_Image_type) -> np.dtype:
3333
"""Returns a ITK PixelID given a numpy array."""
3434

3535
# This is a Mapping from numpy array types to itk pixel types.
36-
_np_itk = {"UC":np.uint8,
37-
"US":np.uint16,
38-
"UI":np.uint32,
39-
"UL":np.uint64,
40-
"ULL":np.uint64,
41-
"SC":np.int8,
42-
"SS":np.int16,
43-
"SI":np.int32,
44-
"SL":np.int64,
45-
"SLL":np.int64,
46-
"F":np.float32,
47-
"D":np.float64,
48-
"PF2":np.float32,
49-
"PF3":np.float32,
36+
_np_itk = {"UC":np.dtype(np.uint8),
37+
"US":np.dtype(np.uint16),
38+
"UI":np.dtype(np.uint32),
39+
"UL":np.dtype(np.uint64),
40+
"ULL":np.dtype(np.uint64),
41+
"SC":np.dtype(np.int8),
42+
"SS":np.dtype(np.int16),
43+
"SI":np.dtype(np.int32),
44+
"SL":np.dtype(np.int64),
45+
"SLL":np.dtype(np.int64),
46+
"F":np.dtype(np.float32),
47+
"D":np.dtype(np.float64),
48+
"PF2":np.dtype(np.float32),
49+
"PF3":np.dtype(np.float32),
5050
}
5151
import os
5252
if os.name == 'nt':
53-
_np_itk['UL'] = np.uint32
54-
_np_itk['SL'] = np.int32
53+
_np_itk['UL'] = np.dtype(np.uint32)
54+
_np_itk['SL'] = np.dtype(np.int32)
5555
try:
5656
return _np_itk[itk_Image_type]
5757
except KeyError as e:

Wrapping/Generators/Python/PyBase/pyBase.i

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,13 @@ str = str
566566
import numpy as np
567567
from itk.support import types
568568
569-
# if both a numpy dtype and a ctype exist, use the latter.
569+
# Convert numpy type to dtype object for consistency
570+
# i.e. <np.float32> -> np.dtype('float32')
570571
if type(pixel_type) is type:
572+
pixel_type = np.dtype(pixel_type)
573+
574+
# if both a numpy dtype and an ITK ctype exist, use the latter.
575+
if issubclass(type(pixel_type), np.dtype):
571576
c_pixel_type = types.itkCType.GetCTypeForDType(pixel_type)
572577
if c_pixel_type is not None:
573578
pixel_type = c_pixel_type

Wrapping/Generators/Python/Tests/extras.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,10 @@ def custom_callback(name, progress):
389389

390390
# BridgeNumPy
391391

392+
arr = np.zeros([3,4,5],dtype=np.dtype('uintc'))
393+
image = itk.image_from_array(arr)
394+
assert itk.template(image)[1] == (itk.UI, 3)
395+
392396
# Images
393397

394398
image = itk.imread(filename)

Wrapping/Generators/Python/itk/support/extras.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -273,26 +273,23 @@ def _long_type():
273273

274274
# This is a Mapping from numpy array types to itk pixel types.
275275
_np_itk = {
276-
np.uint8: itk.UC,
277-
np.uint16: itk.US,
278-
np.uint32: itk.UI,
279-
np.uint64: _long_type(),
280-
np.int8: itk.SC,
281-
np.int16: itk.SS,
282-
np.int32: itk.SI,
283-
np.int64: itk.SL,
284-
np.float32: itk.F,
285-
np.float64: itk.D,
286-
np.complex64: itk.complex[itk.F],
287-
np.complex128: itk.complex[itk.D],
276+
np.dtype(np.uint8): itk.UC,
277+
np.dtype(np.uint16): itk.US,
278+
np.dtype(np.uint32): itk.UI,
279+
np.dtype(np.uint64): _long_type(),
280+
np.dtype(np.int8): itk.SC,
281+
np.dtype(np.int16): itk.SS,
282+
np.dtype(np.int32): itk.SI,
283+
np.dtype(np.int64): itk.SL,
284+
np.dtype(np.float32): itk.F,
285+
np.dtype(np.float64): itk.D,
286+
np.dtype(np.complex64): itk.complex[itk.F],
287+
np.dtype(np.complex128): itk.complex[itk.D],
288288
}
289289
try:
290-
return _np_itk[numpy_array_type.dtype.type]
290+
return _np_itk[numpy_array_type.dtype]
291291
except KeyError as e:
292-
for key in _np_itk:
293-
if np.issubdtype(numpy_array_type.dtype.type, key):
294-
return _np_itk[key]
295-
raise e
292+
raise e
296293

297294

298295
def _GetArrayFromImage(

Wrapping/Generators/Python/itk/support/types.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -119,28 +119,28 @@ def initialize_c_types_once() -> (
119119
"""
120120
import numpy as np
121121

122-
_F: "itkCType" = itkCType("float", "F", np.float32)
123-
_D: "itkCType" = itkCType("double", "D", np.float64)
124-
_UC: "itkCType" = itkCType("unsigned char", "UC", np.uint8)
125-
_US: "itkCType" = itkCType("unsigned short", "US", np.uint16)
126-
_UI: "itkCType" = itkCType("unsigned int", "UI", np.uint32)
122+
_F: "itkCType" = itkCType("float", "F", np.dtype(np.float32))
123+
_D: "itkCType" = itkCType("double", "D", np.dtype(np.float64))
124+
_UC: "itkCType" = itkCType("unsigned char", "UC", np.dtype(np.uint8))
125+
_US: "itkCType" = itkCType("unsigned short", "US", np.dtype(np.uint16))
126+
_UI: "itkCType" = itkCType("unsigned int", "UI", np.dtype(np.uint32))
127127
if os.name == "nt":
128-
_UL: "itkCType" = itkCType("unsigned long", "UL", np.uint32)
129-
_SL: "itkCType" = itkCType("signed long", "SL", np.int32)
128+
_UL: "itkCType" = itkCType("unsigned long", "UL", np.dtype(np.uint32))
129+
_SL: "itkCType" = itkCType("signed long", "SL", np.dtype(np.int32))
130130
_LD: "itkCType" = itkCType("long double", "LD")
131131
else:
132-
_UL: "itkCType" = itkCType("unsigned long", "UL", np.uint64)
133-
_SL: "itkCType" = itkCType("signed long", "SL", np.int64)
132+
_UL: "itkCType" = itkCType("unsigned long", "UL", np.dtype(np.uint64))
133+
_SL: "itkCType" = itkCType("signed long", "SL", np.dtype(np.int64))
134134
if hasattr(np, "float128"):
135-
_LD: "itkCType" = itkCType("long double", "LD", np.float128)
135+
_LD: "itkCType" = itkCType("long double", "LD", np.dtype(np.float128))
136136
else:
137137
_LD: "itkCType" = itkCType("long double", "LD")
138-
_ULL: "itkCType" = itkCType("unsigned long long", "ULL", np.uint64)
139-
_SC: "itkCType" = itkCType("signed char", "SC", np.int8)
140-
_SS: "itkCType" = itkCType("signed short", "SS", np.int16)
141-
_SI: "itkCType" = itkCType("signed int", "SI", np.int32)
142-
_SLL: "itkCType" = itkCType("signed long long", "SLL", np.int64)
143-
_B: "itkCType" = itkCType("bool", "B", np.bool_)
138+
_ULL: "itkCType" = itkCType("unsigned long long", "ULL", np.dtype(np.uint64))
139+
_SC: "itkCType" = itkCType("signed char", "SC", np.dtype(np.int8))
140+
_SS: "itkCType" = itkCType("signed short", "SS", np.dtype(np.int16))
141+
_SI: "itkCType" = itkCType("signed int", "SI", np.dtype(np.int32))
142+
_SLL: "itkCType" = itkCType("signed long long", "SLL", np.dtype(np.int64))
143+
_B: "itkCType" = itkCType("bool", "B", np.dtype(np.bool8))
144144
return _F, _D, _UC, _US, _UI, _UL, _SL, _LD, _ULL, _SC, _SS, _SI, _SLL, _B
145145

146146

0 commit comments

Comments
 (0)