47
47
from .._h5py_compat import h5py , have_h5py
48
48
from .. import ecat
49
49
from .. import parrec
50
+ from ..casting import have_binary128
50
51
51
52
from ..arrayproxy import ArrayProxy , is_proxy
52
53
53
54
from nose import SkipTest
54
55
from nose .tools import (assert_true , assert_false , assert_raises ,
55
56
assert_equal , assert_not_equal , assert_greater_equal )
56
57
57
- from numpy .testing import ( assert_almost_equal , assert_array_equal )
58
+ from numpy .testing import assert_almost_equal , assert_array_equal , assert_allclose
58
59
59
60
from ..testing import data_path as DATA_PATH , assert_dt_equal
60
61
@@ -142,7 +143,10 @@ def validate_get_scaled(self, pmaker, params):
142
143
143
144
for dtype in np .sctypes ['float' ] + np .sctypes ['int' ] + np .sctypes ['uint' ]:
144
145
out = prox .get_scaled (dtype = dtype )
145
- assert_almost_equal (out , params ['arr_out' ])
146
+ # Half-precision is imprecise. Obviously. It's a bad idea, but don't break
147
+ # the test over it.
148
+ rtol = 1e-03 if dtype == np .float16 else 1e-05
149
+ assert_allclose (out , params ['arr_out' ].astype (out .dtype ), rtol = rtol , atol = 1e-08 )
146
150
assert_greater_equal (out .dtype , np .dtype (dtype ))
147
151
# Shape matches expected shape
148
152
assert_equal (out .shape , params ['shape' ])
@@ -192,6 +196,7 @@ class TestAnalyzeProxyAPI(_TestProxyAPI):
192
196
shapes = ((2 ,), (2 , 3 ), (2 , 3 , 4 ), (2 , 3 , 4 , 5 ))
193
197
has_slope = False
194
198
has_inter = False
199
+ data_dtypes = (np .uint8 , np .int16 , np .int32 , np .float32 , np .complex64 , np .float64 )
195
200
array_order = 'F'
196
201
# Cannot set offset for Freesurfer
197
202
settable_offset = True
@@ -216,11 +221,12 @@ def obj_params(self):
216
221
offsets = (self .header_class ().get_data_offset (),)
217
222
else :
218
223
offsets = (0 , 16 )
219
- slopes = (1. , 2. ) if self .has_slope else (1. ,)
220
- inters = (0. , 10. ) if self .has_inter else (0. ,)
221
- dtypes = (np .uint8 , np .int16 , np .float32 )
224
+ # For non-integral parameters, cast to float32 value can be losslessly cast
225
+ # later, enabling exact checks, then back to float for consistency
226
+ slopes = (1. , 2. , float (np .float32 (3.1416 ))) if self .has_slope else (1. ,)
227
+ inters = (0. , 10. , float (np .float32 (2.7183 ))) if self .has_inter else (0. ,)
222
228
for shape , dtype , offset , slope , inter in product (self .shapes ,
223
- dtypes ,
229
+ self . data_dtypes ,
224
230
offsets ,
225
231
slopes ,
226
232
inters ):
@@ -262,7 +268,7 @@ def sio_func():
262
268
dtype = dtype ,
263
269
dtype_out = dtype_out ,
264
270
arr = arr .copy (),
265
- arr_out = arr * slope + inter ,
271
+ arr_out = arr . astype ( dtype_out ) * slope + inter ,
266
272
shape = shape ,
267
273
offset = offset ,
268
274
slope = slope ,
@@ -325,6 +331,10 @@ class TestSpm2AnalyzeProxyAPI(TestSpm99AnalyzeProxyAPI):
325
331
class TestNifti1ProxyAPI (TestSpm99AnalyzeProxyAPI ):
326
332
header_class = Nifti1Header
327
333
has_inter = True
334
+ data_dtypes = (np .uint8 , np .int16 , np .int32 , np .float32 , np .complex64 , np .float64 ,
335
+ np .int8 , np .uint16 , np .uint32 , np .int64 , np .uint64 , np .complex128 )
336
+ if have_binary128 ():
337
+ data_dtypes .extend (np .float128 , np .complex256 )
328
338
329
339
330
340
class TestMGHAPI (TestAnalyzeProxyAPI ):
@@ -334,6 +344,7 @@ class TestMGHAPI(TestAnalyzeProxyAPI):
334
344
has_inter = False
335
345
settable_offset = False
336
346
data_endian = '>'
347
+ data_dtypes = (np .uint8 , np .int16 , np .int32 , np .float32 )
337
348
338
349
339
350
class TestMinc1API (_TestProxyAPI ):
0 commit comments