@@ -23,7 +23,7 @@ def __init__(self, array, out_dtype=None)
23
23
24
24
import numpy as np
25
25
26
- from .casting import shared_range , int_to_float , as_int
26
+ from .casting import shared_range , int_to_float , as_int , int_abs
27
27
from .volumeutils import finite_range , array_to_file
28
28
29
29
@@ -277,11 +277,10 @@ def to_fileobj(self, fileobj, order='F', nan2zero=True):
277
277
278
278
def _do_scaling (self ):
279
279
arr = self ._array
280
- arr_dtype = arr .dtype
281
280
out_dtype = self ._out_dtype
282
281
assert out_dtype .kind in 'iu'
283
282
mn , mx = self .finite_range ()
284
- if arr_dtype .kind == 'f' :
283
+ if arr . dtype .kind == 'f' :
285
284
# Float to (u)int scaling
286
285
self ._range_scale ()
287
286
return
@@ -291,10 +290,21 @@ def _do_scaling(self):
291
290
if mx <= out_max and mn >= out_min : # already in range
292
291
return
293
292
# (u)int to (u)int scaling
293
+ self ._iu2iu ()
294
+
295
+ def _iu2iu (self ):
296
+ # (u)int to (u)int scaling
297
+ mn , mx = self .finite_range ()
294
298
if self ._out_dtype .kind == 'u' :
299
+ # We're checking for a sign flip. This can only work for uint
300
+ # output, because, for int output, the abs min of the type is
301
+ # greater than the abs max, so the data either fit into the range in
302
+ # the test above, or this test won't pass
295
303
shared_min , shared_max = shared_range (self .scaler_dtype ,
296
304
self ._out_dtype )
297
- if mx <= 0 and abs (mn ) <= shared_max : # sign flip enough?
305
+ # Need abs that deals with max neg ints. abs problem only arises
306
+ # when all the data is set to max neg integer value
307
+ if mx <= 0 and int_abs (mn ) <= shared_max : # sign flip enough?
298
308
# -1.0 * arr will be in scaler_dtype precision
299
309
self .slope = - 1.0
300
310
return
@@ -406,42 +416,20 @@ def to_fileobj(self, fileobj, order='F', nan2zero=True):
406
416
order = order ,
407
417
nan2zero = nan2zero )
408
418
409
- def _do_scaling (self ):
410
- """ Calculate / set scaling for floats/(u)ints to (u)ints
411
- """
412
- arr = self ._array
413
- arr_dtype = arr .dtype
414
- out_dtype = self ._out_dtype
415
- assert out_dtype .kind in 'iu'
416
- mn , mx = self .finite_range ()
417
- if mn == np .inf : # No valid data
418
- return
419
- if (mn , mx ) == (0.0 , 0.0 ): # Data all zero
420
- return
421
- if arr_dtype .kind == 'f' :
422
- # Float to (u)int scaling
423
- self ._range_scale ()
424
- return
419
+ def _iu2iu (self ):
425
420
# (u)int to (u)int
426
- info = np .iinfo (out_dtype )
427
- out_max , out_min = info .max , info .min
428
- if mx <= out_max and mn >= out_min : # already in range
421
+ mn , mx = self .finite_range ()
422
+ shared_min , shared_max = shared_range (self .scaler_dtype ,
423
+ self ._out_dtype )
424
+ # range may be greater than the largest integer for this type.
425
+ # as_int needed to work round numpy 1.4.1 int casting bug
426
+ type_range = as_int (shared_max ) - as_int (shared_min )
427
+ mn2mx = as_int (mx ) - as_int (mn )
428
+ if mn2mx <= type_range : # offset enough?
429
+ self .inter = mn - shared_min
429
430
return
430
- # (u)int to (u)int scaling
431
- if self ._out_dtype .kind == 'u' :
432
- shared_min , shared_max = shared_range (self .scaler_dtype ,
433
- self ._out_dtype )
434
- # range may be greater than the largest integer for this type.
435
- # as_int needed to work round numpy 1.4.1 int casting bug
436
- mn2mx = as_int (mx ) - as_int (mn )
437
- if mn2mx <= shared_max : # offset enough?
438
- self .inter = mn
439
- return
440
- if mx <= 0 and abs (mn ) <= shared_max : # sign flip enough?
441
- # -1.0 * arr will be in scaler_dtype precision
442
- self .slope = - 1.0
443
- return
444
- self ._range_scale ()
431
+ # Try slope options (sign flip) and then range scaling
432
+ super (SlopeInterArrayWriter , self )._iu2iu ()
445
433
446
434
def _range_scale (self ):
447
435
""" Calculate scaling, intercept based on data range and output type """
0 commit comments