@@ -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+
50116def _read_volume_info (fobj ):
51117 """Helper for reading the footer from a surface file."""
52118 volume_info = OrderedDict ()
0 commit comments