def create_R2(in_vol, in_rh_surf, in_lh_surf): img = nib.load(in_vol) data = img.get_fdata() # set all visual areas 1 through 12 to 1.0 for i in range(data.shape[0]): for j in range(data.shape[1]): for k in range(data.shape[2]): if data[i,j,k] > 0.0: data[i,j,k] = 1.0 out_vol = nib.Nifti1Image(data, img.affine) nib.save(out_vol, os.path.join(os.getcwd(),'prf','r2.nii.gz')) data = fsio.read_morph_data(in_rh_surf) for i in range(data.shape[0]): if data[i] > 0.0: data[i] = 1.0 fsio.write_morph_data(os.path.join(os.getcwd(),'prf','prf_surfaces','rh.r2'),data) data = fsio.read_morph_data(in_lh_surf) for i in range(data.shape[0]): if data[i] > 0.0: data[i] = 1.0 fsio.write_morph_data(os.path.join(os.getcwd(),'prf','prf_surfaces','lh.r2'),data)
def get_native_cortical_data(subject_dir, data_type): if FS_dir_structure: lh_cortical_data = read_morph_data(subject_dir + '/surf/lh.' + data_type) rh_cortical_data = read_morph_data(subject_dir + '/surf/rh.' + data_type) else: lh_cortical_data = read_morph_data(subject_dir + '/lh.' + data_type) rh_cortical_data = read_morph_data(subject_dir + '/rh.' + data_type) return lh_cortical_data, rh_cortical_data
def morph2dense(source_sphere,target_sphere,input_morph,path_output): """ This function maps a morphological file from a source surface to a target target surface. Inputs: *source_sphere: source surface. *target_sphere: target surface. *input_morph: morphological input file. *path_output: path where output is saved. created by Daniel Haenelt Date created: 13-07-2019 Last modified: 13-07-2019 """ import os from nibabel.freesurfer.io import read_morph_data, write_morph_data, read_geometry from scipy.interpolate import griddata # make output folder if not os.path.exists(path_output): os.mkdir(path_output) # transform morphological data to dense surfaces pts_sphere_dense, _ = read_geometry(target_sphere) pts_sphere, _ = read_geometry(source_sphere) # get morphological data morph = read_morph_data(input_morph) # do the transformation method = "nearest" morph_dense = griddata(pts_sphere, morph, pts_sphere_dense, method) # write dense morphological data write_morph_data(os.path.join(path_output,os.path.basename(input_morph)), morph_dense)
def _guess_surf_file(fl): # MGH/MGZ files try: return fsmgh.load(fl).get_data().flatten() except: pass # FreeSurfer Curv files try: return fsio.read_morph_data(fl) except: pass # Nifti files try: return np.squeeze(nib.load(fl).get_data()) except: raise ValueError('Could not determine filetype for: %s' % fl)
def fs_to_dae( args ): #load in FS mesh verts,faces = fsio.read_geometry( args.input ) #dumb copypasta for mesh face normals norms = np.zeros( verts.shape, dtype=verts.dtype ) tris = verts[faces] n = np.cross( tris[::,1 ] - tris[::,0] , tris[::,2 ] - tris[::,0] ) norm_sizes = np.sqrt(n[:,0]**2 + n[:,1]**2 + n[:,2]**2) for i in range(3): n[:,i] = n[:,i] / norm_sizes del norm_sizes #map back to vertices norms[ faces[:,0] ] += n norms[ faces[:,1] ] += n norms[ faces[:,2] ] += n del n norm_sizes = np.sqrt(norms[:,0]**2 + norms[:,1]**2 + norms[:,2]**2) for i in range(3): norms[:,i] = norms[:,i] / norm_sizes #color if not args.color: color = np.ones(norms.shape) * 0.4 else: scalars = fsio.read_morph_data(args.color) color = color_func(scalars) #make trimesh mesh = trimesh.Trimesh(\ verts,\ faces,\ vertex_normals=norms,\ vertex_colors=color) mesh.export(file_obj=args.output, file_type="collada") #mesh.export(file_obj=args.output, file_type="obj") #mesh.export_gltf(file_obj=args.output) return
def read_surface(filename): extension = filename.split('.')[-1] if extension == 'mha': img = sitk.ReadImage(filename) return sitk.GetArrayFromImage(img) elif extension == 'annot': raise ValueError('Reader for extensions \'annot\' not yet implemented') elif extension == 'label': raise ValueError('Reader for extensions \'label\' not yet implemented') elif extension in ['inflated', 'pial', 'white']: coords, faces = io.read_geometry(filename) return coords, faces else: return io.read_morph_data(filename)
# %% import datasets centers = datasets.load_centers_all() features = [] for center in centers: persons = center.get_by_label(2) f = center.get_cortical_thickness(persons) features.append(f) # %% from nibabel.freesurfer.io import read_morph_data from nilearn.surface import load_surf_data p = r'E:\workspace\AD_meta\data\AD\ADNI\003\surf\rh.thickness.003_S_0907_NC_ADNI1_screening' a = read_morph_data(p) pg = r'E:\workspace\AD_meta\data\AD\EDSD\FRE\surf\lh.sphere.FRE_MCI001.gii' b = load_surf_data(pg) # %% import datasets import os centers = datasets.load_centers_all() for center in centers: surf_dir = center.file_dir + '\surf' files = os.listdir(surf_dir) for f in files: if 'lh.thickness' in f: a = read_morph_data(os.path.join(surf_dir, f)) print(a.shape)
def _guess_surf_file(fl): if len(fl) > 4 and (fl[-4:] == '.mgz' or fl[-4:] == '.mgh'): return np.squeeze(np.array(fsmgh.load(fl).dataobj)) else: return fsio.read_morph_data(fl)
def load_freesurfer_morph(filename): ''' load_freesurfer_morph(filename) yields the result of loading the given filename as FreeSurfer morph-data (e.g., lh.curv). ''' return fsio.read_morph_data(filename)
def _load_fn(): p = fsio.read_morph_data(flnm) p.setflags(write=False) return p
class Subject(mri.Subject): ''' A neuropythy.freesurfer.Subject is an instance of neuropythy.mri.Subject that depends only on the path of the subject represented; all other data are automatically derived from this. ''' def __init__(self, path, meta_data=None, check_path=True): if check_path and not is_freesurfer_subject_path(path): raise ValueError('given path does not appear to hold a freesurfer subject') # get the name... path = os.path.abspath(path) name = os.path.split(path)[-1] self.name = name self.path = path self.meta_data = meta_data self.hemis = Subject.load_hemis(name, path) self.images = Subject.load_images(name, path) # these are the only actually required data for the constructor; the rest is values # This [private] function and this variable set up automatic properties from the FS directory # in order to be auto-loaded, a property must appear in this dictionary: _auto_retino_names = pyr.pmap({ (tag + sep + name): (ptag + pname) for (tag,ptag) in [('', ''), ('rf', 'rf_' ), ('prf', 'prf_' ), ('meas', 'measured_' ), ('measured', 'measured_' ), ('emp', 'empirical_' ), ('empirical', 'empirical_' ), ('trn', 'training_' ), ('train', 'training_' ), ('training', 'training_' ), ('val', 'validation_'), ('valid', 'validation_'), ('validation', 'validation_'), ('test', 'validation_'), ('gold', 'gold_' ), ('retinotopy', '' ), ('retino', '' ), ('predict', 'predicted_' ), ('pred', 'predicted_' ), ('model', 'model_' ), ('mdl', 'model_' ), ('inferred', 'inferred_' ), ('bayes', 'inferred_' ), ('inf', 'inferred_' ), ('benson14', 'benson14_' ), ('benson17', 'benson17_' ), ('atlas', 'atlas_' ), ('template', 'template_' )] for sep in (['_', '.', '-'] if len(tag) > 0 else ['']) for (name, pname) in [ ('eccen', 'eccentricity' ), ('angle', 'polar_angle' ), ('theta', 'theta' ), ('rho', 'rho' ), ('prfsz', 'size' ), ('size', 'size' ), ('radius', 'radius' ), ('sigma', 'sigma' ), ('varex', 'variance_explained'), ('vexpl', 'variance_explained'), ('varexp', 'variance_explained'), ('weight', 'weight' ), ('varea', 'visual_area' ), ('vsroi', 'visual_area' ), ('vroi', 'visual_area' ), ('vslab', 'visual_area' )]}) _auto_properties = pyr.pmap({k: (a, lambda f: fsio.read_morph_data(f)) for d in [{'sulc': 'convexity', 'thickness': 'thickness', 'volume': 'volume', 'area': 'white_surface_area', 'area.mid': 'midgray_surface_area', 'area.pial': 'pial_surface_area', 'curv': 'curvature'}, _auto_retino_names] for (k,a) in six.iteritems(d)}) @staticmethod def _cortex_from_path(subid, chirality, name, surf_path, data_path, data_prefix=Ellipsis): ''' Subject._cortex_from_path(subid, chirality, name, spath, dpath) yields a Cortex object that has been loaded from the given path. The given spath should be the path from which to load the structural information (like lh.sphere and rh.white) while the dpath is the path from which to load the non-structural information (like lh.thickness or rh.curv). ''' # data prefix is ellipsis when we use the same as the chirality; unless the name ends with # X, in which case, it's considered a reversed-hemisphere chirality = chirality.lower() if data_prefix is Ellipsis: if name.lower().endswith('x'): data_prefix = 'rh' if chirality == 'lh' else 'lh' else: data_prefix = chirality # we can start by making a lazy-map of the auto-properties def _make_prop_loader(flnm): def _load_fn(): p = fsio.read_morph_data(flnm) p.setflags(write=False) return p return _load_fn def _make_mghprop_loader(flnm): def _load_fn(): p = fsmgh.load(flnm).get_data().flatten() p.setflags(write=False) return p return _load_fn props = {} for (k,(a,_)) in six.iteritems(Subject._auto_properties): f = os.path.join(data_path, data_prefix + '.' + k) if os.path.isfile(f): props[a] = _make_prop_loader(f) # That takes care of the defauly properties; now look for auto-retino properties for flnm in os.listdir(data_path): if flnm[0] == '.' or not flnm.startswith(data_prefix + '.'): continue if flnm.endswith('.mgz') or flnm.endswith('.mgh'): mid = flnm[3:-4] loader = _make_mghprop_loader else: mid = flnm[3:] loader = _make_prop_loader if mid in Subject._auto_retino_names: tr = Subject._auto_retino_names[mid] props[tr] = loader(os.path.join(data_path, flnm)) props = pimms.lazy_map(props) # we need a tesselation in order to make the surfaces or the cortex object white_surf_name = os.path.join(surf_path, chirality + '.white') # We need the tesselation at instantiation-time, so we can load it now tess = geo.Tesselation(fsio.read_geometry(white_surf_name)[1], properties=props) # start by creating the surface file names def _make_surf_loader(flnm): def _load_fn(): x = fsio.read_geometry(flnm)[0].T x.setflags(write=False) return x return _load_fn surfs = {} for s in ['white', 'pial', 'inflated', 'sphere']: surfs[s] = _make_surf_loader(os.path.join(surf_path, chirality + '.' + s)) surfs = pimms.lazy_map(surfs) # okay, now we can do the same for the relevant registrations; since the sphere registration # is the same as the sphere surface, we can just copy that one over: regs = {'native': lambda:surfs['sphere']} # see if our subject id has special neuropythy datafiles... surf_paths = [surf_path] extra_path = os.path.join(library_path(), 'data', subid, 'surf') if os.path.isdir(extra_path): surf_paths.insert(0, extra_path) for surf_path in surf_paths: for flnm in os.listdir(surf_path): if flnm.startswith(chirality + '.') and flnm.endswith('.sphere.reg'): mid = flnm[(len(chirality)+1):-11] if mid == '': mid = 'fsaverage' regs[mid] = _make_surf_loader(os.path.join(surf_path, flnm)) regs = pimms.lazy_map(regs) # great; now we can actually create the cortex object itself return mri.Cortex(chirality, tess, surfs, regs).persist() @staticmethod def load_hemis(name, path): ''' Subject.load_hemis(name, path) yields a persistent map of hemisphere names ('lh', 'rh', possibly others) for the given freesurfer subject sub. Other hemispheres may include lhx and rhx (mirror-inverted hemisphere objects). ''' surf_path = os.path.join(path, 'surf') # basically, we want to create a lh and rh hemisphere object with automatically-loaded # properties based on the above auto-property data ctcs = {} for h in ['lh', 'rh']: ctcs[h] = Subject._cortex_from_path(name, h, h, surf_path, surf_path) # we also want to check for the xhemi subject xpath = os.path.join(path, 'xhemi', 'surf') if os.path.isdir(xpath): for (h,xh) in zip(['lh', 'rh'], ['rhx', 'lhx']): ctcs[xh] = Subject._cortex_from_path(name, h, xh, xpath, surf_path) # that's all! return pimms.lazy_map(ctcs) @staticmethod def load_mgh_images(name, path): ''' Subject.load_mgh_images(name, path) yields a persistent map of the MGHImage objects for all the valid mgz files in the relevant subject's FreeSurfer mri/ directory (where the subject directory is given by path). ''' # These are just given their basic filenames; nothing fancy here path = os.path.join(path, 'mri') fls = [f for p in [path, os.path.join(path, 'orig')] if os.path.isdir(p) for fname in os.listdir(p) for f in [os.path.join(p, fname)] if f[0] != '.' if len(f) > 4 and f[-4:].lower() in ['.mgz', '.mgh'] if os.path.isfile(f)] def _make_loader(fname): def _loader(): return _load_imm_mgh(fname) return _loader return pimms.lazy_map({os.path.split(flnm)[-1][:-4]: _make_loader(flnm) for flnm in fls}) @staticmethod def load_images(name, path): ''' Subject.load_images(name, path) yields a persistent map of MRImages tracked by the given subject sub; in freesurfer subjects these are renamed and converted from their typical freesurfer filenames (such as 'ribbon') to forms that conform to the neuropythy naming conventions (such as 'gray_mask'). To access data by their original names, use the Subject.load_mgh_images() function. ''' ims = {} mgh_images = Subject.load_mgh_images(name, path) def _make_imm_mask(arr, val, eq=True): arr = (arr == val) if eq else (arr != val) arr.setflags(write=False) return fsmgh.MGHImage(arr, mgh_images['ribbon'].affine, mgh_images['ribbon'].header) # start with the ribbon: ims['lh_gray_mask'] = lambda:_make_imm_mask(mgh_images['ribbon'].get_data(), 3) ims['lh_white_mask'] = lambda:_make_imm_mask(mgh_images['ribbon'].get_data(), 2) ims['rh_gray_mask'] = lambda:_make_imm_mask(mgh_images['ribbon'].get_data(), 42) ims['rh_white_mask'] = lambda:_make_imm_mask(mgh_images['ribbon'].get_data(), 41) ims['brain_mask'] = lambda:_make_imm_mask(mgh_images['ribbon'].get_data(), 0, False) # next, do the standard ones: def _make_accessor(nm): return lambda:mgh_images[nm] for (tname, name) in zip(['original', 'normalized', 'segmentation', 'brain'], ['orig', 'norm', 'aseg', 'brain']): ims[tname] = _make_accessor(name) # last, check for auto-retino-properties: for k in six.iterkeys(mgh_images): if k in Subject._auto_retino_names: tr = Subject._auto_retino_names[k] ims[tr] = _make_accessor(k) return pimms.lazy_map(ims) @pimms.value def mgh_images(name, path): ''' sub.mgh_images is a persistent map of MRImages, represented as MGHImage objects, tracked by the given FreeSurfer subject sub. ''' return Subject.load_mgh_images(name, path) @pimms.value def voxel_to_vertex_matrix(mgh_images): ''' See neuropythy.mri.Subject.voxel_to_vertex_matrix. ''' return pimms.imm_array(mgh_images['ribbon'].header.get_vox2ras_tkr()) @pimms.value def voxel_to_native_matrix(mgh_images): ''' See neuropythy.mri.Subject.voxel_to_native_matrix. ''' return pimms.imm_array(mgh_images['ribbon'].header.get_affine())
def fs_to_dae(args): #load in FS mesh verts, faces = fsio.read_geometry(args.input) #dumb copypasta for mesh face normals norms = np.zeros(verts.shape, dtype=verts.dtype) tris = verts[faces] n = np.cross(tris[::, 1] - tris[::, 0], tris[::, 2] - tris[::, 0]) norm_sizes = np.sqrt(n[:, 0]**2 + n[:, 1]**2 + n[:, 2]**2) for i in range(3): n[:, i] = n[:, i] / norm_sizes del norm_sizes #map back to vertices norms[faces[:, 0]] += n norms[faces[:, 1]] += n norms[faces[:, 2]] += n del n norm_sizes = np.sqrt(norms[:, 0]**2 + norms[:, 1]**2 + norms[:, 2]**2) for i in range(3): norms[:, i] = norms[:, i] / norm_sizes # # collada section # #color if not args.color: #color = np.ones((norms.shape[0],4)) color = np.random.uniform(size=norms.shape) else: scalars = fsio.read_morph_data(args.color) color = color_func(scalars) #color = np.ones((norms.shape[0],3)) * #create collada obj mesh = collada.Collada() #add shading effect = collada.material.Effect("effect0",\ [], #TEXTURES GO HERE "phong", diffuse=(1,1,1), specular=(1,1,1), double_sided=True) mat = collada.material.Material("material0", "mymaterial", effect) mesh.effects.append(effect) mesh.materials.append(mat) vert_src = collada.source.FloatSource("cubeverts-array", verts, ('X', 'Y', 'Z')) #norm_src = collada.source.FloatSource("cubenormals-array", np.array(norms), ('X', 'Y', 'Z')) color_src = collada.source.FloatSource("cubecolors-array", np.array(color), ('R', 'G', 'B')) geom = collada.geometry.Geometry(mesh, "geometry0", "fsave_test",\ [vert_src,color_src]) #creates list of inputs for collada DOM obj...so many decorators input_list = collada.source.InputList() input_list.addInput(0, 'VERTEX', "#cubeverts-array") input_list.addInput(1, 'COLOR', "#cubecolors-array") #input_list.addInput(2, 'NORMAL', "#cubenormals-array") #creates faces triset = geom.createTriangleSet( np.concatenate([faces,faces],axis=1),\ input_list, "materialref") triset.generateNormals() geom.primitives.append(triset) mesh.geometries.append(geom) #creates scene node, which causes display matnode = collada.scene.MaterialNode("materialref", mat, inputs=[]) geomnode = collada.scene.GeometryNode(geom, [matnode]) node = collada.scene.Node("node0", children=[geomnode]) #create scene myscene = collada.scene.Scene("fs_base_scene", [node]) mesh.scenes.append(myscene) mesh.scene = myscene mesh.write(args.output) return
def map2grid(file_grid, file_input, sigma, path_output="", basename_output="", binary=False, overwrite=True): """ This script allows you to sample indexed morphological data onto the regular grid. Optional, a gaussian filter can be applied to the output image. Inputs: *file_grid: filename of grid coordinate mapping. *file_input: filename of morphological data or *.mgh data. *sigma: standard deviation of Gaussian kernel. *path_output: path where output is saved. *basename_output: basename of written output file. *binary: threshold output grid (for curvature file). *overwrite: write output to file. Output: *grid_array: file mapped onto array. created by Daniel Haenelt Date created: 01-11-2018 Last modified: 22-04-2020 """ import os import numpy as np import nibabel as nb from nibabel.freesurfer.io import read_morph_data from scipy.ndimage.filters import gaussian_filter # load data grid_img = nb.load(file_grid) grid_array = grid_img.get_fdata() if os.path.splitext(file_input)[1] == ".mgh": morph = nb.load(file_input).get_fdata() else: morph = read_morph_data(file_input) # sample data onto grid for i in range(np.size(grid_array, 0)): for j in range(np.size(grid_array, 1)): if grid_array[i, j] != 0: grid_array[i, j] = morph[grid_array[i, j].astype(int)] # gaussian filter (opt) if sigma != 0: order = 0 mode = "reflect" truncate = 4.0 grid_array = gaussian_filter(grid_array, sigma=sigma, order=order, mode=mode, truncate=truncate) # binary mode (opt) if binary is True: grid_array[grid_array > 0] = 1 grid_array[grid_array != 1] = -1 # write output data if overwrite: # make output folder if not os.path.exists(path_output): os.mkdir(path_output) if sigma == 0 and binary is True: filenameOUT = os.path.join(path_output, basename_output + "_grid_binary.nii") elif sigma == 0 and binary is False: filenameOUT = os.path.join(path_output, basename_output + "_grid.nii") elif sigma != 0 and binary is True: filenameOUT = os.path.join( path_output, basename_output + "_sigma" + str(sigma) + "_grid_binary.nii") else: filenameOUT = os.path.join( path_output, basename_output + "_sigma" + str(sigma) + "_grid.nii") output = nb.Nifti1Image(grid_array, grid_img.affine, grid_img.header) nb.save(output, filenameOUT) return grid_array
numverts_orig = fsio.read_geometry((Path(fsdir)/'surf'/f'{hemi}.inflated').str)[0].shape[0] # note the 0 inde problem here, here might not be correct validix = transfertodense(subjectid, np.arange(numverts_orig), hemi,'nearest','inflated') savepkl((fsdi/'surf'/f'{hemi}.DENSE.pkl').str,{'validix':validix}) ######### transfer thickness, curvature, and sulc values from standard to dense for hemi in hemis: # load a1 = loadpkl((Path(dir0)/f'{hemi}midgray.pkl').str) a2 = loadpkl((Path(fsdir)/'surf'/f'{hemi}.DENSETRUNC{fstruncate}.pkl').str) # read sulc data a3 = fsio.read_morph_data((Path(fsdir)/'surf'/f'{hemi}.sulc').str) # transfer values thickness = transfertodense(subjectid, a1['thickness'], hemi,'nearest') curvature = transfertodense(subjectid, a1['curvature'],hemi,'nearest') sulc = transfertodense(subjectid, a3, hemi,'nearest') # save(sprintf('%s/%smidgrayDENSE.pkl',dir0,hemi),'thickness','curvature') # write mgz writemgz(subjectid,'thicknessDENSE',thickness, hemi) writemgz(subjectid,'curvatureDENSE',curvature, hemi) writemgz(subjectid,'sulcDENSE', sulc, hemi) # write mgz for truncated writemgz(subjectid,f'thicknessDENSETRUNC{fstruncate}',thickness[a2['validix']],hemi) writemgz(subjectid,f'curvatureDENSETRUNC{fstruncate}',curvature[a2['validix']],hemi)
#!/usr/bin/env python import numpy as np import nibabel as nib import nibabel.freesurfer.io as fsio import scipy.io as sio rh_eccentricity = fsio.read_morph_data('./prf/prf_surfaces/rh.eccentricity') rh_rfWidth = fsio.read_morph_data('./prf/prf_surfaces/rh.rfWidth') rh_polarAngle = fsio.read_morph_data('./prf/prf_surfaces/rh.polarAngle') rh_varea = fsio.read_morph_data('./prf/prf_surfaces/rh.varea') rh_r2 = fsio.read_morph_data('./prf/prf_surfaces/rh.r2') lh_eccentricity = fsio.read_morph_data('./prf/prf_surfaces/lh.eccentricity') lh_rfWidth = fsio.read_morph_data('./prf/prf_surfaces/lh.rfWidth') lh_polarAngle = fsio.read_morph_data('./prf/prf_surfaces/lh.polarAngle') lh_varea = fsio.read_morph_data('./prf/prf_surfaces/lh.varea') lh_r2 = fsio.read_morph_data('./prf/prf_surfaces/lh.r2') prf_surfs = { 'rh_eccentricity': rh_eccentricity, 'rh_rfWidth': rh_rfWidth, 'rh_polarAngle': rh_polarAngle, 'rh_varea': rh_varea, 'rh_r2': rh_r2, 'lh_eccentricity': lh_eccentricity, 'lh_rfWidth': lh_rfWidth, 'lh_polarAngle': lh_polarAngle, 'lh_varea': lh_varea, 'lh_r2': lh_r2 }
corr_y_label = "t-score (session 4)" # parameters frac = 0.25 niter = 1000 """ do not edit below """ # load data label = read_label(input_label).tolist() # if input file extension is not *.mgh, interprete as morphological file if os.path.splitext(os.path.basename(input_sess1))[1] == ".mgh": sess1 = np.squeeze(nb.load(input_sess1).get_fdata()) else: sess1 = np.squeeze(read_morph_data(input_sess1)) # if input file extension is not *.mgh, interprete as morphological file if os.path.splitext(os.path.basename(input_sess2))[1] == ".mgh": sess2 = np.squeeze(nb.load(input_sess2).get_fdata()) else: sess2 = np.squeeze(read_morph_data(input_sess2)) # get the amount of data points ndata = np.round(frac * len(label)).astype(int) # randomly select ndata points in sess1 and sess2 label_shuffled = random.sample(label, len(label)) label_shuffled = label_shuffled[0:ndata] # get correlation between sessions
def runfreesurfer2(subjectid,extraflags=''): ''' def runfreesurfer2(subjectid,extraflags): <subjectid> is like 'C0001' <extraflags> (optional) is a string with extra flags to pass to recon-all. Default: '' This is part 2/2 for pushing anatomical data through FreeSurfer. see code for assumptions. ''' from RZutilpy.cvnpy import cvnpath, writemgz, fstoint from RZutilpy.system import makedirs,Path from RZutilpy.rzio import savepkl, loadpkl import nibabel.freesurfer.io as fsio import nibabel as nib import re from numpy import stack from sklearn.neighbors import NearestNeighbors # calc dir0 = (Path(cvnpath('anatomicals')) / subjectid).str fsdir = (Path(cvnpath('freesurfer')) / subjectid).str # make subject anatomical directory makedirs(dir0) # convert some miscellaneous files # convert .thickness files to ASCII # no need for python since nibabel can directly read the file # unix_wrapper('mris_convert -c {0}/surf/lh.thickness {0}/surf/lh.white {0}/surf/lh.thickness.asc'.format(str(fsdir))) # unix_wrapper('mris_convert -c {0}/surf/rh.thickness {0}/surf/rh.white {0}/surf/rh.thickness.asc'.format(str(fsdir))) # # convert .curv files to ASCII # unix_wrapper('mris_convert -c {0}/surf/lh.curv {0}/surf/lh.white {0}/surf/lh.curv.asc'.format(str(fsdir))) # unix_wrapper('mris_convert -c {0}/surf/rh.curv {0}/surf/rh.white {0}/surf/rh.curv.asc'.format(str(fsdir))) #### make mid-gray surface unix_wrapper('mris_expand -thickness {0}/surf/lh.white 0.5 {0}/surf/lh.graymid'.format(fsdir)) unix_wrapper('mris_expand -thickness {0}/surf/rh.white 0.5 {0}/surf/rh.graymid'.format(fsdir)) #### consolidate mid-gray surface stuff into a .mat file for hemi in ['lh' 'rh']: # read .graymid surface vertices,faces = fsio.read_geometry((Path(fsdir) / 'surf'/ f'{hemi}.graymid').str) # construct vertices (4 x V), becareful here, numpy and matlab index might be different!!! vertices = vertices.T + np.array([128, 129, 128]).reshape(-1,1) vertices = np.vstack((vertices, np.ones(vertices.shape[1]).reshape(1,-1))) # construct faces (F x 3) faces = faces[:,[0, 2, 1]] # necessary to convert freesurfer to matlab # load auxiliary info (V x 1) thickness = fsio.read_morph_data((Path(fsdir) / 'surf' / f'{hemi}.thickness').str) curvature = fsio.read_morph_data((Path(fsdir) / 'surf' / f'{hemi}.curv').str) # get freesurfer labels (fslabels is V x 1) fslabels, _, _ = fsio.read_annot((Path(fsdir) / 'label' / f'{hemi}.aparc.annot').str) # save savepkl((Path(cvnpath('anatomicals')) / subjectid / f'{hemi}midgray.pkl'.format(hemi)).str, {'vertices':vertices, 'faces':faces, 'thickness':thickness, \ 'curvature':curvature, 'fslabels': fslabels}) #### calculate gray-matter information if isempty(regexp(extraflags,'hires')): # load ribbon ribmgz = nib.load((Path(fsdir)/ 'mri' / 'ribbon.mgz').str) rib = fstoint(ribmgz.get_data()) # load coordinates of surface vertices coord0 = stack(\ (loadpkl(Path((cvnpath('anatomicals')) / subjectid / 'lhmidgray.mat').str)['vertices'],\ loadpkl((Path(cvnpath('anatomicals')) / subjectid / 'rhmidgray.mat').str)['vertices']),\ axis=1) #### use nearestNeighour, need to double check this nbrs = NearestNeighbors(1, metric='l2') nbrs.fit(coord0.T) dist, mnix = nbrs.kneighbors(rib, 1) # do I need to reshape dist and mnix? # compute distances to vertices [i.e. create a volume where gray matter voxels have certain informative values] #[dist,mnix] = surfaceslice2(ismember(rib,[3 42]),coord0, 3, 4) # NOTICE HARD-CODED VALUES HERE #### # save # 1-mm volume with, for each gray matter voxel, distance to closest vertex (of mid-gray surface) nib.save(inttofs(dist), (Path(fsdir) / 'mri'/ 'ribbonsurfdist.mgz').str, ribmgz) # 1-mm volume with, for each gray matter voxel, index of closest vertex (of mid-gray surface) nib.save(inttofs(mnix),(Path(fsdir) / 'mri'/ 'ribbonsurfindex.mgz').str, ribmgz) #### calculate transfer functions # calc [tfunFSSSlh,tfunFSSSrh,tfunSSFSlh,tfunSSFSrh] = \ calctransferfunctions((Path(cvnpath('freesurfer')).joinpath('fsaverage', 'surf','lh.sphere.reg')).str, \ (Path(cvnpath('freesurfer')).joinpath('fsaverage', 'surf','rh.sphere.reg')).str, \ (Path(cvnpath('freesurfer')).joinpath(subjectid, 'surf','lh.sphere.reg')).str, \ (Path(cvnpath('freesurfer')).joinpath(subjectid, 'surf','rh.sphere.reg')).str) # save savepkl((Path(cvnpath('anatomicals')) / subjectid /'tfun.mat').str,\ {'tfunFSSSlh': tfunFSSSlh,\ 'tfunFSSSrh': tfunFSSSrh,\ 'tfunSSFSlh': tfunSSFSlh\ 'tfunSSFSrh': tfunSSFSrh})
def read_surf_file(flnm): if flnm.endswith(".mgh") or flnm.endswith(".mgz"): data = fsmgh.load(flnm).get_data().flatten() else: data = fsio.read_morph_data(flnm) return data