Skip to content

Commit 4b916f6

Browse files
committed
RF: Move annotation value generation code into a separate function. Warn in
write_annot if annotation values not correct.
1 parent c6c6677 commit 4b916f6

File tree

1 file changed

+35
-24
lines changed

1 file changed

+35
-24
lines changed

nibabel/freesurfer/io.py

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,27 @@ def _read_volume_info(fobj):
7373
return volume_info
7474

7575

76+
def _pack_rgba(rgba):
77+
"""Used by :meth:`read_annot` and :meth:`write_annot` to pack an RGBA
78+
sequence into a single integer.
79+
80+
Parameters
81+
----------
82+
83+
rgba : ndarray, shape (n, 4)
84+
RGBA colours
85+
86+
Returns
87+
-------
88+
89+
out : ndarray, shape (n, )
90+
Annotation values for each colour.
91+
"""
92+
# ctab :: n x 4
93+
bitshifts = 2 ** np.array([[0], [8], [16], [24]], dtype=rgba.dtype)
94+
return rgba.dot(bitshifts).squeeze()
95+
96+
7697
def read_geometry(filepath, read_metadata=False, read_stamp=False):
7798
"""Read a triangular format Freesurfer surface mesh.
7899
@@ -347,35 +368,30 @@ def read_annot(filepath, orig_ids=False):
347368
orig_tab = np.fromfile(fobj, '>c', length)
348369
orig_tab = orig_tab[:-1]
349370
names = list()
350-
ctab = np.zeros((n_entries, 5), np.int32)
371+
ctab = np.zeros((n_entries, 5), dt)
351372
for i in xrange(n_entries):
352373
# structure name length + string
353374
name_length = np.fromfile(fobj, dt, 1)[0]
354375
name = np.fromfile(fobj, "|S%d" % name_length, 1)[0]
355376
names.append(name)
356-
# RGBA
377+
# read RGBA for this entry
357378
ctab[i, :4] = np.fromfile(fobj, dt, 4)
358-
# generate the annotation value
359-
ctab[i, 4] = (ctab[i, 0] +
360-
ctab[i, 1] * (2 ** 8) +
361-
ctab[i, 2] * (2 ** 16) +
362-
ctab[i, 3] * (2 ** 24))
363379
# We've got a new-format .annot file
364380
else:
365381
# file version number
366382
ctab_version = -n_entries
367383
if ctab_version != 2:
368384
raise Exception('Color table version not supported')
369-
# maximum colour table index used
385+
# maximum LUT index present in the file
370386
max_index = np.fromfile(fobj, dt, 1)[0]
371-
ctab = np.zeros((max_index, 5), np.int32)
387+
ctab = np.zeros((max_index, 5), dt)
372388
# orig_tab string length + string
373389
length = np.fromfile(fobj, dt, 1)[0]
374390
np.fromfile(fobj, "|S%d" % length, 1)[0] # Orig table path
375-
# number of entries to read from the file
391+
# number of LUT entries present in the file
376392
entries_to_read = np.fromfile(fobj, dt, 1)[0]
377393
names = list()
378-
for i in xrange(entries_to_read):
394+
for _ in xrange(entries_to_read):
379395
# index of this entry
380396
idx = np.fromfile(fobj, dt, 1)[0]
381397
# structure name length + string
@@ -384,16 +400,13 @@ def read_annot(filepath, orig_ids=False):
384400
names.append(name)
385401
# RGBA
386402
ctab[idx, :4] = np.fromfile(fobj, dt, 4)
387-
ctab[idx, 4] = (ctab[idx, 0] +
388-
ctab[idx, 1] * (2 ** 8) +
389-
ctab[idx, 2] * (2 ** 16) +
390-
ctab[idx, 3] * (2 ** 24))
403+
404+
# generate annotation values for each LUT entry
405+
ctab[:, 4] = _pack_rgba(ctab[:, :4])
391406

392407
# make sure names are strings, not bytes
393408
names = [n.decode('ascii') for n in names]
394409

395-
labels = labels.astype(np.int32)
396-
397410
if not orig_ids:
398411
ord = np.argsort(ctab[:, -1])
399412
mask = labels != 0
@@ -437,13 +450,11 @@ def write_string(s):
437450

438451
# Generate annotation values for each ctab entry
439452
if fill_ctab:
440-
new_ctab = np.zeros((ctab.shape[0], 5), dtype=np.int32)
441-
new_ctab[:, :4] = ctab[:, :4]
442-
ctab = new_ctab
443-
ctab[:, 4] = (ctab[:, 0] +
444-
ctab[:, 1] * (2 ** 8) +
445-
ctab[:, 2] * (2 ** 16) +
446-
ctab[:, 3] * (2 ** 24))
453+
ctab = np.hstack((ctab[:, :4],
454+
_pack_rgba(ctab[:, :4]).reshape(-1, 1)))
455+
elif not np.array_equal(ctab[:, 4], _pack_rgba(ctab[:, :4])):
456+
warnings.warn('Annotation values in {} will be incorrect'.format(
457+
filepath))
447458

448459
# vtxct
449460
write(vnum)

0 commit comments

Comments
 (0)