Skip to content

Commit f55e7a9

Browse files
committed
STY: improve coding style for parrec based on feedback
1 parent 19fd9c1 commit f55e7a9

File tree

2 files changed

+44
-21
lines changed

2 files changed

+44
-21
lines changed

nibabel/parrec.py

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,21 @@ def _process_image_lines(image_lines, version):
329329
return image_defs
330330

331331

332+
def _direction_numbers(bvecs):
333+
""" Enumerate directions from an (N, 3) array of direction vectors.
334+
"""
335+
cnt = 0
336+
bvec_dict = {}
337+
bvec_nos = np.zeros(len(bvecs))
338+
for i, bvec in enumerate(bvecs):
339+
bv = tuple(bvec)
340+
if bv not in bvec_dict:
341+
bvec_dict[bv] = cnt
342+
cnt += 1
343+
bvec_nos[i] = bvec_dict.get(bv)
344+
return bvec_nos
345+
346+
332347
def vol_numbers(slice_nos):
333348
""" Calculate volume numbers inferred from slice numbers `slice_nos`
334349
@@ -634,7 +649,9 @@ def __init__(self, info, image_defs, permit_truncated=False,
634649
recording is detected.
635650
strict_sort : bool, optional, keyword-only
636651
If True, a larger number of header fields are used while sorting
637-
the REC data array.
652+
the REC data array. This may produce a different sort order than
653+
`strict_sort=False`, where volumes are sorted by the order in which
654+
the slices appear in the .PAR file.
638655
"""
639656
self.general_info = info.copy()
640657
self.image_defs = image_defs.copy()
@@ -747,6 +764,11 @@ def get_bvals_bvecs(self):
747764
bvecs = apply_affine(np.linalg.inv(permute_to_psl), bvecs)
748765
return bvals, bvecs
749766

767+
def get_def(self, name):
768+
""" Return a single image definition field. """
769+
idef = self.image_defs
770+
return idef[name] if name in idef.dtype.names else None
771+
750772
def _get_unique_image_prop(self, name):
751773
""" Scan image definitions and return unique value of a property.
752774
@@ -1011,7 +1033,9 @@ def get_sorted_slice_indices(self):
10111033
discarding any slice indices from incomplete volumes.
10121034
10131035
If `self.strict_sort` is True, a more complicated sorting based on
1014-
multiple fields from the .PAR file is used.
1036+
multiple fields from the .PAR file is used. This may produce a
1037+
different sort order than `strict_sort=False`, where volumes are sorted
1038+
by the order in which the slices appear in the .PAR file.
10151039
10161040
Returns
10171041
-------
@@ -1034,22 +1058,18 @@ def get_sorted_slice_indices(self):
10341058
echos = self.image_defs['echo number']
10351059

10361060
# try adding keys only present in a subset of .PAR files
1037-
try:
1038-
# only present in PAR v4.2+
1039-
asl_labels = self.image_defs['label type']
1040-
asl_keys = (asl_labels, )
1041-
except:
1042-
asl_keys = ()
1061+
idefs = self.image_defs
1062+
asl_keys = (idefs['label_type'], ) if 'label_type' in \
1063+
idefs.dtype.names else ()
1064+
10431065
if not self.general_info['diffusion'] == 0:
1044-
try:
1045-
# only present for .PAR v4.1+
1046-
bvals = self.image_defs['diffusion b value number']
1047-
bvecs = self.image_defs['gradient orientation number']
1048-
except:
1049-
bvals = self.image_defs['diffusion_b_factor']
1050-
# use hash to get a single sortable value per direction
1051-
bvecs = [hash(tuple(
1052-
a)) for a in self.image_defs['diffusion'].tolist()]
1066+
bvals = self.get_def('diffusion b value number')
1067+
if bvals is None:
1068+
bvals = self.get_def('diffusion_b_factor')
1069+
bvecs = self.get_def('gradient orientation number')
1070+
if bvecs is None:
1071+
# manually enumerate the different directions
1072+
bvecs = _direction_numbers(self.get_def('diffusion'))
10531073
diffusion_keys = (bvecs, bvals)
10541074
else:
10551075
diffusion_keys = ()
@@ -1124,7 +1144,9 @@ def from_file_map(klass, file_map, mmap=True, permit_truncated=False,
11241144
:meth:`PARRECHeader.get_data_scaling`).
11251145
strict_sort : bool, optional, keyword-only
11261146
If True, a larger number of header fields are used while sorting
1127-
the REC data array.
1147+
the REC data array. This may produce a different sort order than
1148+
`strict_sort=False`, where volumes are sorted by the order in which
1149+
the slices appear in the .PAR file.
11281150
"""
11291151
with file_map['header'].get_prepare_fileobj('rt') as hdr_fobj:
11301152
hdr = klass.header_class.from_fileobj(
@@ -1162,7 +1184,9 @@ def from_filename(klass, filename, mmap=True, permit_truncated=False,
11621184
:meth:`PARRECHeader.get_data_scaling`).
11631185
strict_sort : bool, optional, keyword-only
11641186
If True, a larger number of header fields are used while sorting
1165-
the REC data array.
1187+
the REC data array. This may produce a different sort order than
1188+
`strict_sort=False`, where volumes are sorted by the order in which
1189+
the slices appear in the .PAR file.
11661190
"""
11671191
file_map = klass.filespec_to_file_map(filename)
11681192
return klass.from_file_map(file_map,

nibabel/tests/test_parrec.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,10 +567,9 @@ class FakeHeader(object):
567567
""" Minimal API of header for PARRECArrayProxy
568568
"""
569569

570-
def __init__(self, shape, dtype, strict_sort=False):
570+
def __init__(self, shape, dtype):
571571
self._shape = shape
572572
self._dtype = np.dtype(dtype)
573-
self.strict_sort = strict_sort
574573

575574
def get_data_shape(self):
576575
return self._shape

0 commit comments

Comments
 (0)