Skip to content

Commit b457534

Browse files
committed
RF: Drop (mostly) redundant ArrayProxy.get_scaled() method
1 parent 5b76c8e commit b457534

File tree

6 files changed

+44
-111
lines changed

6 files changed

+44
-111
lines changed

nibabel/arrayproxy.py

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -378,34 +378,27 @@ def get_unscaled(self):
378378
"""
379379
return self._get_unscaled(slicer=())
380380

381-
def get_scaled(self, dtype=None):
382-
""" Read data from file and apply scaling
381+
def __array__(self, dtype=None):
382+
""" Read data from file and apply scaling, casting to ``dtype``
383383
384-
The dtype of the returned array is the narrowest dtype that can
385-
represent the data without overflow, and is at least as wide as
386-
the dtype parameter.
384+
If ``dtype`` is unspecified, the dtype of the returned array is the
385+
narrowest dtype that can represent the data without overflow.
386+
Generally, it is the wider of the dtypes of the slopes or intercepts.
387387
388-
If dtype is unspecified, it is the wider of the dtypes of the slope
389-
or intercept. This will generally be determined by the parameter
390-
size in the image header, and so should be consistent for a given
391-
image format, but may vary across formats. Notably, these factors
392-
are single-precision (32-bit) floats for NIfTI-1 and double-precision
393-
(64-bit) floats for NIfTI-2.
388+
The types of the scale factors will generally be determined by the
389+
parameter size in the image header, and so should be consistent for a
390+
given image format, but may vary across formats.
394391
395392
Parameters
396393
----------
397-
dtype : numpy dtype specifier
398-
A numpy dtype specifier specifying the narrowest acceptable
399-
dtype.
394+
dtype : numpy dtype specifier, optional
395+
A numpy dtype specifier specifying the type of the returned array.
400396
401397
Returns
402398
-------
403399
array
404-
Scaled of image data of data type `dtype`.
400+
Scaled image data with type `dtype`.
405401
"""
406-
return self._get_scaled(dtype=dtype, slicer=())
407-
408-
def __array__(self, dtype=None):
409402
arr = self._get_scaled(dtype=dtype, slicer=())
410403
if dtype is not None:
411404
arr = arr.astype(dtype, copy=False)

nibabel/dataobj_images.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import numpy as np
1212

13-
from .arrayproxy import is_proxy
1413
from .filebasedimages import FileBasedImage
1514
from .keywordonly import kw_only_meth
1615
from .deprecated import deprecate_with_version
@@ -351,14 +350,10 @@ def get_fdata(self, caching='fill', dtype=np.float64):
351350
if self._fdata_cache is not None:
352351
if self._fdata_cache.dtype.type == dtype.type:
353352
return self._fdata_cache
354-
dataobj = self._dataobj
355-
# Attempt to confine data array to dtype during scaling
356-
# On overflow, may still upcast
357-
if is_proxy(dataobj):
358-
dataobj = dataobj.get_scaled(dtype=dtype)
359353
# Always return requested data type
360-
# For array proxies, will only copy on overflow
361-
data = np.asanyarray(dataobj, dtype=dtype)
354+
# For array proxies, will attempt to confine data array to dtype
355+
# during scaling
356+
data = np.asanyarray(self._dataobj, dtype=dtype)
362357
if caching == 'fill':
363358
self._fdata_cache = data
364359
return data

