Skip to content

Commit 49725c7

Browse files
committed
Permit tuple ArrayProxy spec in place of header
1 parent d4e152a commit 49725c7

File tree

1 file changed

+40
-12
lines changed

1 file changed

+40
-12
lines changed

nibabel/arrayproxy.py

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,17 @@ class ArrayProxy(object):
4545
of the numpy dtypes, starting at a given file position ``offset`` with
4646
single ``slope`` and ``intercept`` scaling to produce output values.
4747
48-
The class ``__init__`` requires a ``header`` object with methods:
48+
The class ``__init__`` requires a spec which defines how the data will be
49+
read and rescaled. The spec may be a tuple of length 2 - 5, containing the
50+
shape, storage dtype, offset, slope and intercept, or a ``header`` object
51+
with methods:
4952
5053
* get_data_shape
5154
* get_data_dtype
5255
* get_data_offset
5356
* get_slope_inter
5457
55-
The header should also have a 'copy' method. This requirement will go away
58+
A header should also have a 'copy' method. This requirement will go away
5659
when the deprecated 'header' propoerty goes away.
5760
5861
This implementation allows us to deal with Analyze and its variants,
@@ -64,17 +67,32 @@ class ArrayProxy(object):
6467
"""
6568
# Assume Fortran array memory layout
6669
order = 'F'
70+
_header = None
6771

6872
@kw_only_meth(2)
69-
def __init__(self, file_like, header, mmap=True):
73+
def __init__(self, file_like, spec, mmap=True):
7074
""" Initialize array proxy instance
7175
7276
Parameters
7377
----------
7478
file_like : object
7579
File-like object or filename. If file-like object, should implement
7680
at least ``read`` and ``seek``.
77-
header : object
81+
spec : object or tuple
82+
Tuple must have length 2-5, with the following fields:
83+
- shape : tuple
84+
tuple of ints describing shape of data
85+
- storage_dtype : dtype specifier
86+
dtype of array inside proxied file, or input to ``numpy.dtype``
87+
to specify array dtype
88+
- offset : int
89+
Offset, in bytes, of data array from start of file
90+
(default: 0)
91+
- slope : float
92+
Scaling factor for resulting data (default: 1.0)
93+
- inter : float
94+
Intercept for rescaled dadta (default: 0.0)
95+
OR
7896
Header object implementing ``get_data_shape``, ``get_data_dtype``,
7997
``get_data_offset``, ``get_slope_inter``
8098
mmap : {True, False, 'c', 'r'}, optional, keyword only
@@ -90,16 +108,26 @@ def __init__(self, file_like, header, mmap=True):
90108
if mmap not in (True, False, 'c', 'r'):
91109
raise ValueError("mmap should be one of {True, False, 'c', 'r'}")
92110
self.file_like = file_like
111+
if hasattr(spec, 'get_data_shape'):
112+
slope, inter = spec.get_slope_inter()
113+
par = (spec.get_data_shape(),
114+
spec.get_data_dtype(),
115+
spec.get_data_offset(),
116+
1. if slope is None else slope,
117+
0. if inter is None else inter)
118+
# Reference to original header; we will remove this soon
119+
self._header = spec.copy()
120+
elif 2 <= len(spec) <= 5:
121+
optional = (0, 1., 0.)
122+
par = spec + optional[len(spec) - 2:]
123+
else:
124+
raise TypeError('spec must be tuple of length 2-5 or header object')
125+
93126
# Copies of values needed to read array
94-
self._shape = header.get_data_shape()
95-
self._dtype = header.get_data_dtype()
96-
self._offset = header.get_data_offset()
97-
self._slope, self._inter = header.get_slope_inter()
98-
self._slope = 1.0 if self._slope is None else self._slope
99-
self._inter = 0.0 if self._inter is None else self._inter
127+
self._shape, self._dtype, self._offset, self._slope, self._inter = par
128+
# Permit any specifier that can be interpreted as a numpy dtype
129+
self._dtype = np.dtype(self._dtype)
100130
self._mmap = mmap
101-
# Reference to original header; we will remove this soon
102-
self._header = header.copy()
103131

104132
@property
105133
def header(self):

0 commit comments

Comments
 (0)