Skip to content

Commit b4c9b6c

Browse files
committed
BF - add dtypes to recoder to deal with odd dtype hashing
1 parent 2cb68f7 commit b4c9b6c

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

nibabel/tests/test_utils.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
from ..tmpdirs import InTemporaryDirectory
1717

1818
from ..volumeutils import (array_from_file,
19-
array_to_file,
20-
calculate_scale,
21-
scale_min_max,
22-
can_cast, allopen,
23-
shape_zoom_affine,
24-
rec2dict)
19+
array_to_file,
20+
calculate_scale,
21+
scale_min_max,
22+
can_cast, allopen,
23+
make_dt_codes,
24+
native_code,
25+
shape_zoom_affine,
26+
rec2dict)
2527

2628
from numpy.testing import (assert_array_almost_equal,
2729
assert_array_equal)
@@ -288,3 +290,25 @@ def test_rec2dict():
288290
r = np.zeros((), dtype = [('x', 'i4'), ('s', 'S10')])
289291
d = rec2dict(r)
290292
yield assert_equal(d, {'x': 0, 's': ''})
293+
294+
295+
def test_dtypes():
296+
# numpy - at least up to 1.5.1 - has odd behavior for hashing -
297+
# specifically:
298+
# In [9]: hash(dtype('<f4')) == hash(dtype('<f4').newbyteorder('<'))
299+
# Out[9]: False
300+
# In [10]: dtype('<f4') == dtype('<f4').newbyteorder('<')
301+
# Out[10]: True
302+
# where '<' is the native byte order
303+
dt_defs = ((16, 'float32', np.float32),)
304+
dtr = make_dt_codes(dt_defs)
305+
# These of course should pass regardless of dtype
306+
assert_equal(dtr[np.float32], 16)
307+
assert_equal(dtr['float32'], 16)
308+
# These also pass despite dtype issue
309+
assert_equal(dtr[np.dtype(np.float32)], 16)
310+
assert_equal(dtr[np.dtype('f4')], 16)
311+
assert_equal(dtr[np.dtype('f4').newbyteorder('S')], 16)
312+
# But this one used to fail
313+
assert_equal(dtr[np.dtype('f4').newbyteorder(native_code)], 16)
314+

nibabel/volumeutils.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,11 +263,21 @@ def make_dt_codes(codes):
263263
'''
264264
dt_codes = []
265265
for code, name, np_type in codes:
266-
dt_codes.append((code, name, np_type,
267-
np.dtype(np_type),
268-
np.dtype(np_type).newbyteorder('S')))
266+
this_dt = np.dtype(np_type)
267+
# To satisfy an oddness in numpy dtype hashing, we need to add the dtype
268+
# with native order as well as the default dtype (=) order
269+
dt_codes.append((code, name,
270+
np_type,
271+
this_dt,
272+
this_dt.newbyteorder(native_code),
273+
this_dt.newbyteorder(swapped_code)))
269274
return Recoder(dt_codes,
270-
fields=('code', 'label', 'type', 'dtype', 'sw_dtype'))
275+
fields=('code',
276+
'label',
277+
'type',
278+
'dtype',
279+
'native_dtype',
280+
'sw_dtype'))
271281

272282

273283
def can_cast(in_type, out_type, has_intercept=False, has_slope=False):

0 commit comments

Comments
 (0)