Skip to content

Commit e06ed5e

Browse files
committed
first implementation of aseg stats reader
1 parent 9b23a32 commit e06ed5e

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

nibabel/freesurfer/io.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,72 @@ def _fread3_many(fobj, n):
4747
return (b1 << 16) + (b2 << 8) + b3
4848

4949

50+
def read_aseg_stats(seg_stats_file, set ='subcortical', volumes_only = False):
51+
"""
52+
Returns the subcortical stats found in Freesurfer output: subid/stats/aseg.stats
53+
54+
Tries to match the outputs returned by Freesurfer's Matlab counter part: load_segstats.m
55+
56+
Parameters
57+
----------
58+
filepath : str
59+
Abs path to aseg.stats file.
60+
61+
set : str
62+
Which set of volumes to return, among ['subcortical', 'wholebrain']. Default: 'subcortical'.
63+
The choice 'subcortical' returns the usual subortical segmentations.
64+
The choice 'wholebrain' returns only volumes (only stat available),
65+
whose segmentations include [ 'BrainSegVol', 'BrainSegVolNotVent',
66+
'lhCortexVol', 'rhCortexVol', 'lhCorticalWhiteMatterVol', 'rhCorticalWhiteMatterVol',
67+
'SubCortGrayVol', 'TotalGrayVol', 'SupraTentorialVol', 'SupraTentorialVolNotVent',
68+
'MaskVol', 'BrainSegVol-to-eTIV', 'MaskVol-to-eTIV', 'lhSurfaceHoles', 'rhSurfaceHoles',
69+
'eTIV' ]
70+
71+
Returns
72+
-------
73+
seg_name : numpy array of strings
74+
Array of segmentation names
75+
seg_index : numpy array
76+
Array of indices of segmentations into the Freesurfer color lookup table.
77+
seg_stats : numpy array
78+
Matrix of subcortical statistics, with the following 5 columns by default.
79+
If volumes_only = True, only the volumes in mm^3 are returned.
80+
Columns in the full output are:
81+
1. number of voxels
82+
2. volume of voxels (mm^3) -- same as number but scaled by voxvol
83+
3. mean intensity over space
84+
4. std intensity over space
85+
5. min intensity over space
86+
6. max intensity over space
87+
7. range intensity over space
88+
89+
"""
90+
91+
acceptable_choices = ['subcortical', 'wholebrain', 'eTIV']
92+
set = set.lower()
93+
if set not in acceptable_choices:
94+
raise ValueError('invalid choice. Choose one among: {}'.format(acceptable_choices))
95+
96+
if set in 'subcortical':
97+
stats = np.loadtxt(seg_stats_file, dtype="i1,i1,i4,f4,S50,f4,f4,f4,f4,f4")
98+
if volumes_only:
99+
out_data = np.array([seg[3] for seg in stats])
100+
else:
101+
# need to ensure both two types return data correspond in seg order
102+
out_data = stats
103+
104+
elif set in [ 'wholebrain', 'eTIV']:
105+
wb_regex_pattern = r'# Measure ([\w/+_\- ]+), ([\w/+_\- ]+), ([\w/+_\- ]+), ([\d\.]+), ([\w/+_\-^]+)'
106+
datatypes = np.dtype('U100,U100,U100,f8,U10')
107+
stats = np.fromregex(seg_stats_file, wb_regex_pattern, dtype=datatypes)
108+
if set in ['eTIV']:
109+
out_data = np.array([seg[3] for seg in stats if seg[1] == 'eTIV'])
110+
else:
111+
out_data = np.array([seg[3] for seg in stats])
112+
113+
return out_data
114+
115+
50116
def _read_volume_info(fobj):
51117
"""Helper for reading the footer from a surface file."""
52118
volume_info = OrderedDict()

0 commit comments

Comments
 (0)