Skip to content

Commit 870bb1d

Browse files
committed
updating docs and improving implementation
1 parent 83b55a2 commit 870bb1d

File tree

1 file changed

+37
-18
lines changed

1 file changed

+37
-18
lines changed

nibabel/freesurfer/io.py

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import numpy as np
77
import getpass
88
import time
9+
from os.path import exists as pexists, realpath
910

1011
from collections import OrderedDict
1112
from 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

Comments
 (0)