@@ -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+
7697def 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