66import numpy as np
77import getpass
88import time
9+ from os .path import exists as pexists , realpath
910
1011from collections import OrderedDict
1112from six .moves import xrange
@@ -47,29 +48,41 @@ def _fread3_many(fobj, n):
4748 return (b1 << 16 ) + (b2 << 8 ) + b3
4849
4950
50- def read_aseg_stats (seg_stats_file , set = 'subcortical' , volumes_only = False ):
51+ def read_aseg_stats (seg_stats_file ,
52+ set_wanted = 'subcortical' ,
53+ volumes_only = False ):
5154 """
5255 Returns the subcortical stats found in Freesurfer output: subid/stats/aseg.stats
5356
5457 Tries to match the outputs returned by Freesurfer's Matlab counter part: load_segstats.m
5558
5659 Parameters
5760 ----------
58- filepath : str
61+ seg_stats_file : str
5962 Abs path to aseg.stats file.
6063
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' ]
64+ set_wanted : str
65+ Which set of volumes to return, among ['subcortical', 'wholebrain', 'etiv_only' ].
66+ Default: 'subcortical'.
67+ The choice 'subcortical' returns the usual subortical segmentations.
68+ The choice 'wholebrain' returns the volumes in aseg.stats coded as :
69+ [ 'BrainSegVol', 'BrainSegVolNotVent', 'lhCortexVol', 'rhCortexVol', 'lhCorticalWhiteMatterVol',
70+ 'rhCorticalWhiteMatterVol', 'SubCortGrayVol', 'TotalGrayVol', 'SupraTentorialVol',
71+ 'SupraTentorialVolNotVent', 'MaskVol', 'BrainSegVol-to-eTIV', 'MaskVol-to-eTIV',
72+ 'lhSurfaceHoles', 'rhSurfaceHoles', 'eTIV' ]
73+ These are noted as 'Measure' in the commented section of stats/aseg.stats file.
74+ The choice 'etiv_only' returns the value for eTIV (estimated total intra-cranial volume) only.
75+
76+ volumes_only : bool
77+ Flag to indicate only the volumes are wanted.
78+
79+ Default: False, returning all info available, to closely match the outputs returned by Freesurfer's Matlab counter part:
80+ https://github.com/freesurfer/freesurfer/blob/dev/matlab/load_segstats.m
7081
7182 Returns
7283 -------
84+ By default (volumes_only=False), three arrays are returned:
85+
7386 seg_name : numpy array of strings
7487 Array of segmentation names
7588 seg_index : numpy array
@@ -86,26 +99,32 @@ def read_aseg_stats(seg_stats_file, set ='subcortical', volumes_only = False):
8699 6. max intensity over space
87100 7. range intensity over space
88101
102+ When volumes_only=True, only one array is returned containing only volumes.
103+
89104 """
90105
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 ))
106+ seg_stats_file = realpath (seg_stats_file )
107+ if not pexists (seg_stats_file ):
108+ raise IOError ('given path does not exist : {}' .format (seg_stats_file ))
109+
110+ acceptable_choices = ['subcortical' , 'wholebrain' , 'etiv_only' ]
111+ set_wanted = set_wanted .lower ()
112+ if set_wanted not in acceptable_choices :
113+ raise ValueError ('Invalid choice. Choose one among: {}' .format (acceptable_choices ))
95114
96- if set in 'subcortical' :
115+ if set_wanted in 'subcortical' :
97116 stats = np .loadtxt (seg_stats_file , dtype = "i1,i1,i4,f4,S50,f4,f4,f4,f4,f4" )
98117 if volumes_only :
99118 out_data = np .array ([seg [3 ] for seg in stats ])
100119 else :
101120 # need to ensure both two types return data correspond in seg order
102121 out_data = stats
103122
104- elif set in [ 'wholebrain' , 'eTIV ' ]:
123+ elif set_wanted in ['wholebrain' , 'etiv_only ' ]:
105124 wb_regex_pattern = r'# Measure ([\w/+_\- ]+), ([\w/+_\- ]+), ([\w/+_\- ]+), ([\d\.]+), ([\w/+_\-^]+)'
106125 datatypes = np .dtype ('U100,U100,U100,f8,U10' )
107126 stats = np .fromregex (seg_stats_file , wb_regex_pattern , dtype = datatypes )
108- if set in ['eTIV ' ]:
127+ if set_wanted in ['etiv_only ' ]:
109128 out_data = np .array ([seg [3 ] for seg in stats if seg [1 ] == 'eTIV' ])
110129 else :
111130 out_data = np .array ([seg [3 ] for seg in stats ])
0 commit comments