@@ -73,6 +73,27 @@ def _read_volume_info(fobj):
73
73
return volume_info
74
74
75
75
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
+
76
97
def read_geometry (filepath , read_metadata = False , read_stamp = False ):
77
98
"""Read a triangular format Freesurfer surface mesh.
78
99
@@ -347,35 +368,30 @@ def read_annot(filepath, orig_ids=False):
347
368
orig_tab = np .fromfile (fobj , '>c' , length )
348
369
orig_tab = orig_tab [:- 1 ]
349
370
names = list ()
350
- ctab = np .zeros ((n_entries , 5 ), np . int32 )
371
+ ctab = np .zeros ((n_entries , 5 ), dt )
351
372
for i in xrange (n_entries ):
352
373
# structure name length + string
353
374
name_length = np .fromfile (fobj , dt , 1 )[0 ]
354
375
name = np .fromfile (fobj , "|S%d" % name_length , 1 )[0 ]
355
376
names .append (name )
356
- # RGBA
377
+ # read RGBA for this entry
357
378
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 ))
363
379
# We've got a new-format .annot file
364
380
else :
365
381
# file version number
366
382
ctab_version = - n_entries
367
383
if ctab_version != 2 :
368
384
raise Exception ('Color table version not supported' )
369
- # maximum colour table index used
385
+ # maximum LUT index present in the file
370
386
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 )
372
388
# orig_tab string length + string
373
389
length = np .fromfile (fobj , dt , 1 )[0 ]
374
390
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
376
392
entries_to_read = np .fromfile (fobj , dt , 1 )[0 ]
377
393
names = list ()
378
- for i in xrange (entries_to_read ):
394
+ for _ in xrange (entries_to_read ):
379
395
# index of this entry
380
396
idx = np .fromfile (fobj , dt , 1 )[0 ]
381
397
# structure name length + string
@@ -384,16 +400,13 @@ def read_annot(filepath, orig_ids=False):
384
400
names .append (name )
385
401
# RGBA
386
402
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 ])
391
406
392
407
# make sure names are strings, not bytes
393
408
names = [n .decode ('ascii' ) for n in names ]
394
409
395
- labels = labels .astype (np .int32 )
396
-
397
410
if not orig_ids :
398
411
ord = np .argsort (ctab [:, - 1 ])
399
412
mask = labels != 0
@@ -437,13 +450,11 @@ def write_string(s):
437
450
438
451
# Generate annotation values for each ctab entry
439
452
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 ))
447
458
448
459
# vtxct
449
460
write (vnum )
0 commit comments