Skip to content

Commit 351ca44

Browse files
committed
DOC+PL+TEST: Correct docstrings and change to property decorators.
1 parent fdd34b5 commit 351ca44

File tree

7 files changed

+147
-135
lines changed

7 files changed

+147
-135
lines changed

nibabel/brainvoyager/bv.py

+61-39
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ def calc_BV_header_size(hdr_dict_proto, hdr_dict, parent_hdr_dict=None):
273273
# check the length of the array to expect
274274
if def_or_name in hdr_dict:
275275
n_values = hdr_dict[def_or_name]
276+
# handle cases when n_values is resides outside of the
277+
# current scope (e.g. nr_of_timepoints in VMP_HDR_DICT_PROTO)
276278
else:
277279
n_values = parent_hdr_dict[def_or_name]
278280
for i in range(n_values):
@@ -306,7 +308,7 @@ def update_BV_header(hdr_dict_proto, hdr_dict_old, hdr_dict_new,
306308
hdr_dict before any changes.
307309
hdr_dict_new: OrderedDict
308310
hdr_dict with changed fields in n_fields_name or c_fields_name fields.
309-
parent_old: OrderedDict
311+
parent_old: None or OrderedDict, optional
310312
When update_BV_header() is called recursively the not yet updated
311313
(parent) hdr_dict is passed to give access to n_fields_name fields
312314
outside the current scope (see below).
@@ -325,28 +327,27 @@ def update_BV_header(hdr_dict_proto, hdr_dict_old, hdr_dict_new,
325327
# handle only nested loop fields
326328
if not isinstance(pack_format, tuple):
327329
continue
330+
# calculate the change of array length and the new array length
331+
if def_or_name in hdr_dict_old:
332+
delta_values = (hdr_dict_new[def_or_name] -
333+
hdr_dict_old[def_or_name])
334+
n_values = hdr_dict_new[def_or_name]
328335
else:
329-
# calculate the change of array length and the new array length
330-
if def_or_name in hdr_dict_old:
331-
delta_values = (hdr_dict_new[def_or_name] -
332-
hdr_dict_old[def_or_name])
333-
n_values = hdr_dict_new[def_or_name]
334-
else:
335-
delta_values = (parent_new[def_or_name] -
336-
parent_old[def_or_name])
337-
n_values = parent_new[def_or_name]
338-
if delta_values > 0: # add nested loops
339-
for i in range(delta_values):
340-
hdr_dict_new[name].append(_proto2default(pack_format,
341-
hdr_dict_new))
342-
elif delta_values < 0: # remove nested loops
343-
for i in range(abs(delta_values)):
344-
hdr_dict_new[name].pop()
345-
# loop over nested fields
346-
for i in range(n_values):
347-
update_BV_header(pack_format, hdr_dict_old[name][i],
348-
hdr_dict_new[name][i], hdr_dict_old,
349-
hdr_dict_new)
336+
delta_values = (parent_new[def_or_name] -
337+
parent_old[def_or_name])
338+
n_values = parent_new[def_or_name]
339+
if delta_values > 0: # add nested loops
340+
for i in range(delta_values):
341+
hdr_dict_new[name].append(_proto2default(pack_format,
342+
hdr_dict_new))
343+
elif delta_values < 0: # remove nested loops
344+
for i in range(abs(delta_values)):
345+
hdr_dict_new[name].pop()
346+
# loop over nested fields
347+
for i in range(n_values):
348+
update_BV_header(pack_format, hdr_dict_old[name][i],
349+
hdr_dict_new[name][i], hdr_dict_old,
350+
hdr_dict_new)
350351
return hdr_dict_new
351352

352353

@@ -453,7 +454,7 @@ class BvFileHeader(Header):
453454
# format defaults
454455
# BV files are radiological (left-is-right) by default
455456
# (VTC files have a flag for that, however)
456-
default_x_flip = True
457+
default_xflip = True
457458
default_endianness = '<' # BV files are always little-endian
458459
allowed_dtypes = [1, 2, 3]
459460
default_dtype = 2
@@ -470,9 +471,10 @@ def __init__(self,
470471
471472
Parameters
472473
----------
473-
binaryblock : {None, string} optional
474-
binary block to set into header. By default, None, in
475-
which case we insert the default empty header block
474+
hdr_dict : None or OrderedDict, optional
475+
An OrderedDict containing all header fields parsed from the file.
476+
By default, None, in which case we create a default hdr_dict from
477+
the corresponding _HDR_DICT_PROTO
476478
endianness : {None, '<','>', other endian code} string, optional
477479
endianness of the binaryblock. If None, guess endianness
478480
from the data.
@@ -641,11 +643,12 @@ def set_data_dtype(self, datatype):
641643
raise HeaderDataError(
642644
'File format does not support setting of header!')
643645

644-
def get_xflip(self):
645-
"""Get xflip for data."""
646-
return self.default_x_flip
646+
@property
647+
def xflip(self):
648+
return self.default_xflip
647649

648-
def set_xflip(self, xflip):
650+
@xflip.setter
651+
def xflip(self, xflip):
649652
"""Set xflip for data."""
650653
if xflip is True:
651654
return
@@ -666,15 +669,15 @@ def get_base_affine(self):
666669
Note that we get the translations from the center of the
667670
(guessed) framing cube of the referenced VMR (anatomical) file.
668671
669-
Internal storage of the image is ZYXT, where (in patient coordiante/
672+
Internal storage of the image is ZYXT, where (in patient coordinates/
670673
real world orientations):
671674
Z := axis increasing from right to left (R to L)
672675
Y := axis increasing from superior to inferior (S to I)
673676
X := axis increasing from anterior to posterior (A to P)
674677
T := volumes (if present in file format)
675678
"""
676679
zooms = self.get_zooms()
677-
if not self.get_xflip():
680+
if not self.xflip:
678681
# make the BV internal Z axis neurological (left-is-left);
679682
# not default in BV files!
680683
zooms = (-zooms[0], zooms[1], zooms[2])
@@ -689,7 +692,7 @@ def get_base_affine(self):
689692
rot[:, 2] = [0, -zooms[1], 0]
690693

691694
# compute the translation
692-
fcc = np.array(self.get_framing_cube()) / 2 # center of framing cube
695+
fcc = np.array(self.framing_cube) / 2 # center of framing cube
693696
bbc = np.array(self.get_bbox_center()) # center of bounding box
694697
tra = np.dot((bbc - fcc), rot)
695698

@@ -700,11 +703,14 @@ def get_base_affine(self):
700703

701704
return M
702705

703-
get_best_affine = get_base_affine
706+
def get_best_affine(self):
707+
return self.get_base_affine()
704708

705-
get_default_affine = get_base_affine
709+
def get_default_affine(self):
710+
return self.get_base_affine()
706711

707-
get_affine = get_base_affine
712+
def get_affine(self):
713+
return self.get_base_affine()
708714

709715
def _guess_framing_cube(self):
710716
"""Guess the dimensions of the framing cube.
@@ -729,7 +735,8 @@ def _guess_framing_cube(self):
729735
else:
730736
return fc, fc, fc
731737

732-
def get_framing_cube(self):
738+
@property
739+
def framing_cube(self):
733740
"""Get the dimensions of the framing cube.
734741
735742
Get the dimensions of the framing cube that constitutes the
@@ -739,7 +746,8 @@ def get_framing_cube(self):
739746
"""
740747
return self._framing_cube
741748

742-
def set_framing_cube(self, fc):
749+
@framing_cube.setter
750+
def framing_cube(self, fc):
743751
"""Set the dimensions of the framing cube.
744752
745753
Set the dimensions of the framing cube that constitutes the
@@ -771,10 +779,24 @@ def get_zooms(self):
771779
for d in shape[0:3])
772780

773781
def set_zooms(self, zooms):
782+
"""Set the zooms for the image.
783+
784+
Voxel dimensions of functional data in BV file formats are
785+
always in relationship to the voxel dimensions in a VMR file and
786+
therefore need to be equal for all three spatial dimensions.
787+
788+
Parameters
789+
----------
790+
zooms : int or sequence
791+
An integer or a sequence of integers specifying the relationship
792+
between voxel dimensions and real-world dimensions. If a single
793+
integer is used it is applied to all spatial dimensions. If a
794+
sequence of integers is used all dimensions have to be equal.
795+
"""
774796
if type(zooms) == int:
775797
self._hdr_dict['resolution'] = zooms
776798
else:
777-
if any([zooms[i] != zooms[i + 1] for i in range(len(zooms) - 1)]):
799+
if np.any(np.diff(zooms)):
778800
raise BvError('Zooms for all dimensions must be equal!')
779801
else:
780802
self._hdr_dict['resolution'] = int(zooms[0])

nibabel/brainvoyager/bv_vmp.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ def get_data_shape(self):
113113

114114
def set_data_shape(self, shape=None, zyx=None, n=None):
115115
''' Set shape of data
116+
116117
To conform with nibabel standards this implements shape.
117118
However, to fill the BvVmpHeader with sensible information use the
118119
zyx and the n parameter instead.
@@ -164,14 +165,16 @@ def set_data_shape(self, shape=None, zyx=None, n=None):
164165
self._hdr_dict = update_BV_header(self.hdr_dict_proto,
165166
hdr_dict_old, self._hdr_dict)
166167

167-
def get_framing_cube(self):
168+
@property
169+
def framing_cube(self):
168170
''' Get the dimensions of the framing cube that constitutes
169171
the coordinate system boundaries for the bounding box.
170172
'''
171173
hdr = self._hdr_dict
172174
return hdr['dim_z'], hdr['dim_y'], hdr['dim_x']
173175

174-
def set_framing_cube(self, fc):
176+
@framing_cube.setter
177+
def framing_cube(self, fc):
175178
''' Set the dimensions of the framing cube that constitutes
176179
the coordinate system boundaries for the bounding box.
177180
@@ -191,5 +194,6 @@ class BvVmpImage(BvFileImage):
191194
files_types = (('image', '.vmp'),)
192195
valid_exts = ('.vmp',)
193196

197+
194198
load = BvVmpImage.load
195199
save = BvVmpImage.instance_to_filename

nibabel/brainvoyager/bv_vmr.py

+19-24
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@
7373
)
7474

7575

76-
def computeOffsetPostHDR(hdr_dict, fileobj):
77-
currentSeek = fileobj.tell()
78-
return currentSeek + (hdr_dict['dim_x'] * hdr_dict['dim_y'] *
79-
hdr_dict['dim_z'])
76+
def compute_offset_post_hdr(hdr_dict, fileobj):
77+
current_seek = fileobj.tell()
78+
return current_seek + (hdr_dict['dim_x'] * hdr_dict['dim_y'] *
79+
hdr_dict['dim_z'])
8080

8181

82-
def concatePrePos(preDict, posDict):
82+
def merge_pre_pos(preDict, posDict):
8383
temp = preDict.copy()
8484
temp.update(posDict)
8585
return temp
@@ -175,7 +175,7 @@ def get_base_affine(self):
175175
rot[:, 2] = [0, -zooms[1], 0]
176176

177177
# compute the translation
178-
fcc = np.array(self.get_framing_cube()) / 2 # center of framing cube
178+
fcc = np.array(self.framing_cube) / 2 # center of framing cube
179179
bbc = np.array(self.get_bbox_center()) # center of bounding box
180180
tra = np.dot((bbc - fcc), rot)
181181

@@ -187,30 +187,24 @@ def get_base_affine(self):
187187
# look for additional transformations in past_spatial_trans and combine
188188
# with M
189189
if self._hdr_dict['past_spatial_trans']:
190-
STarray = np.zeros((len(self._hdr_dict['past_spatial_trans']),
191-
4, 4))
190+
st_array = np.zeros((len(self._hdr_dict['past_spatial_trans']),
191+
4, 4))
192192
for st in range(len(self._hdr_dict['past_spatial_trans'])):
193-
STarray[st, :, :] = \
193+
st_array[st, :, :] = \
194194
parse_st(self._hdr_dict['past_spatial_trans'][st])
195-
combinedST = combine_st(STarray, inv=True)
196-
M = np.dot(M, combinedST)
195+
combined_st = combine_st(st_array, inv=True)
196+
M = np.dot(M, combined_st)
197197
return M
198198

199-
get_best_affine = get_base_affine
200-
201-
get_default_affine = get_base_affine
202-
203-
get_affine = get_base_affine
204-
205199
@classmethod
206200
def from_fileobj(klass, fileobj, endianness=default_endianness,
207201
check=True):
208-
hdr_dictPre = parse_BV_header(VMR_PRHDR_DICT_PROTO, fileobj)
202+
hdr_dict_pre = parse_BV_header(VMR_PRHDR_DICT_PROTO, fileobj)
209203
# calculate new seek for the post data header
210-
newSeek = computeOffsetPostHDR(hdr_dictPre, fileobj)
211-
fileobj.seek(newSeek)
212-
hdr_dictPos = parse_BV_header(VMR_PSHDR_DICT_PROTO, fileobj)
213-
hdr_dict = concatePrePos(hdr_dictPre, hdr_dictPos)
204+
new_seek = compute_offset_post_hdr(hdr_dict_pre, fileobj)
205+
fileobj.seek(new_seek)
206+
hdr_dict_pos = parse_BV_header(VMR_PSHDR_DICT_PROTO, fileobj)
207+
hdr_dict = merge_pre_pos(hdr_dict_pre, hdr_dict_pos)
214208
# The offset is always 8 for VMR files.
215209
offset = 8
216210
return klass(hdr_dict, endianness, check, offset)
@@ -219,7 +213,7 @@ def get_bbox_center(self):
219213
"""Get the center coordinate of the bounding box.
220214
Not required for VMR files
221215
"""
222-
return np.array([self.get_framing_cube() / 2 for d in range(3)])
216+
return np.array([self.framing_cube / 2 for d in range(3)])
223217

224218
def get_zooms(self):
225219
return (self._hdr_dict['vox_res_z'], self._hdr_dict['vox_res_y'],
@@ -236,7 +230,7 @@ def write_to(self, fileobj):
236230
sizePrH = calc_BV_header_size(VMR_PRHDR_DICT_PROTO, self._hdr_dict)
237231
# write the preHeader
238232
fileobj.write(binaryblock[0:sizePrH])
239-
fileobj.seek(computeOffsetPostHDR(self._hdr_dict, fileobj))
233+
fileobj.seek(compute_offset_post_hdr(self._hdr_dict, fileobj))
240234
fileobj.write(binaryblock[sizePrH:])
241235

242236

@@ -250,5 +244,6 @@ class BvVmrImage(BvFileImage):
250244
files_types = (('image', '.vmr'),)
251245
valid_exts = ('.vmr',)
252246

247+
253248
load = BvVmrImage.load
254249
save = BvVmrImage.instance_to_filename

0 commit comments

Comments
 (0)