Source code for graynet.freesurfer

from __future__ import print_function

__all__ = ['import_features', 'get_data']

from collections.abc import Iterable
from os.path import exists as pexists
from traceback import print_exc

import nibabel
import numpy as np

from graynet import config_graynet as cfg

_base_feature_list = ['thickness', 'curv', 'sulc', 'area',
                      'area.pial', 'jacobian_white']


[docs]def import_features(fs_dir, subject_list, base_feature='freesurfer_thickness', fwhm=10, atlas='fsaverage'): """Reads features after ensuring subjects are provided and their data exist.""" if isinstance(subject_list, Iterable): if len(subject_list) < 1: raise ValueError('Empty subject list.') subjects_list = subject_list elif isinstance(subject_list, str): if not pexists(subject_list): raise IOError("subject list path doesn't exist: {}".format(subject_list)) subjects_list = np.atleast_1d(np.genfromtxt(subject_list, dtype=str).astype(str)) else: raise ValueError('Invalid value provided for subject list.' '\n Must be a list of paths, or path to a file containing ' 'list of paths, one for each subject.') features = dict() for subj_id in subjects_list: try: print('Reading {} for {} ... '.format(base_feature, subj_id), end='') features[subj_id] = get_data(fs_dir, subj_id, base_feature, fwhm, atlas) print(' Done.') except: print_exc() raise ValueError('{} data for {} could not be read!' ''.format(base_feature, subj_id)) return features
[docs]def get_data(fs_dir, subject_id, base_feature, fwhm=10, atlas='fsaverage'): """Reads the specified features from both hemispheres for a given subject.""" feat_name = base_feature.lower() if feat_name in cfg.features_freesurfer: bare_name_feat = feat_name.replace('freesurfer_', '') left = __read_morph_feature( path_to_vertex_data(fs_dir, subject_id, hemi='lh', feature=bare_name_feat, atlas=atlas, fwhm=fwhm)) right = __read_morph_feature( path_to_vertex_data(fs_dir, subject_id, hemi='rh', feature=bare_name_feat, atlas=atlas, fwhm=fwhm)) whole = np.hstack((left, right)) else: raise ValueError('Invalid choice for freesurfer data.' ' Valid choices: {}'.format(cfg.features_freesurfer)) return whole
def __all_data_exists(fs_dir, subject_id, base_feature, fwhm=10, atlas='fsaverage'): """Ensures all data exists for a given subject""" if base_feature.lower() in _base_feature_list: data_exists = True for hemi in ['lh', 'rh']: if not pexists(path_to_vertex_data(fs_dir, subject_id, feature=base_feature, hemi=hemi, atlas=atlas, fwhm=fwhm)): return False else: raise ValueError('Invalid choice for freesurfer data. ' 'Valid choices: {}'.format(_base_feature_list)) return data_exists def path_to_vertex_data(fsd, sid, hemi='lh', fwhm=10, atlas='fsaverage', feature='thickness'): """Returning the path to surface features. Using a smoothed version""" return fsd / sid / 'surf' / '{}.{}.fwhm{}.{}.mgh'.format(hemi, feature, fwhm, atlas) def __read_morph_feature(thk_path): """Assumes mgh format: lh.thickness.fwhm10.fsaverage.mgh""" vec = nibabel.load(thk_path).get_fdata() #typically of shape: (163842, 1, 1) return np.squeeze(vec) # becomes (163842, )