nibabel/ecat.py

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,16 @@ def __array__(self, dtype=None):
696696
697697
If you want to read only some slices, use the slicing syntax
698698
(``__getitem__``) below, or ``subheader.data_from_fileobj(frame)``
699+
700+
Parameters
701+
----------
702+
dtype : numpy dtype specifier, optional
703+
A numpy dtype specifier specifying the type of the returned array.
704+
705+
Returns
706+
-------
707+
array
708+
Scaled image data with type `dtype`.
699709
'''
700710
# dtype=None is interpreted as float64
701711
data = np.empty(self.shape, dtype=dtype)
@@ -705,32 +715,6 @@ def __array__(self, dtype=None):
705715
frame_mapping[i][0])
706716
return data
707717

708-
def get_scaled(self, dtype=None):
709-
""" Read data from file and apply scaling
710-
711-
The dtype of the returned array is the narrowest dtype that can
712-
represent the data without overflow, and is at least as wide as
713-
the dtype parameter.
714-
715-
If dtype is unspecified, it is automatically determined.
716-
717-
Parameters
718-
----------
719-
dtype : numpy dtype specifier
720-
A numpy dtype specifier specifying the narrowest acceptable
721-
dtype.
722-
723-
Returns
724-
-------
725-
array
726-
Scaled of image data of data type `dtype`.
727-
"""
728-
data = self.__array__()
729-
if dtype is None:
730-
return data
731-
final_type = np.promote_types(data.dtype, dtype)
732-
return data.astype(final_type, copy=False)
733-
734718
def __getitem__(self, sliceobj):
735719
""" Return slice `sliceobj` from ECAT data, optimizing if possible
736720
"""

nibabel/minc1.py

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -261,45 +261,29 @@ def ndim(self):
261261
def is_proxy(self):
262262
return True
263263

264-
def _get_scaled(self, dtype, slicer):
265-
data = self.minc_file.get_scaled_data(slicer)
266-
if dtype is None:
267-
return data
268-
final_type = np.promote_types(data.dtype, dtype)
269-
return data.astype(final_type, copy=False)
270-
271-
def get_scaled(self, dtype=None):
272-
""" Read data from file and apply scaling
273-
274-
The dtype of the returned array is the narrowest dtype that can
275-
represent the data without overflow, and is at least as wide as
276-
the dtype parameter.
264+
def __array__(self, dtype=None):
265+
""" Read data from file and apply scaling, casting to ``dtype``
277266
278-
If dtype is unspecified, it is automatically determined.
267+
If ``dtype`` is unspecified, the dtype is automatically determined.
279268
280269
Parameters
281270
----------
282-
dtype : numpy dtype specifier
283-
A numpy dtype specifier specifying the narrowest acceptable
284-
dtype.
271+
dtype : numpy dtype specifier, optional
272+
A numpy dtype specifier specifying the type of the returned array.
285273
286274
Returns
287275
-------
288276
array
289-
Scaled of image data of data type `dtype`.
277+
Scaled image data with type `dtype`.
290278
"""
291-
return self._get_scaled(dtype=dtype, slicer=())
292-
293-
def __array__(self, dtype=None):
294-
''' Read of data from file '''
295-
arr = self._get_scaled(dtype=dtype, slicer=())
279+
arr = self.minc_file.get_scaled_data(sliceobj=())
296280
if dtype is not None:
297281
arr = arr.astype(dtype, copy=False)
298282
return arr
299283

300284
def __getitem__(self, sliceobj):
301285
""" Read slice `sliceobj` of data from file """
302-
return self._get_scaled(dtype=None, slicer=sliceobj)
286+
return self.minc_file.get_scaled_data(sliceobj)
303287

304288

305289
class MincHeader(SpatialHeader):

nibabel/parrec.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -676,30 +676,23 @@ def get_unscaled(self):
676676
"""
677677
return self._get_unscaled(slicer=())
678678

679-
def get_scaled(self, dtype=None):
680-
""" Read data from file and apply scaling
681-
682-
The dtype of the returned array is the narrowest dtype that can
683-
represent the data without overflow, and is at least as wide as
684-
the dtype parameter.
679+
def __array__(self, dtype=None):
680+
""" Read data from file and apply scaling, casting to ``dtype``
685681
686-
If dtype is unspecified, it is the wider of the dtypes of the slopes
687-
or intercepts
682+
If ``dtype`` is unspecified, the dtype of the returned array is the
683+
narrowest dtype that can represent the data without overflow.
684+
Generally, it is the wider of the dtypes of the slopes or intercepts.
688685
689686
Parameters
690687
----------
691-
dtype : numpy dtype specifier
692-
A numpy dtype specifier specifying the narrowest acceptable
693-
dtype.
688+
dtype : numpy dtype specifier, optional
689+
A numpy dtype specifier specifying the type of the returned array.
694690
695691
Returns
696692
-------
697693
array
698-
Scaled of image data of data type `dtype`.
694+
Scaled image data with type `dtype`.
699695
"""
700-
return self._get_scaled(dtype=dtype, slicer=())
701-
702-
def __array__(self, dtype=None):
703696
arr = self._get_scaled(dtype=dtype, slicer=())
704697
if dtype is not None:
705698
arr = arr.astype(dtype, copy=False)

nibabel/tests/test_proxy_api.py

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,10 @@ def validate_array_interface_with_dtype(self, pmaker, params):
142142
for dtype in np.sctypes['float'] + np.sctypes['int'] + np.sctypes['uint']:
143143
# Directly coerce with a dtype
144144
direct = dtype(prox)
145-
assert_almost_equal(direct, orig.astype(dtype))
145+
# Half-precision is imprecise. Obviously. It's a bad idea, but don't break
146+
# the test over it.
147+
rtol = 1e-03 if dtype == np.float16 else 1e-05
148+
assert_allclose(direct, orig.astype(dtype), rtol=rtol, atol=1e-08)
146149
assert_dt_equal(direct.dtype, np.dtype(dtype))
147150
assert_equal(direct.shape, params['shape'])
148151
# All three methods should produce equivalent results
@@ -153,25 +156,6 @@ def validate_array_interface_with_dtype(self, pmaker, params):
153156
# Shape matches expected shape
154157
assert_equal(out.shape, params['shape'])
155158

156-
def validate_get_scaled(self, pmaker, params):
157-
# Check proxy returns expected array from asarray
158-
prox, fio, hdr = pmaker()
159-
out = prox.get_scaled()
160-
assert_array_equal(out, params['arr_out'])
161-
assert_dt_equal(out.dtype, params['dtype_out'])
162-
# Shape matches expected shape
163-
assert_equal(out.shape, params['shape'])
164-
165-
for dtype in np.sctypes['float'] + np.sctypes['int'] + np.sctypes['uint']:
166-
out = prox.get_scaled(dtype=dtype)
167-
# Half-precision is imprecise. Obviously. It's a bad idea, but don't break
168-
# the test over it.
169-
rtol = 1e-03 if dtype == np.float16 else 1e-05
170-
assert_allclose(out, params['arr_out'].astype(out.dtype), rtol=rtol, atol=1e-08)
171-
assert_greater_equal(out.dtype, np.dtype(dtype))
172-
# Shape matches expected shape
173-
assert_equal(out.shape, params['shape'])
174-
175159
def validate_header_isolated(self, pmaker, params):
176160
# Confirm altering input header has no effect
177161
# Depends on header providing 'get_data_dtype', 'set_data_dtype',

0 commit comments

Comments
 (0)