def build_coord_list(coords, dwi_dir): from nilearn import masking try: import cPickle as pickle except ImportError: import _pickle as pickle nodif_brain_mask_path = "%s%s" % (dwi_dir, '/nodif_brain_mask.nii.gz') x_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[0] y_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[1] z_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[2] def mmToVox(mmcoords): voxcoords = ['', '', ''] voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45) voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63) voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36) return voxcoords # Convert coords back to voxels coords_vox = [] for coord in coords: coords_vox.append(mmToVox(coord)) coords = list(tuple(x) for x in coords_vox) coord_num = len(coords) return coords, coord_num
def coord_masker(mask, coords, label_names, error): from nilearn import masking x_vox = np.diagonal(masking._load_mask_img(mask)[1][:3, 0:3])[0] y_vox = np.diagonal(masking._load_mask_img(mask)[1][:3, 0:3])[1] z_vox = np.diagonal(masking._load_mask_img(mask)[1][:3, 0:3])[2] def mmToVox(mmcoords): voxcoords = ['', '', ''] voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45) voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63) voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36) return voxcoords mask_data, _ = masking._load_mask_img(mask) # mask_coords = list(zip(*np.where(mask_data == True))) coords_vox = [] for i in coords: coords_vox.append(mmToVox(i)) coords_vox = list(tuple(x) for x in coords_vox) bad_coords = [] for coord in coords_vox: sphere_vol = np.zeros(mask_data.shape, dtype=bool) sphere_vol[tuple(coord)] = 1 if (mask_data & sphere_vol).any(): print("%s%s" % (coord, ' falls within mask...')) continue inds = get_sphere(coord, error, (np.abs(x_vox), y_vox, z_vox), mask_data.shape) sphere_vol[tuple(inds.T)] = 1 if (mask_data & sphere_vol).any(): print("%s%s%.2f%s" % (coord, ' is within a + or - ', float(error), ' mm neighborhood...')) continue bad_coords.append(coord) bad_coords = [x for x in bad_coords if x is not None] indices = [] for bad_coord in bad_coords: indices.append(coords_vox.index(bad_coord)) label_names = list(label_names) coords = list(tuple(x) for x in coords) for ix in sorted(indices, reverse=True): print("%s%s%s%s" % ('Removing: ', label_names[ix], ' at ', coords[ix])) label_names.pop(ix) coords.pop(ix) return coords, label_names
def inverse_transform(self, X, y=None, **kwargs): """ Reconstruct image from transformed data. :param X: data :param y: targets :param kwargs: :return: """ X = np.asarray(X) # get ROI masks atlas_obj = AtlasLibrary().get_atlas(self.atlas_name, self.affine, self.shape, self.mask_threshold) roi_objects = self._get_rois(atlas_obj, which_rois=self.rois, background_id=self.background_id) unmasked = np.squeeze(np.zeros_like(atlas_obj.map, dtype='float32')) for i, roi in enumerate(roi_objects): mask, mask_affine = masking._load_mask_img(roi.mask) mask_img = image.new_img_like(roi.mask, mask, mask_affine) mask_data = _utils.as_ndarray(mask_img.get_fdata(), dtype=np.bool) if self.collection_mode == 'list': unmasked[mask_data] = X[i] else: unmasked[mask_data] = X[self.mask_indices == i] new_image = image.new_img_like(atlas_obj.atlas, unmasked) return new_image
def make_searchlight_masks(self): # Compute world coordinates of all in-mask voxels. # Return indices as sparse matrix of 0's and 1's print("start get coords") world_process_mask = self.data.nifti_masker.fit_transform(self.process_mask) world_brain_mask = self.data.nifti_masker.fit_transform(self.data.mask) process_mask_1D = world_brain_mask.copy() process_mask_1D[:,:] = 0 no_overlap = np.where( world_process_mask * world_brain_mask > 0 ) #get the indices where at least one entry is 0 process_mask_1D[no_overlap] = 1 #delete entries for which there is no overlap mask, mask_affine = masking._load_mask_img(self.data.mask) mask_coords = np.where(mask != 0) mc1 = np.reshape(mask_coords[0], (1, -1)) mc2 = np.reshape(mask_coords[1], (1, -1)) mc3 = np.reshape(mask_coords[2], (1, -1)) mask_coords = np.concatenate((mc1.T,mc2.T, mc3.T), axis = 1) selected_3D = self.data.nifti_masker.inverse_transform( process_mask_1D ) process_mask_coords = np.where(selected_3D.get_data()[:,:,:,0] != 0) pmc1 = np.reshape(process_mask_coords[0], (1, -1)) pmc2 = np.reshape(process_mask_coords[1], (1, -1)) pmc3 = np.reshape(process_mask_coords[2], (1, -1)) process_mask_coords = np.concatenate((pmc1.T,pmc2.T, pmc3.T), axis = 1) clf = neighbors.NearestNeighbors(radius = 3) A = clf.fit(mask_coords).radius_neighbors_graph(process_mask_coords) del mask_coords, process_mask_coords, selected_3D, no_overlap print("Built searchlight masks.") print("Each searchlight has on the order of " + str( sum(sum(A[0].toarray())) ) + " voxels") self.A = A.tolil() self.process_mask_1D = process_mask_1D
def coord_masker(mask, coords, label_names): x_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[0] y_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[1] z_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[2] def mmToVox(mmcoords): voxcoords = ['','',''] voxcoords[0] = int((round(int(mmcoords[0])/x_vox))+45) voxcoords[1] = int((round(int(mmcoords[1])/y_vox))+63) voxcoords[2] = int((round(int(mmcoords[2])/z_vox))+36) return voxcoords mask_data, _ = masking._load_mask_img(mask) mask_coords = list(zip(*np.where(mask_data == True))) coords_vox = [] for i in coords: coords_vox.append(mmToVox(i)) coords_vox = list(tuple(x) for x in coords_vox) bad_coords = [] error=8 for coord in coords_vox: sphere_vol = np.zeros(mask_data.shape, dtype=bool) sphere_vol[tuple(coord)] = 1 if (mask_data & sphere_vol).any(): print(str(coord) + ' falls within mask...') continue inds = get_sphere(coord, error, (np.abs(x_vox), y_vox, z_vox), mask_data.shape) sphere_vol[tuple(inds.T)] = 1 if (mask_data & sphere_vol).any(): print(str(coord) + ' is within a + or - ' + str(error) + ' voxel neighborhood...') continue bad_coords.append(coord) bad_coords = [x for x in bad_coords if x is not None] indices=[] for bad_coord in bad_coords: indices.append(coords_vox.index(bad_coord)) for ix in sorted(indices, reverse=True): print('Removing: ' + str(label_names[ix]) + ' at ' + str(coords[ix])) del label_names[ix] del coords[ix] return(coords, label_names)
def apply_mask_and_get_affinity(seeds, niimg, radius, allow_overlap, n_jobs=1, mask_img=None): import time start = time.time() seeds = list(seeds) affine = niimg.affine # Compute world coordinates of all in-mask voxels. mask_img = check_niimg_3d(mask_img) mask_img = image.resample_img(mask_img, target_affine=affine, target_shape=niimg.shape[:3], interpolation='nearest') mask, _ = masking._load_mask_img(mask_img) mask_coords = list(zip(*np.where(mask != 0))) X = masking._apply_mask_fmri(niimg, mask_img) # For each seed, get coordinates of nearest voxel nearests = joblib.Parallel(n_jobs=n_jobs)( joblib.delayed(seed_nearest)(seed_chunk, affine, mask_coords) for thread_id, seed_chunk in enumerate(np.array_split(seeds, n_jobs))) nearests = [i for j in nearests for i in j] mask_coords = np.asarray(list(zip(*mask_coords))) mask_coords = coord_transform(mask_coords[0], mask_coords[1], mask_coords[2], affine) mask_coords = np.asarray(mask_coords).T clf = neighbors.NearestNeighbors(radius=radius) A = clf.fit(mask_coords).radius_neighbors_graph(seeds) A = A.tolil() for i, nearest in enumerate(nearests): if nearest is None: continue A[i, nearest] = True # Include the voxel containing the seed itself if not masked mask_coords = mask_coords.astype(int).tolist() for i, seed in enumerate(seeds): try: A[i, mask_coords.index(seed)] = True except ValueError: # seed is not in the mask pass if not allow_overlap: if np.any(A.sum(axis=0) >= 2): raise ValueError('Overlap detected between spheres') return X, A
def coord_masker(mask, coords, label_names): x_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[0] y_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[1] z_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[2] def mmToVox(mmcoords): voxcoords = ['','',''] voxcoords[0] = int((round(int(mmcoords[0])/x_vox))+45) voxcoords[1] = int((round(int(mmcoords[1])/y_vox))+63) voxcoords[2] = int((round(int(mmcoords[2])/z_vox))+36) return voxcoords mask_data, _ = masking._load_mask_img(mask) mask_coords = list(zip(*np.where(mask_data == True))) coords_vox = [] for i in coords: coords_vox.append(mmToVox(i)) coords_vox = list(tuple(x) for x in coords_vox) bad_coords = [] for coord in coords_vox: bad_coord = check_neighborhood(coord, mask_coords) bad_coords.append(bad_coord) bad_coords = [x for x in bad_coords if x is not None] #if __name__ == '__main__': #number_processes = (multiprocessing.cpu_count()) #pool = multiprocessing.Pool(int(number_processes)) #coord = coords_vox #result = pool.map_async(check_neighborhood, coord) #pool.close() #pool.join() #bad_coords = [x for x in result.get() if x is not None] indices=[] for bad_coord in bad_coords: indices.append(coords_vox.index(bad_coord)) for ix in sorted(indices, reverse=True): print('Removing: ' + str(label_names[ix]) + ' at ' + str(coords[ix])) del label_names[ix] del coords[ix] return(coords, label_names)
def apply_mask(self, series, mask_img): """ Apply mask on series. :param series: np.ndarray, data working on :param mask_img: :return: """ mask_img = _utils.check_niimg_3d(mask_img) mask, mask_affine = masking._load_mask_img(mask_img) mask_img = image.new_img_like(mask_img, mask, mask_affine) mask_data = _utils.as_ndarray(mask_img.get_fdata(), dtype=np.bool) return series[mask_data].T
def parcel_masker(mask, coords, parcel_list, label_names, dir_path, ID): from pynets import nodemaker from nilearn.image import resample_img from nilearn import masking ##For parcel masking, specify overlap thresh and error cushion in mm voxels perc_overlap = 0.75 ##Default is >=90% overlap mask_img = nib.load(mask) mask_data, _ = masking._load_mask_img(mask) i = 0 indices = [] for parcel in parcel_list: parcel_vol = np.zeros(mask_data.shape, dtype=bool) parcel_data_reshaped = resample_img(parcel, target_affine=mask_img.affine, target_shape=mask_data.shape).get_data() parcel_vol[parcel_data_reshaped==1] = 1 ##Count number of unique voxels where overlap of parcel and mask occurs overlap_count = len(np.unique(np.where((mask_data.astype('uint8')==1) & (parcel_vol.astype('uint8')==1)))) ##Count number of total unique voxels within the parcel total_count = len(np.unique(np.where(((parcel_vol.astype('uint8')==1))))) ##Calculate % overlap try: overlap = float(overlap_count/total_count) except: overlap = float(0) if overlap >= perc_overlap: print(str(round(100*overlap,1)) + '% of parcel ' + str(label_names[i]) + ' falls within mask...') else: indices.append(i) i = i + 1 label_names_adj=list(label_names) coords_adj = list(tuple(x) for x in coords) parcel_list_adj = parcel_list for ix in sorted(indices, reverse=True): print('Removing: ' + str(label_names_adj[ix]) + ' at ' + str(coords_adj[ix])) label_names_adj.pop(ix) coords_adj.pop(ix) parcel_list_adj.pop(ix) ##Create a resampled 3D atlas that can be viewed alongside mask img for QA resampled_parcels_nii_path = dir_path + '/' + ID + '_parcels_resampled2mask_' + str(os.path.basename(mask).split('.')[0]) + '.nii.gz' resampled_parcels_atlas, _ = nodemaker.create_parcel_atlas(parcel_list_adj) resampled_parcels_map_nifti = resample_img(resampled_parcels_atlas, target_affine=mask_img.affine, target_shape=mask_data.shape) nib.save(resampled_parcels_map_nifti, resampled_parcels_nii_path) return(coords_adj, label_names_adj, parcel_list_adj)
def fit(self, imgs, y, y_mask=None, groups=None, X=None, A=None): # check if image is 4D imgs = check_niimg_4d(imgs) # Get the seeds process_mask_img = self.process_mask_img if self.process_mask_img is None: process_mask_img = self.mask_img # Compute world coordinates of the seeds process_mask, process_mask_affine = masking._load_mask_img( process_mask_img) process_mask_coords = np.where(process_mask != 0) process_mask_coords = coord_transform(process_mask_coords[0], process_mask_coords[1], process_mask_coords[2], process_mask_affine) process_mask_coords = np.asarray(process_mask_coords).T import time start = time.time() print("GETTING SEARCHLIGHT SPHERES") X, A = apply_mask_and_get_affinity(process_mask_coords, imgs, self.radius, True, mask_img=self.mask_img, n_jobs=self.n_jobs) self.X = X self.A = A self.y = y self.process_mask = process_mask elapsed = time.time() - start print(elapsed) print("FITTING") scores = search_light_rsa(X, y, None, A, y_mask, self.n_jobs, self.verbose) scores_3D = np.zeros((process_mask.shape) + (len(y), )) for i in range(len(y)): scores_3D[process_mask, i] = scores[:, i] self.scores_ = scores_3D return self
def fit(self, imgs, y, groups=None): """Fit the spatiotemporal searchlight Parameters ---------- imgs : Niimg-like object See http://nilearn.github.io/manipulating_images/input_output.html Use 5D image. [x voxels, y voxels, z voxels, trials, time series of each trials] y : 1D array-like Target variable to predict. Must have exactly as many elements as trials in imgs. groups : array-like, optional group label for each sample for cross validation. Must have exactly as many elements as trials in imgs. default None NOTE: will have no effect for scikit learn < 0.18 (as nilearn says) """ # check if image is 5D, simply. if len(imgs.shape) != 5: raise ValueError('This SpatioTemporalSearhcLight instance needs 5D image.') # Get the seeds process_mask_img = self.mask_img # Compute world coordinates of the seeds process_mask, process_mask_affine = masking._load_mask_img(process_mask_img) process_mask_coords = np.where(process_mask != 0) process_mask_coords = coord_transform( process_mask_coords[0], process_mask_coords[1], process_mask_coords[2], process_mask_affine) process_mask_coords = np.asarray(process_mask_coords).T X, A = _apply_mask_and_get_affinity( process_mask_coords, imgs, self.radius, True, mask_img=self.mask_img) # Run Searchlight scores = self._search_light(X, y, A, groups=groups) scores_3D = np.zeros(process_mask.shape) scores_3D[process_mask] = scores self.scores_ = scores_3D return self
def make_searchlight_masks(self): ''' Compute world coordinates of all in-mask voxels. Returns a list of masks, one mask for each searchlight. For a whole brain, this will generate thousands of masks. Returns masks in lil format (efficient for storing sparse matrices)''' # Compute world coordinates of all in-mask voxels. # Return indices as sparse matrix of 0's and 1's print("start get coords") world_process_mask = self.data.nifti_masker.fit_transform( self.process_mask) world_brain_mask = self.data.nifti_masker.fit_transform(self.data.mask) process_mask_1D = world_brain_mask.copy() process_mask_1D[:, :] = 0 no_overlap = np.where( world_process_mask * world_brain_mask > 0) #get the indices where at least one entry is 0 process_mask_1D[ no_overlap] = 1 #delete entries for which there is no overlap mask, mask_affine = masking._load_mask_img(self.data.mask) mask_coords = np.where(mask != 0) mc1 = np.reshape(mask_coords[0], (1, -1)) mc2 = np.reshape(mask_coords[1], (1, -1)) mc3 = np.reshape(mask_coords[2], (1, -1)) mask_coords = np.concatenate((mc1.T, mc2.T, mc3.T), axis=1) selected_3D = self.data.nifti_masker.inverse_transform(process_mask_1D) process_mask_coords = np.where(selected_3D.get_data()[:, :, :, 0] != 0) pmc1 = np.reshape(process_mask_coords[0], (1, -1)) pmc2 = np.reshape(process_mask_coords[1], (1, -1)) pmc3 = np.reshape(process_mask_coords[2], (1, -1)) process_mask_coords = np.concatenate((pmc1.T, pmc2.T, pmc3.T), axis=1) clf = neighbors.NearestNeighbors(radius=3) A = clf.fit(mask_coords).radius_neighbors_graph(process_mask_coords) del mask_coords, process_mask_coords, selected_3D, no_overlap print("Built searchlight masks.") print("Each searchlight has on the order of " + str(sum(sum(A[0].toarray()))) + " voxels") self.A = A.tolil() self.process_mask_1D = process_mask_1D
def parcel_masker(mask, coords, parcel_list, label_names, dir_path, ID, perc_overlap): from pynets import nodemaker from nilearn.image import resample_img from nilearn import masking mask_img = nib.load(mask) mask_data, _ = masking._load_mask_img(mask) i = 0 indices = [] for parcel in parcel_list: parcel_vol = np.zeros(mask_data.shape, dtype=bool) parcel_data_reshaped = resample_img( parcel, target_affine=mask_img.affine, target_shape=mask_data.shape).get_data() parcel_vol[parcel_data_reshaped == 1] = 1 # Count number of unique voxels where overlap of parcel and mask occurs overlap_count = len( np.unique( np.where((mask_data.astype('uint8') == 1) & (parcel_vol.astype('uint8') == 1)))) # Count number of total unique voxels within the parcel total_count = len( np.unique(np.where((parcel_vol.astype('uint8') == 1)))) # Calculate % overlap try: overlap = float(overlap_count / total_count) except RuntimeWarning: print('\nWarning: No overlap with mask!\n') overlap = float(0) if overlap >= perc_overlap: print("%.2f%s%s%s" % (100 * overlap, '% of parcel ', label_names[i], ' falls within mask...')) else: indices.append(i) i = i + 1 label_names_adj = list(label_names) coords_adj = list(tuple(x) for x in coords) parcel_list_adj = parcel_list for ix in sorted(indices, reverse=True): print("%s%s%s%s" % ('Removing: ', label_names_adj[ix], ' at ', coords_adj[ix])) label_names_adj.pop(ix) coords_adj.pop(ix) parcel_list_adj.pop(ix) # Create a resampled 3D atlas that can be viewed alongside mask img for QA resampled_parcels_nii_path = "%s%s%s%s%s%s" % ( dir_path, '/', ID, '_parcels_resampled2mask_', os.path.basename(mask).split('.')[0], '.nii.gz') resampled_parcels_atlas, _ = nodemaker.create_parcel_atlas(parcel_list_adj) resampled_parcels_map_nifti = resample_img(resampled_parcels_atlas, target_affine=mask_img.affine, target_shape=mask_data.shape) nib.save(resampled_parcels_map_nifti, resampled_parcels_nii_path) return coords_adj, label_names_adj, parcel_list_adj
def fit(self, imgs, y): """Fit the searchlight Parameters ---------- imgs : List of images y : 1D array-like Target variable to predict. Must have exactly as many elements as 3D images in img. Attributes ---------- `scores_` : numpy.ndarray search_light scores. Same shape as input parameter process_mask_img. """ # Compute world coordinates of all in-mask voxels. self.affine = nibabel.load(imgs[0]).affine if isinstance( imgs[0], str) else imgs[0].affine mask, mask_affine = masking._load_mask_img(self.mask_img) mask_coords = np.where(mask != 0) mask_coords = np.asarray( mask_coords + (np.ones(len(mask_coords[0]), dtype=np.int), )) mask_coords = np.dot(mask_affine, mask_coords)[:3].T # Compute world coordinates of all in-process mask voxels if self.process_mask_img is None: process_mask = mask process_mask_coords_world = mask_coords else: process_mask, process_mask_affine = \ masking._load_mask_img(self.process_mask_img) process_mask_coords = np.where(process_mask != 0) process_mask_coords_world = \ np.asarray(process_mask_coords + (np.ones(len(process_mask_coords[0]), dtype=np.int),)) process_mask_coords_world = np.dot(process_mask_affine, process_mask_coords_world)[:3].T clf = neighbors.NearestNeighbors(radius=self.radius) A = clf.fit(mask_coords).radius_neighbors_graph( process_mask_coords_world) if self.process_mask_img is not None: empty_ind = [i for i in range(A.shape[0]) if A[i, :].getnnz() == 0] if empty_ind: warn( 'Skipping %g voxels of processing mask outside mask_img (first index: %g)' % (len(empty_ind), empty_ind[0])) A = A[list(set(range(A.shape[0])) - set(empty_ind)), :] process_mask[tuple( np.asarray(process_mask_coords)[:, empty_ind])] = False A = A.tolil() # scores is an 1D array of CV scores with length equals to the number # of voxels in processing mask (columns in process_mask) # X = masking._apply_mask_fmri(imgs, self.mask_img) X = NiftiMasker(mask_img=self.mask_img).fit_transform(imgs) estimator = self.estimator if isinstance(estimator, str): estimator = ESTIMATOR_CATALOG[estimator](**self.estimator_params) elif hasattr(estimator, '__name__'): # check if estimator has to be initialized estimator = estimator(**self.estimator_params) else: estimator.set_params(**self.estimator_params) scores = search_light(X, y, estimator, A, self.scoring, self.cv, self.n_jobs, self.verbose) scores_3D = np.zeros(process_mask.shape) scores_3D[process_mask] = scores self.scores_ = scores_3D return self
def run_struct_mapping(FSLDIR, ID, bedpostx_dir, dir_path, NETWORK, coords_MNI, node_size, atlas_select, atlas_name, label_names, plot_switch): edge_threshold = 0.90 connectome_fdt_thresh = 1000 ####Auto-set INPUTS#### nodif_brain_mask_path = bedpostx_dir + '/nodif_brain_mask.nii.gz' merged_th_samples_path = bedpostx_dir + '/merged_th1samples.nii.gz' merged_f_samples_path = bedpostx_dir + '/merged_f1samples.nii.gz' merged_ph_samples_path = bedpostx_dir + '/merged_ph1samples.nii.gz' input_MNI = FSLDIR + '/data/standard/MNI152_T1_2mm_brain.nii.gz' probtrackx_output_dir_path = bedpostx_dir + '/probtrackx_' + NETWORK ####Auto-set INPUTS#### ##Delete any existing roi spheres del_files_spheres = glob.glob(bedpostx_dir + '/roi_sphere*diff.nii.gz') try: for i in del_files_spheres: os.remove(i) except: pass ##Create transform matrix between diff and MNI using FLIRT flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'), name='coregister') flirt.inputs.reference = merged_f_samples_path flirt.inputs.in_file = input_MNI flirt.inputs.out_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat' flirt.run() ##Apply transform between diff and MNI using FLIRT flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'), name='coregister') flirt.inputs.reference = merged_f_samples_path flirt.inputs.in_file = input_MNI flirt.inputs.apply_xfm = True flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat' flirt.inputs.out_file = bedpostx_dir + '/xfms/MNI2diff_affine.nii.gz' flirt.run() x_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[0] y_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[1] z_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[2] def mmToVox(mmcoords): voxcoords = ['', '', ''] voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45) voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63) voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36) return voxcoords ##Convert coords back to voxels coords_vox = [] for coord in coords_MNI: coords_vox.append(mmToVox(coord)) coords = list(tuple(x) for x in coords_vox) j = 0 for i in coords: ##Grow spheres at ROI X = coords[j][0] Y = coords[j][1] Z = coords[j][2] out_file1 = bedpostx_dir + '/roi_point_' + str(j) + '.nii.gz' args = '-mul 0 -add 1 -roi ' + str(X) + ' 1 ' + str(Y) + ' 1 ' + str( Z) + ' 1 0 1' maths = fsl.ImageMaths(in_file=input_MNI, op_string=args, out_file=out_file1) os.system(maths.cmdline + ' -odt float') out_file2 = bedpostx_dir + '/roi_sphere_' + str(j) + '.nii.gz' args = '-kernel sphere ' + str(node_size) + ' -fmean -bin' maths = fsl.ImageMaths(in_file=out_file1, op_string=args, out_file=out_file2) os.system(maths.cmdline + ' -odt float') ##Map ROIs from Standard Space to diffusion Space: ##Applying xfm and input matrix to transform ROI's between diff and MNI using FLIRT, flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'), name='coregister') flirt.inputs.reference = nodif_brain_mask_path flirt.inputs.in_file = out_file2 out_file_diff = out_file2.split('.nii')[0] + '_diff.nii.gz' flirt.inputs.out_file = out_file_diff flirt.inputs.apply_xfm = True flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat' flirt.run() j = j + 1 if not os.path.exists(probtrackx_output_dir_path): os.makedirs(probtrackx_output_dir_path) seed_files = glob.glob(bedpostx_dir + '/*diff.nii.gz') seeds_text = probtrackx_output_dir_path + '/masks.txt' try: os.remove(seeds_text) except OSError: pass seeds_file_list = [] for seed_file in seed_files: seeds_file_list.append(seed_file) f = open(seeds_text, 'w') l1 = map(lambda x: x + '\n', seeds_file_list) f.writelines(l1) f.close() del_files_points = glob.glob(bedpostx_dir + '/roi_point*.nii.gz') for i in del_files_points: os.remove(i) del_files_spheres = glob.glob(bedpostx_dir + '/roi_sphere*[!diff].nii.gz') for i in del_files_spheres: os.remove(i) mx_path = dir_path + '/' + str(ID) + '_' + NETWORK + '_structural_mx.txt' probtrackx2 = pe.Node(interface=fsl.ProbTrackX2(), name='probtrackx2') probtrackx2.inputs.network = True probtrackx2.inputs.seed = seeds_text probtrackx2.inputs.onewaycondition = True probtrackx2.inputs.c_thresh = 0.2 probtrackx2.inputs.n_steps = 2000 probtrackx2.inputs.step_length = 0.5 probtrackx2.inputs.n_samples = 5000 probtrackx2.inputs.dist_thresh = 0.0 probtrackx2.inputs.opd = True probtrackx2.inputs.loop_check = True probtrackx2.inputs.omatrix1 = True probtrackx2.overwrite = True probtrackx2.inputs.verbose = True probtrackx2.inputs.mask = nodif_brain_mask_path probtrackx2.inputs.out_dir = probtrackx_output_dir_path probtrackx2.inputs.thsamples = merged_th_samples_path probtrackx2.inputs.fsamples = merged_f_samples_path probtrackx2.inputs.phsamples = merged_ph_samples_path probtrackx2.iterables = ("seed", seed_files) try: probtrackx2.inputs.avoid_mp = vetricular_CSF_mask_path except: pass probtrackx2.run() del (probtrackx2) if os.path.exists(probtrackx_output_dir_path + '/fdt_network_matrix'): mx = np.genfromtxt(probtrackx_output_dir_path + '/fdt_network_matrix') waytotal = np.genfromtxt(probtrackx_output_dir_path + '/waytotal') np.seterr(divide='ignore', invalid='ignore') conn_matrix = np.divide(mx, waytotal) conn_matrix[np.isnan(conn_matrix)] = 0 conn_matrix = np.nan_to_num(conn_matrix) conn_matrix = normalize(conn_matrix) ##Save matrix out_path_mx = dir_path + '/' + str( ID) + '_' + NETWORK + '_structural_mx.txt' np.savetxt(out_path_mx, conn_matrix, delimiter='\t') if plot_switch == True: rois_num = conn_matrix.shape[0] print("Creating plot of dimensions:\n" + str(rois_num) + ' x ' + str(rois_num)) plt.figure(figsize=(10, 10)) plt.imshow(conn_matrix, interpolation="nearest", vmax=1, vmin=-1, cmap=plt.cm.RdBu_r) ##And display the labels plt.colorbar() plt.title(atlas_select.upper() + ' ' + NETWORK + ' Structural Connectivity') out_path_fig = dir_path + '/' + str( ID) + '_' + NETWORK + '_structural_adj_mat.png' plt.savefig(out_path_fig) plt.close() conn_matrix_symm = np.maximum(conn_matrix, conn_matrix.transpose()) fdt_paths_loc = probtrackx_output_dir_path + '/fdt_paths.nii.gz' ##Plotting with glass brain ##Create transform matrix between diff and MNI using FLIRT flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'), name='coregister') flirt.inputs.reference = input_MNI flirt.inputs.in_file = nodif_brain_mask_path flirt.inputs.out_matrix_file = bedpostx_dir + '/xfms/diff2MNI.mat' flirt.run() ##Apply transform between diff and MNI using FLIRT flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'), name='coregister') flirt.inputs.reference = input_MNI flirt.inputs.in_file = nodif_brain_mask_path flirt.inputs.apply_xfm = True flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/diff2MNI.mat' flirt.inputs.out_file = bedpostx_dir + '/xfms/diff2MNI_affine.nii.gz' flirt.run() flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'), name='coregister') flirt.inputs.reference = input_MNI flirt.inputs.in_file = fdt_paths_loc out_file_MNI = fdt_paths_loc.split('.nii')[0] + '_MNI.nii.gz' flirt.inputs.out_file = out_file_MNI flirt.inputs.apply_xfm = True flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/diff2MNI.mat' flirt.run() fdt_paths_MNI_loc = probtrackx_output_dir_path + '/fdt_paths_MNI.nii.gz' if plot_switch == True: norm = colors.Normalize(vmin=-1, vmax=1) clust_pal = sns.color_palette("Blues_r", 4) clust_colors = colors.to_rgba_array(clust_pal) connectome = plotting.plot_connectome( conn_matrix_symm, coords_MNI, edge_threshold=edge_threshold, node_color=clust_colors, edge_cmap=plotting.cm.black_blue_r) connectome.add_overlay(img=fdt_paths_MNI_loc, threshold=connectome_fdt_thresh, cmap=plotting.cm.cyan_copper_r) out_file_path = dir_path + '/structural_connectome_fig_' + NETWORK + '_' + str( ID) + '.png' plt.savefig(out_file_path) plt.close() from pynets import plotting as pynplot NETWORK = NETWORK + '_structural' pynplot.plot_connectogram(conn_matrix, conn_model, atlas_name, dir_path, ID, NETWORK, label_names) if NETWORK != None: est_path = dir_path + '/' + ID + '_' + NETWORK + '_structural_est.txt' else: est_path = dir_path + '/' + ID + '_structural_est.txt' try: np.savetxt(est_path, conn_matrix_symm, delimiter='\t') except RuntimeError: print('Diffusion network connectome failed!') return (est_path)
def reg_coords2diff(coords, bedpostx_dir, node_size, dir_path): try: FSLDIR = os.environ['FSLDIR'] except NameError: print('FSLDIR environment variable not set!') import glob import nipype.interfaces.fsl as fsl import nipype.pipeline.engine as pe from nilearn import masking try: import cPickle as pickle except ImportError: import _pickle as pickle pick_dump = True volumes_dir = "%s%s%s" % (dir_path, '/volumes_', str(node_size)) nodif_brain_mask_path = "%s%s" % (bedpostx_dir, '/nodif_brain_mask.nii.gz') merged_f_samples_path = "%s%s" % (bedpostx_dir, '/merged_f1samples.nii.gz') x_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[0] y_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[1] z_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[2] def mmToVox(mmcoords): voxcoords = ['', '', ''] voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45) voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63) voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36) return voxcoords # Convert coords back to voxels coords_vox = [] for coord in coords: coords_vox.append(mmToVox(coord)) coords = list(tuple(x) for x in coords_vox) j = 0 for i in coords: # Grow spheres at ROI X = coords[j][0] Y = coords[j][1] Z = coords[j][2] out_file1 = "%s%s%s%s" % (volumes_dir, '/roi_point_', str(j), '.nii.gz') args = "%s%s%s%s%s%s%s" % ('-mul 0 -add 1 -roi ', str(X), ' 1 ', str(Y), ' 1 ', str(Z), ' 1 0 1') maths = fsl.ImageMaths(in_file=FSLDIR + '/data/standard/MNI152_T1_1mm_brain.nii.gz', op_string=args, out_file=out_file1) os.system(maths.cmdline + ' -odt float') out_file2 = "%s%s%s%s" % (volumes_dir, '/region_', str(j), '.nii.gz') args = "%s%s%s" % ('-kernel sphere ', str(node_size), ' -fmean -bin') maths = fsl.ImageMaths(in_file=out_file1, op_string=args, out_file=out_file2) os.system(maths.cmdline + ' -odt float') # Map ROIs from Standard Space to diffusion Space: # Applying xfm and input matrix to transform ROI's between diff and MNI using FLIRT, flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'), name='coregister') flirt.inputs.reference = merged_f_samples_path flirt.inputs.in_file = out_file2 out_file_diff = "%s%s" % (out_file2.split('.nii')[0], '_diff.nii.gz') flirt.inputs.out_file = out_file_diff flirt.inputs.out_matrix_file = '/tmp/out_flirt.mat' flirt.inputs.apply_xfm = True flirt.inputs.in_matrix_file = "%s%s" % (bedpostx_dir, '/xfms/MNI2diff.mat') flirt.run() j = j + 1 args = '-bin' maths = fsl.ImageMaths(in_file=out_file_diff, op_string=args, out_file=out_file_diff) print('\nBinarizing custom mask...') os.system(maths.cmdline) del_files_points = glob.glob(volumes_dir + '/roi_point*') if len(del_files_points) > 0: for i in del_files_points: os.remove(i) spheres_list = [i for i in os.listdir(volumes_dir) if 'diff.nii.gz' in i] if pick_dump is True: # Save coords to pickle coord_path = "%s%s" % (dir_path, '/coords.pkl') with open(coord_path, 'wb') as f: pickle.dump(coords, f, protocol=2) return spheres_list
def get_searchlight_neighbours_matrix(mask_file, radius=6): """ Parameters ---------- mask_file : string Path to mask-file. radius : integer Searchlight radius in mm. Returns ------- A : ndarray, shape(n_voxel, n_voxel) Affinity matrix. A[i,j]==1 if voxel_i, voxel_j are neighbours and 0 otherwise Examples -------- >>> A = get_searchlight_neighbours_matrix('MNI152_2mm_brain_mask.nii') >>> A.shape """ # heavily borrowed from nilearn: http://nilearn.github.io/ from nilearn import image from nilearn import masking from nilearn.image.resampling import coord_transform from distutils.version import LooseVersion import sklearn from sklearn import neighbors from nilearn._utils.niimg_conversions import check_niimg_3d def _apply_mask_and_get_affinity(seeds, niimg, radius, allow_overlap, mask_img=None): seeds = list(seeds) aff = niimg.get_affine() # Compute world coordinates of all in-mask voxels. if mask_img is not None: mask_img = check_niimg_3d(mask_img) mask_img = image.resample_img(mask_img, target_affine=aff, target_shape=niimg.shape[:3], interpolation='nearest') mask, _ = masking._load_mask_img(mask_img) mask_coords = list(zip(*np.where(mask != 0))) # X = masking._apply_mask_fmri(niimg, mask_img) else: mask_coords = list(np.ndindex(niimg.shape[:3])) # For each seed, get coordinates of nearest voxel nearests = [] for sx, sy, sz in seeds: nearest = np.round(coord_transform(sx, sy, sz, np.linalg.inv(aff))) nearest = nearest.astype(int) nearest = (nearest[0], nearest[1], nearest[2]) try: nearests.append(mask_coords.index(nearest)) except ValueError: nearests.append(None) mask_coords = np.asarray(list(zip(*mask_coords))) mask_coords = coord_transform(mask_coords[0], mask_coords[1], mask_coords[2], aff) mask_coords = np.asarray(mask_coords).T if (radius is not None and LooseVersion(sklearn.__version__) < LooseVersion('0.16')): # Fix for scikit learn versions below 0.16. See # https://github.com/scikit-learn/scikit-learn/issues/4072 radius += 1e-6 clf = neighbors.NearestNeighbors(radius=radius) A = clf.fit(mask_coords).radius_neighbors_graph(seeds) A = A.tolil() for i, nearest in enumerate(nearests): if nearest is None: continue A[i, nearest] = True # Include the voxel containing the seed itself if not masked mask_coords = mask_coords.astype(int).tolist() for i, seed in enumerate(seeds): try: A[i, mask_coords.index(seed)] = True except ValueError: # seed is not in the mask pass if not allow_overlap: if np.any(A.sum(axis=0) >= 2): raise ValueError('Overlap detected between spheres') return A process_mask_img = nib.load(mask_file) # Compute world coordinates of the seeds process_mask, process_mask_affine = masking._load_mask_img( process_mask_img) process_mask_coords = np.where(process_mask != 0) process_mask_coords = coord_transform(process_mask_coords[0], process_mask_coords[1], process_mask_coords[2], process_mask_affine) process_mask_coords = np.asarray(process_mask_coords).T A = _apply_mask_and_get_affinity(process_mask_coords, process_mask_img, radius, True, mask_img=process_mask_img) return A # .toarray().astype('bool')
def coords_masker(roi, coords, label_names, mask, error): from nilearn import masking if mask and roi == mask: error = 0 mask_data, mask_aff = masking._load_mask_img(roi) x_vox = np.diagonal(mask_aff[:3, 0:3])[0] y_vox = np.diagonal(mask_aff[:3, 0:3])[1] z_vox = np.diagonal(mask_aff[:3, 0:3])[2] def mmToVox(mask_aff, mmcoords): return nib.affines.apply_affine(np.linalg.inv(mask_aff), mmcoords) # mask_coords = list(zip(*np.where(mask_data == True))) coords_vox = [] for i in coords: coords_vox.append(mmToVox(mask_aff, i)) coords_vox = list( tuple(map(lambda y: isinstance(y, float) and int(round(y, 0)), x)) for x in coords_vox) bad_coords = [] for coords in coords_vox: sphere_vol = np.zeros(mask_data.shape, dtype=bool) sphere_vol[tuple(coords)] = 1 if (mask_data & sphere_vol).any(): print("%s%s" % (coords, ' falls within roi mask...')) continue inds = get_sphere(coords, error, (np.abs(x_vox), y_vox, z_vox), mask_data.shape) sphere_vol[tuple(inds.T)] = 1 if (mask_data & sphere_vol).any(): print("%s%s%.2f%s" % (coords, ' is within a + or - ', float(error), ' mm neighborhood...')) continue bad_coords.append(coords) bad_coords = [x for x in bad_coords if x is not None] indices = [] for bad_coords in bad_coords: indices.append(coords_vox.index(bad_coords)) label_names = list(label_names) coords = list(tuple(x) for x in coords_vox) try: for ix in sorted(indices, reverse=True): print("%s%s%s%s" % ('Removing: ', label_names[ix], ' at ', coords[ix])) label_names.pop(ix) coords.pop(ix) except RuntimeError: print( 'ERROR: Restrictive masking. No coords remain after masking with brain mask/roi...' ) if len(coords) <= 1: raise ValueError( '\nERROR: ROI mask was likely too restrictive and yielded < 2 remaining coords' ) return coords, label_names
def reg_coords2diff(coords, bedpostx_dir, node_size): try: FSLDIR = os.environ['FSLDIR'] except NameError: print('FSLDIR environment variable not set!') import glob import nipype.interfaces.fsl as fsl import nipype.pipeline.engine as pe from nilearn import masking volumes_dir = bedpostx_dir + '/volumes' nodif_brain_mask_path = bedpostx_dir + '/nodif_brain_mask.nii.gz' merged_f_samples_path = bedpostx_dir + '/merged_f1samples.nii.gz' x_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[0] y_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[1] z_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[2] def mmToVox(mmcoords): voxcoords = ['', '', ''] voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45) voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63) voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36) return voxcoords ##Convert coords back to voxels coords_vox = [] for coord in coords: coords_vox.append(mmToVox(coord)) coords = list(tuple(x) for x in coords_vox) j = 0 for i in coords: ##Grow spheres at ROI X = coords[j][0] Y = coords[j][1] Z = coords[j][2] out_file1 = volumes_dir + '/roi_point_' + str(j) + '.nii.gz' args = '-mul 0 -add 1 -roi ' + str(X) + ' 1 ' + str(Y) + ' 1 ' + str( Z) + ' 1 0 1' maths = fsl.ImageMaths(in_file=FSLDIR + '/data/standard/MNI152_T1_1mm_brain.nii.gz', op_string=args, out_file=out_file1) os.system(maths.cmdline + ' -odt float') out_file2 = volumes_dir + '/region_' + str(j) + '.nii.gz' args = '-kernel sphere ' + str(node_size) + ' -fmean -bin' maths = fsl.ImageMaths(in_file=out_file1, op_string=args, out_file=out_file2) os.system(maths.cmdline + ' -odt float') ##Map ROIs from Standard Space to diffusion Space: ##Applying xfm and input matrix to transform ROI's between diff and MNI using FLIRT, flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'), name='coregister') flirt.inputs.reference = merged_f_samples_path flirt.inputs.in_file = out_file2 out_file_diff = out_file2.split('.nii')[0] + '_diff.nii.gz' flirt.inputs.out_file = out_file_diff flirt.inputs.out_matrix_file = '/tmp/out_flirt.mat' flirt.inputs.apply_xfm = True flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat' flirt.run() j = j + 1 del_files_points = glob.glob(volumes_dir + '/roi_point*') try: for i in del_files_points: os.remove(i) except: pass spheres_list = [i for i in os.listdir(volumes_dir) if 'diff.nii' in i] return spheres_list
def _apply_mask_and_get_affinity(seeds, niimg, radius, allow_overlap, mask_img=None): seeds = list(seeds) aff = niimg.get_affine() # Compute world coordinates of all in-mask voxels. if mask_img is not None: mask_img = check_niimg_3d(mask_img) mask_img = image.resample_img(mask_img, target_affine=aff, target_shape=niimg.shape[:3], interpolation='nearest') mask, _ = masking._load_mask_img(mask_img) mask_coords = list(zip(*np.where(mask != 0))) # X = masking._apply_mask_fmri(niimg, mask_img) else: mask_coords = list(np.ndindex(niimg.shape[:3])) # For each seed, get coordinates of nearest voxel nearests = [] for sx, sy, sz in seeds: nearest = np.round(coord_transform(sx, sy, sz, np.linalg.inv(aff))) nearest = nearest.astype(int) nearest = (nearest[0], nearest[1], nearest[2]) try: nearests.append(mask_coords.index(nearest)) except ValueError: nearests.append(None) mask_coords = np.asarray(list(zip(*mask_coords))) mask_coords = coord_transform(mask_coords[0], mask_coords[1], mask_coords[2], aff) mask_coords = np.asarray(mask_coords).T if (radius is not None and LooseVersion(sklearn.__version__) < LooseVersion('0.16')): # Fix for scikit learn versions below 0.16. See # https://github.com/scikit-learn/scikit-learn/issues/4072 radius += 1e-6 clf = neighbors.NearestNeighbors(radius=radius) A = clf.fit(mask_coords).radius_neighbors_graph(seeds) A = A.tolil() for i, nearest in enumerate(nearests): if nearest is None: continue A[i, nearest] = True # Include the voxel containing the seed itself if not masked mask_coords = mask_coords.astype(int).tolist() for i, seed in enumerate(seeds): try: A[i, mask_coords.index(seed)] = True except ValueError: # seed is not in the mask pass if not allow_overlap: if np.any(A.sum(axis=0) >= 2): raise ValueError('Overlap detected between spheres') return A
def import_mat_func(input_file, ID, atlas_select, NETWORK, pynets_dir, node_size, mask, thr, graph, parlistfile, sps_model, all_nets): if '.nii' in input_file and parlistfile == None and NETWORK == None: if graph == False: func_file = input_file if all_nets != None: func_img = nib.load(func_file) par_path = pynets_dir + '/RSN_refs/yeo.nii.gz' par_img = nib.load(par_path) par_data = par_img.get_data() ref_dict = { 0: 'unknown', 1: 'VIS', 2: 'SM', 3: 'DA', 4: 'VA', 5: 'LIM', 6: 'FP', 7: 'DEF' } def get_ref_net(x, y, z): aff_inv = npl.inv(func_img.affine) # apply_affine(aff, (x,y,z)) # vox to mni vox_coord = apply_affine(aff_inv, (x, y, z)) # mni to vox return ref_dict[int(par_data[int(vox_coord[0]), int(vox_coord[1]), int(vox_coord[2])])] dir_path = os.path.dirname(os.path.realpath(func_file)) atlas = getattr(datasets, 'fetch_%s' % atlas_select)() atlas_name = atlas['description'].splitlines()[0] print(atlas_name + ' comes with {0}.'.format(atlas.keys())) print("\n") coords = np.vstack( (atlas.rois['x'], atlas.rois['y'], atlas.rois['z'])).T if all_nets != None: membership = pd.Series([ get_ref_net(coord[0], coord[1], coord[2]) for coord in coords ]) print('Stacked atlas coordinates in array of shape {0}.'.format( coords.shape)) print("\n") if mask is not None: from nilearn import masking mask_data, _ = masking._load_mask_img(mask) mask_coords = list(zip(*np.where(mask_data != 0))) for coord in coords: if tuple(coord) not in mask_coords: print('Removing coordinate: ' + str(tuple(coord)) + ' since it falls outside of network mask...') ix = np.where(coords == coord)[0][0] coords = np.delete(coords, ix, axis=0) print(str(len(coords))) print("\n") spheres_masker = input_data.NiftiSpheresMasker( seeds=coords, radius=float(node_size), memory='nilearn_cache', memory_level=5, verbose=2) time_series = spheres_masker.fit_transform(func_file) correlation_measure = ConnectivityMeasure(kind='correlation') correlation_matrix = correlation_measure.fit_transform( [time_series])[0] print("\n") print('Time series has {0} samples'.format(time_series.shape[0])) print("\n") else: correlation_matrix = genfromtxt(graph, delimiter='\t') plt.imshow(correlation_matrix, vmin=-1., vmax=1., cmap='RdBu_r', interpolation='nearest') plt.colorbar() plt.title(atlas_name + ' correlation matrix') out_path_fig = dir_path + '/' + ID + '_' + atlas_name + '_adj_mat_corr.png' plt.savefig(out_path_fig) plt.close() ##Tweak edge_threshold to keep only the strongest connections. atlast_graph_title = atlas_name + ' correlation graph' if mask is None: atlast_graph_title = atlas_name + ' correlation graph' else: atlast_graph_title = atlas_name + ' Masked Nodes' edge_threshold = str(float(thr) * 100) + '%' # plot graph: if all_nets != None: # coloring code: n = len(membership.unique()) clust_pal = sns.color_palette("Set1", n) clust_lut = dict( zip(map(str, np.unique(membership.astype('category'))), clust_pal)) clust_colors = colors.to_rgba_array(membership.map(clust_lut)) plotting.plot_connectome(correlation_matrix, coords, node_color=clust_colors, title=atlast_graph_title, edge_threshold=edge_threshold, node_size=20, colorbar=True) else: plotting.plot_connectome(correlation_matrix, coords, title=atlast_graph_title, edge_threshold=edge_threshold, node_size=20, colorbar=True) out_path_fig = dir_path + '/' + ID + '_' + atlas_name + '_connectome_viz.png' plt.savefig(out_path_fig) plt.close() time_series_path = dir_path + '/' + ID + '_ts.txt' np.savetxt(time_series_path, time_series, delimiter='\t') mx = genfromtxt(time_series_path, delimiter='') elif '.nii' in input_file and parlistfile != None and NETWORK == None: # block of code for whole brain parcellations if all_nets != None: par_path = pynets_dir + '/RSN_refs/yeo.nii.gz' par_img = nib.load(par_path) par_data = par_img.get_data() ref_dict = { 0: 'unknown', 1: 'VIS', 2: 'SM', 3: 'DA', 4: 'VA', 5: 'LIM', 6: 'FP', 7: 'DEF' } def get_ref_net(x, y, z): aff_inv = npl.inv(bna_img.affine) # apply_affine(aff, (x,y,z)) # vox to mni vox_coord = apply_affine(aff_inv, (x, y, z)) # mni to vox return ref_dict[int(par_data[int(vox_coord[0]), int(vox_coord[1]), int(vox_coord[2])])] func_file = input_file dir_path = os.path.dirname(os.path.realpath(func_file)) atlas_name = parlistfile.split('/')[-1].split('.')[0] # Code for getting name and coordinates of parcels. # Adapted from Dan L. (https://github.com/danlurie/despolab_lesion/blob/master/code/sandbox/Sandbox%20-%20Calculate%20and%20plot%20HCP%20mean%20matrix.ipynb) bna_img = nib.load(parlistfile) bna_data = bna_img.get_data() if bna_img.get_data_dtype() != np.dtype(np.int): bna_data_for_coords = bna_img.get_data() # Number of parcels: par_max = np.ceil(np.max(bna_data_for_coords)).astype('int') bna_data = bna_data.astype('int16') else: par_max = np.max(bna_data) img_stack = [] for idx in range(1, par_max + 1): roi_img = bna_data == idx img_stack.append(roi_img) img_stack = np.array(img_stack) img_list = [] for idx in range(par_max): roi_img = nilearn.image.new_img_like(bna_img, img_stack[idx]) img_list.append(roi_img) bna_4D = nilearn.image.concat_imgs(img_list) coords = [] for roi_img in img_list: coords.append(nilearn.plotting.find_xyz_cut_coords(roi_img)) coords = np.array(coords) if all_nets != None: membership = pd.Series([ get_ref_net(coord[0], coord[1], coord[2]) for coord in coords ]) # atlas = getattr(datasets, 'fetch_%s' % atlas_select)() # atlas_name = atlas['description'].splitlines()[0] print("\n") print(atlas_name + ' comes with {0}.'.format(par_max) + 'parcels') print("\n") print("\n") print('Stacked atlas coordinates in array of shape {0}.'.format( coords.shape)) print("\n") if mask is not None: from nilearn import masking mask_data, _ = masking._load_mask_img(mask) mask_coords = list(zip(*np.where(mask_data != 0))) for coord in coords: if tuple(coord) not in mask_coords: print('Removing coordinate: ' + str(tuple(coord)) + ' since it falls outside of network mask...') ix = np.where(coords == coord)[0][0] coords = np.delete(coords, ix, axis=0) print(str(len(coords))) ##extract time series from whole brain parcellaions: parcellation = nib.load(parlistfile) parcel_masker = input_data.NiftiLabelsMasker(labels_img=parcellation, background_label=0, memory='nilearn_cache', memory_level=5) time_series = parcel_masker.fit_transform(func_file) ##old ref code for coordinate parcellations: #spheres_masker = input_data.NiftiSpheresMasker(seeds=coords, radius=float(node_size), memory='nilearn_cache', memory_level=2, verbose=2) #time_series = spheres_masker.fit_transform(func_file) correlation_measure = ConnectivityMeasure(kind='correlation') correlation_matrix = correlation_measure.fit_transform([time_series ])[0] print("\n") print('Time series has {0} samples'.format(time_series.shape[0])) print("\n") plt.imshow(correlation_matrix, vmin=-1., vmax=1., cmap='RdBu_r', interpolation='nearest') plt.colorbar() plt.title(atlas_name + ' correlation matrix') out_path_fig = dir_path + '/' + ID + '_' + atlas_name + '_adj_mat_corr.png' plt.savefig(out_path_fig) plt.close() ##Tweak edge_threshold to keep only the strongest connections. atlast_graph_title = atlas_name + ' correlation graph' if mask is None: atlast_graph_title = atlas_name + ' correlation graph' else: atlast_graph_title = atlas_name + ' Masked Nodes' edge_threshold = str(float(thr) * 100) + '%' if all_nets != None: # coloring code: n = len(membership.unique()) clust_pal = sns.color_palette("Set1", n) clust_lut = dict( zip(map(str, np.unique(membership.astype('category'))), clust_pal)) clust_colors = colors.to_rgba_array(membership.map(clust_lut)) plotting.plot_connectome(correlation_matrix, coords, node_color=clust_colors, title=atlast_graph_title, edge_threshold=edge_threshold, node_size=20, colorbar=True) else: plotting.plot_connectome(correlation_matrix, coords, title=atlast_graph_title, edge_threshold=edge_threshold, node_size=20, colorbar=True) out_path_fig = dir_path + '/' + ID + '_' + atlas_name + '_connectome_viz.png' plt.savefig(out_path_fig) plt.close() time_series_path = dir_path + '/' + ID + '_ts.txt' np.savetxt(time_series_path, time_series, delimiter='\t') mx = genfromtxt(time_series_path, delimiter='') elif '.nii' in input_file and NETWORK != None: func_file = input_file ##Reference RSN list load_path = pynets_dir + '/RSN_refs/' + NETWORK + '_coords.csv' df = pd.read_csv(load_path).ix[:, 0:4] i = 1 coords = [] labels = [] for i in range(len(df)): print("ROI Reference #: " + str(i)) x = int(df.ix[i, 1]) y = int(df.ix[i, 2]) z = int(df.ix[i, 3]) print("X:" + str(x) + " Y:" + str(y) + " Z:" + str(z)) coords.append((x, y, z)) labels.append(i) print("\n") print(coords) print(labels) print("\n") print("-------------------") i + 1 dir_path = os.path.dirname(os.path.realpath(func_file)) ##Grow ROIs ##If masking, remove those coords that fall outside of the mask if mask != None: from nilearn import masking mask_data, _ = masking._load_mask_img(mask) mask_coords = list(zip(*np.where(mask_data != 0))) for coord in coords: if coord in mask_coords: print('Removing coordinate: ' + str(coord) + ' since it falls outside of network mask...') coords.remove(coord) masker = input_data.NiftiSpheresMasker(seeds=coords, radius=float(node_size), allow_overlap=True, memory_level=5, memory='nilearn_cache', verbose=2) time_series = masker.fit_transform(func_file) for time_serie, label in zip(time_series.T, labels): plt.plot(time_serie, label=label) plt.title(NETWORK + ' Network Time Series') plt.xlabel('Scan Number') plt.ylabel('Normalized Signal') plt.legend() plt.tight_layout() out_path_fig = dir_path + '/' + ID + '_' + NETWORK + '_TS_plot.png' plt.savefig(out_path_fig) plt.close() connectivity_measure = ConnectivityMeasure(kind='correlation') correlation_matrix = connectivity_measure.fit_transform([time_series ])[0] plot_title = NETWORK + ' Network Time Series' plotting.plot_connectome(correlation_matrix, coords, title=plot_title) ##Display connectome with hemispheric projections. title = "Connectivity Projected on the " + NETWORK out_path_fig = dir_path + '/' + ID + '_' + NETWORK + '_connectome_plot.png' plotting.plot_connectome(correlation_matrix, coords, title=title, display_mode='lyrz', output_file=out_path_fig) time_series_path = dir_path + '/' + ID + '_' + NETWORK + '_ts.txt' np.savetxt(time_series_path, time_series, delimiter='\t') mx = genfromtxt(time_series_path, delimiter='') else: DR_st_1 = input_file dir_path = os.path.dirname(os.path.realpath(DR_st_1)) mx = genfromtxt(DR_st_1, delimiter='') from sklearn.covariance import GraphLassoCV, ShrunkCovariance, graph_lasso estimator = GraphLassoCV() try: est = estimator.fit(mx) except: print( "Error: Lasso sparse matrix modeling failed. Check your input time-series data..." ) # emp_cov = covariance.empirical_covariance(mx) # shrunk_cov = covariance.shrunk_covariance(emp_cov, shrinkage=0.8) # Set shrinkage closer to 1 for poorly-conditioned data # # alphaRange = 10.0 ** np.arange(-8,0) # 1e-7 to 1e-1 by order of magnitude # for alpha in alphaRange: # try: # estimator = covariance.graph_lasso(shrunk_cov, alpha) # print("Calculated graph-lasso covariance matrix for alpha=%s"%alpha) # except FloatingPointError: # print("Failed at alpha=%s"%alpha) # estimator = ShrunkCovariance() # est = estimator.fit(mx) if NETWORK != None: est_path = dir_path + '/' + ID + '_' + NETWORK + '_est%s.txt' % ( '_sps_inv' if sps_model else '') else: est_path = dir_path + '/' + ID + '_est%s.txt' % ('_sps_inv' if sps_model else '') if sps_model == False: if NETWORK != None: np.savetxt(est_path, correlation_matrix, delimiter='\t') else: np.savetxt(est_path, correlation_matrix, delimiter='\t') elif sps_model == True: np.savetxt(est_path, estimator.precision_, delimiter='\t') return (mx, est_path)
def fit(self, imgs, y, data_train=None): """Fit the searchlight Parameters ---------- img : Niimg-like object See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg. 4D image. y : 1D array-like Target variable to predict. Must have exactly as many elements as 3D images in img. data_train : np.array, optional Data to train on, if data for training is different from X. Attributes ---------- `scores_` : numpy.ndarray search_light scores. Same shape as input parameter process_mask_img. """ # Compute world coordinates of all in-mask voxels. mask, mask_affine = masking._load_mask_img(self.mask_img) mask_coords = np.where(mask != 0) mask_coords = np.asarray(mask_coords + (np.ones(len(mask_coords[0]), dtype=np.int),)) mask_coords = np.dot(mask_affine, mask_coords)[:3].T # Compute world coordinates of all in-process mask voxels if self.process_mask_img is None: process_mask = mask process_mask_coords = mask_coords else: process_mask, process_mask_affine = \ masking._load_mask_img(self.process_mask_img) process_mask_coords = np.where(process_mask != 0) process_mask_coords = \ np.asarray(process_mask_coords + (np.ones(len(process_mask_coords[0]), dtype=np.int),)) process_mask_coords = np.dot(process_mask_affine, process_mask_coords)[:3].T clf = neighbors.NearestNeighbors(radius=self.radius) A = clf.fit(mask_coords).radius_neighbors_graph(process_mask_coords) del process_mask_coords, mask_coords A = A.tolil() # scores is an 1D array of CV scores with length equals to the number # of voxels in processing mask (columns in process_mask) X = masking._apply_mask_fmri(imgs, nibabel.Nifti1Image(as_ndarray(mask, dtype=np.int8), mask_affine)) estimator = self.estimator if isinstance(estimator, basestring): estimator = ESTIMATOR_CATALOG[estimator]() # From here starts Dima's modifications, added nii_optional argument # to .fit method if data_train is None: scores = search_light(X, y, estimator, A, self.scoring, self.cv, self.n_jobs, self.verbose) else: scores = search_light(X, y, estimator, A, self.scoring, self.cv, self.n_jobs, self.verbose, data_train) scores_3D = np.zeros(process_mask.shape) scores_3D[process_mask] = scores self.scores_ = scores_3D return self
def compute_spheres_values(self, imgs): start_t = time.time() # Force to get a list of imgs even if only one is given imgs_to_check = [imgs] if not isinstance(imgs, list) else imgs # Load Nifti images ref_shape = imgs_to_check[0].dataobj.shape ref_affine = imgs_to_check[0].affine imgs = [] for img in imgs_to_check: # check if image is 4D imgs.append(check_niimg_4d(img)) # Check that all images have same number of volumes if ref_shape != img.dataobj.shape: raise ValueError("All fMRI image must have same shape") if np.array_equal(ref_affine, img.affine): warnings.warn("fMRI images do not have same affine") self.ref_img = imgs[0] # Compute world coordinates of the seeds process_mask_img = check_niimg_3d(self.process_mask_img) process_mask_img = image.resample_to_img( process_mask_img, imgs[0], interpolation='nearest' ) self.process_mask_img = process_mask_img process_mask, process_mask_affine = masking._load_mask_img( process_mask_img ) process_mask_coords = np.where(process_mask != 0) self.vx_mask_coords = process_mask_coords process_mask_coords = coord_transform( process_mask_coords[0], process_mask_coords[1], process_mask_coords[2], process_mask_affine) process_mask_coords = np.asarray(process_mask_coords).T if self.verbose: print("{} seeds found in the mask".format(len(process_mask_coords))) # Compute spheres _, A = _apply_mask_and_get_affinity( process_mask_coords, imgs[0], self.radius, True, mask_img=self.mask_img ) # Number of runs: 1 4D fMRI image / run n_runs = len(imgs) # Number of spheres (or seed voxels) n_spheres = A.shape[0] # Number of volumes in each 4D fMRI image n_conditions = imgs[0].dataobj.shape[3] mask_img = check_niimg_3d(self.mask_img) mask_img = image.resample_img( mask_img, target_affine=imgs[0].affine, target_shape=imgs[0].shape[:3], interpolation='nearest' ) masked_imgs_data = [] for i_run, img in enumerate(imgs): masked_imgs_data.append(masking._apply_mask_fmri(img, mask_img)) # Extract data of each sphere # X will be #spheres x #run x #conditions x #values X = [] for i_sph in range(n_spheres): # Indexes of all voxels included in the current sphere sph_indexes = A.rows[i_sph] if len(sph_indexes) == 0: # Append when no data are available around the process voxel X.append(np.full((n_runs, n_conditions, 1), 0)) print("Empty sphere") else: # Number of voxel in the current sphere n_values = len(sph_indexes) sub_X = np.empty((n_runs, n_conditions, n_values), dtype=object) for i_run, img in enumerate(imgs): for i_cond in range(n_conditions): sub_X[i_run, i_cond] = masked_imgs_data[i_run][i_cond][ sph_indexes] X.append(sub_X) if self.verbose: dt = time.time() - start_t print("Elapsed time to extract spheres values: {:.01f}s".format(dt)) self.spheres_values = X
def parcel_masker(roi, coords, parcel_list, labels, dir_path, ID, perc_overlap): """ Evaluate the affinity of any arbitrary list of parcel nodes for a user-specified ROI mask. Parameters ---------- roi : str File path to binarized/boolean region-of-interest Nifti1Image file. coords : list List of (x, y, z) tuples in mm-space corresponding to a coordinate atlas used or which represent the center-of-mass of each parcellation node. parcel_list : list List of 3D boolean numpy arrays or binarized Nifti1Images corresponding to ROI masks. labels : list List of string labels corresponding to ROI nodes. dir_path : str Path to directory containing subject derivative data for given run. ID : str A subject id or other unique identifier. perc_overlap : float Value 0-1 indicating a threshold of spatial overlap to use as a spatial error cushion in the case of evaluating ROI-mask membership from a given list of parcel masks. Returns ------- coords_adj : list Filtered list of (x, y, z) tuples in mm-space with a spatial affinity for the specified ROI mask. labels_adj : list Filtered list of string labels corresponding to ROI nodes with a spatial affinity for the specified ROI mask. parcel_list_adj : list Filtered list of 3D boolean numpy arrays or binarized Nifti1Images corresponding to ROI masks with a spatial affinity to the specified ROI mask. """ from pynets.core import nodemaker from nilearn.image import resample_img from nilearn import masking import os.path as op mask_img = nib.load(roi) mask_aff = mask_img.affine mask_data, _ = masking._load_mask_img(roi) mask_img.uncache() i = 0 indices = [] for parcel in parcel_list: parcel_vol = np.zeros(mask_data.shape, dtype=bool) parcel_data_reshaped = np.asarray( resample_img(parcel, target_affine=mask_aff, target_shape=mask_data.shape).dataobj) parcel_vol[parcel_data_reshaped == 1] = 1 # Count number of unique voxels where overlap of parcel and mask occurs overlap_count = len( np.unique( np.where((mask_data.astype('uint16') == 1) & (parcel_vol.astype('uint16') == 1)))) # Count number of total unique voxels within the parcel total_count = len( np.unique(np.where((parcel_vol.astype('uint16') == 1)))) # Calculate % overlap try: overlap = float(overlap_count / total_count) except: print( f"\nWarning: No overlap of parcel {labels[i]} with roi mask!\n" ) overlap = float(0) if overlap >= perc_overlap: print( f"{(100 * overlap):.2f}{'% of parcel '}{labels[i]}{' falls within mask...'}" ) else: indices.append(i) i = i + 1 labels_adj = list(labels) coords_adj = list(tuple(x) for x in coords) parcel_list_adj = parcel_list try: for ix in sorted(indices, reverse=True): print(f"{'Removing: '}{labels_adj[ix]}{' at '}{coords_adj[ix]}") del labels_adj[ix], coords_adj[ix], parcel_list_adj[ix] except RuntimeError: print( 'ERROR: Restrictive masking. No parcels remain after masking with brain mask/roi...' ) # Create a resampled 3D atlas that can be viewed alongside mask img for QA resampled_parcels_nii_path = f"{dir_path}/{ID}_parcels_resampled2roimask_{op.basename(roi).split('.')[0]}.nii.gz" resampled_parcels_map_nifti = resample_img( nodemaker.create_parcel_atlas(parcel_list_adj)[0], target_affine=mask_aff, target_shape=mask_data.shape, interpolation='nearest') nib.save(resampled_parcels_map_nifti, resampled_parcels_nii_path) resampled_parcels_map_nifti.uncache() if not coords_adj: raise ValueError( '\nERROR: ROI mask was likely too restrictive and yielded < 2 remaining parcels' ) return coords_adj, labels_adj, parcel_list_adj
def apply_mask(self, series, mask_img): mask_img = _utils.check_niimg_3d(mask_img) mask, mask_affine = masking._load_mask_img(mask_img) mask_img = image.new_img_like(mask_img, mask, mask_affine) mask_data = _utils.as_ndarray(mask_img.get_data(), dtype=np.bool) return series[mask_data].T
def import_mat_func(input_file, ID, atlas_select, NETWORK, pynets_dir, node_size, mask, thr): if '.nii' in input_file and NETWORK == None: func_file=input_file dir_path = os.path.dirname(os.path.realpath(func_file)) atlas = getattr(datasets, 'fetch_%s' % atlas_select)() atlas_name = atlas['description'].splitlines()[0] print("\n") print(atlas_name + ' comes with {0}.'.format(atlas.keys())) print("\n") coords = np.vstack((atlas.rois['x'], atlas.rois['y'], atlas.rois['z'])).T print("\n") print('Stacked atlas coordinates in array of shape {0}.'.format(coords.shape)) print("\n") if mask is not None: from nilearn import masking mask_data, _ = masking._load_mask_img(mask) mask_coords = list(zip(*np.where(mask_data != 0))) for coord in coords: if tuple(coord) not in mask_coords: print('Removing coordinate: ' + str(tuple(coord)) + ' since it falls outside of network mask...') ix = np.where(coords == coord)[0][0] coords = np.delete(coords, ix, axis=0) print(str(len(coords))) spheres_masker = input_data.NiftiSpheresMasker(seeds=coords, radius=float(node_size), memory='nilearn_cache', memory_level=5, verbose=2, standardize=True) time_series = spheres_masker.fit_transform(func_file) correlation_measure = ConnectivityMeasure(kind='correlation') correlation_matrix = correlation_measure.fit_transform([time_series])[0] print("\n") print('Time series has {0} samples'.format(time_series.shape[0])) print("\n") plt.imshow(correlation_matrix, vmin=-1., vmax=1., cmap='RdBu_r', interpolation='nearest') plt.colorbar() plt.title(atlas_name + ' correlation matrix') out_path_fig=dir_path + '/' + ID + '_' + atlas_name + '_adj_mat_cov.png' plt.savefig(out_path_fig) plt.close() # Tweak edge_threshold to keep only the strongest connections. atlast_graph_title = atlas_name + ' correlation graph' if mask is None: atlast_graph_title = atlas_name + ' correlation graph' else: atlast_graph_title = atlas_name + ' Masked Nodes' edge_threshold = str(float(thr)*100) +'%' plotting.plot_connectome(correlation_matrix, coords, title=atlast_graph_title, edge_threshold=edge_threshold, node_size=20, colorbar=True) out_path_fig=dir_path + '/' + ID + '_' + atlas_name + '_connectome_viz.png' plt.savefig(out_path_fig) plt.close() time_series_path = dir_path + '/' + ID + '_ts.txt' np.savetxt(time_series_path, time_series, delimiter='\t') mx = genfromtxt(time_series_path, delimiter='') elif '.nii' in input_file and NETWORK != None: func_file=input_file ##Reference RSN list load_path= pynets_dir + '/RSN_refs/' + NETWORK + '_coords.csv' df = pd.read_csv(load_path).ix[:,0:4] i=1 coords = [] labels = [] for i in range(len(df)): print("ROI Reference #: " + str(i)) x = int(df.ix[i,1]) y = int(df.ix[i,2]) z = int(df.ix[i,3]) print("X:" + str(x) + " Y:" + str(y) + " Z:" + str(z)) coords.append((x, y, z)) labels.append(i) print("\n") print(coords) print(labels) print("\n") print("-------------------") i + 1 dir_path = os.path.dirname(os.path.realpath(func_file)) ##Grow ROIs ##If masking, remove those coords that fall outside of the mask if mask != None: from nilearn import masking mask_data, _ = masking._load_mask_img(mask) mask_coords = list(zip(*np.where(mask_data != 0))) for coord in coords: if coord in mask_coords: print('Removing coordinate: ' + str(coord) + ' since it falls outside of network mask...') coords.remove(coord) masker = input_data.NiftiSpheresMasker( seeds=coords, radius=float(node_size), allow_overlap=True, memory_level=5, memory='nilearn_cache', verbose=2, standardize=True) time_series = masker.fit_transform(func_file) for time_serie, label in zip(time_series.T, labels): plt.plot(time_serie, label=label) plt.title(NETWORK + ' Network Time Series') plt.xlabel('Scan Number') plt.ylabel('Normalized Signal') plt.legend() plt.tight_layout() out_path_fig=dir_path + '/' + ID + '_' + NETWORK + '_TS_plot.png' plt.savefig(out_path_fig) plt.close() connectivity_measure = ConnectivityMeasure(kind='partial correlation') partial_correlation_matrix = connectivity_measure.fit_transform([time_series])[0] plot_title = NETWORK + ' Network Time Series' plotting.plot_connectome(partial_correlation_matrix, coords, title=plot_title) # Display connectome with hemispheric projections. title = "Connectivity Projected on the " + NETWORK out_path_fig=dir_path + '/' + ID + '_' + NETWORK + '_connectome_plot.png' plotting.plot_connectome(partial_correlation_matrix, coords, title=title, display_mode='lyrz', output_file=out_path_fig) time_series_path = dir_path + '/' + ID + '_' + NETWORK + '_ts.txt' np.savetxt(time_series_path, time_series, delimiter='\t') mx = genfromtxt(time_series_path, delimiter='') else: DR_st_1=input_file dir_path = os.path.dirname(os.path.realpath(DR_st_1)) mx = genfromtxt(DR_st_1, delimiter='') from sklearn.covariance import GraphLassoCV, ShrunkCovariance, graph_lasso estimator = GraphLassoCV() try: est = estimator.fit(mx) except: # print("WARNING: Lasso Cross-Validation Failed. Using Shrunk Covariance instead...") # emp_cov = covariance.empirical_covariance(mx) # shrunk_cov = covariance.shrunk_covariance(emp_cov, shrinkage=0.8) # Set shrinkage closer to 1 for poorly-conditioned data # # alphaRange = 10.0 ** np.arange(-8,0) # 1e-7 to 1e-1 by order of magnitude # for alpha in alphaRange: # try: # estimator = covariance.graph_lasso(shrunk_cov, alpha) # print("Calculated graph-lasso covariance matrix for alpha=%s"%alpha) # except FloatingPointError: # print("Failed at alpha=%s"%alpha) estimator = ShrunkCovariance() est = estimator.fit(mx) if NETWORK != None: est_path_cov = dir_path + '/' + ID + '_' + NETWORK + '_est_cov.txt' est_path_sps_inv_cov = dir_path + '/' + ID + '_' + NETWORK + '_est_sps_inv_cov.txt' else: est_path_cov = dir_path + '/' + ID + '_est_cov.txt' est_path_sps_inv_cov = dir_path + '/' + ID + '_est_sps_inv_cov.txt' np.savetxt(est_path_cov, estimator.covariance_, delimiter='\t') np.savetxt(est_path_sps_inv_cov, estimator.precision_, delimiter='\t') return(mx, est_path_cov, est_path_sps_inv_cov)
def coords_masker(roi, coords, labels, error): """ Evaluate the affinity of any arbitrary list of coordinate nodes for a user-specified ROI mask. Parameters ---------- roi : str File path to binarized/boolean region-of-interest Nifti1Image file. coords : list List of (x, y, z) tuples in mm-space corresponding to a coordinate atlas used or which represent the center-of-mass of each parcellation node. labels : list List of string labels corresponding to ROI nodes. error : int Rounded euclidean distance, in units of voxel number, to use as a spatial error cushion in the case of evaluating the spatial affinity of a given list of coordinates to the given ROI mask. Returns ------- coords : list Filtered list of (x, y, z) tuples in mm-space with a spatial affinity for the specified ROI mask. labels : list Filtered list of string labels corresponding to ROI nodes with a spatial affinity for the specified ROI mask. """ from nilearn import masking from pynets.core.nodemaker import mmToVox mask_data, mask_aff = masking._load_mask_img(roi) x_vox = np.diagonal(mask_aff[:3, 0:3])[0] y_vox = np.diagonal(mask_aff[:3, 0:3])[1] z_vox = np.diagonal(mask_aff[:3, 0:3])[2] # mask_coords = list(zip(*np.where(mask_data == True))) coords_vox = [] for i in coords: coords_vox.append(mmToVox(mask_aff, i)) coords_vox = list( tuple(map(lambda y: isinstance(y, float) and int(round(y, 0)), x)) for x in coords_vox) #coords_vox = list(set(list(tuple(x) for x in coords_vox))) bad_coords = [] for coord_vox in coords_vox: sphere_vol = np.zeros(mask_data.shape, dtype=bool) sphere_vol[tuple(coord_vox)] = 1 if (mask_data & sphere_vol).any(): print(f"{coord_vox}{' falls within mask...'}") continue inds = get_sphere(coord_vox, error, (np.abs(x_vox), y_vox, z_vox), mask_data.shape) sphere_vol[tuple(inds.T)] = 1 if (mask_data & sphere_vol).any(): print( f"{coord_vox}{' is within a + or - '}{float(error):.2f}{' mm neighborhood...'}" ) continue bad_coords.append(coord_vox) bad_coords = [x for x in bad_coords if x is not None] indices = [] for bad_coords in bad_coords: indices.append(coords_vox.index(bad_coords)) labels = list(labels) coords = list(tuple(x) for x in coords) try: for ix in sorted(indices, reverse=True): print(f"{'Removing: '}{labels[ix]}{' at '}{coords[ix]}") del labels[ix], coords[ix] except RuntimeError: print( 'ERROR: Restrictive masking. No coords remain after masking with brain mask/roi...' ) if len(coords) <= 1: raise ValueError( '\nERROR: ROI mask was likely too restrictive and yielded < 2 remaining coords' ) return coords, labels
def grow_nodes(bedpostx_dir, coords, node_size, parc, parcel_list, net_parcels_map_nifti, network): from nilearn import masking import nipype.interfaces.fsl as fsl import nipype.pipeline.engine as pe import glob ####Custom inputs#### try: FSLDIR = os.environ['FSLDIR'] except NameError: print('FSLDIR environment variable not set!') nodif_brain_mask_path = bedpostx_dir + '/nodif_brain_mask.nii.gz' input_MNI = FSLDIR + '/data/standard/MNI152_T1_1mm_brain.nii.gz' volumes_dir = bedpostx_dir + '/volumes' ####Custom inputs#### def save_parcel_vols(bedpostx_dir, parcel_list, net_parcels_map_nifti): import os import time if net_parcels_map_nifti: net_parcels_map_file = bedpostx_dir + '/net_parcels_map_nifti.nii.gz' nib.save(net_parcels_map_nifti, net_parcels_map_file) volumes_dir = bedpostx_dir + '/volumes' if not os.path.exists(volumes_dir): os.mkdir(volumes_dir) num_vols = len(parcel_list) i = 0 for vol in parcel_list: out_path = volumes_dir + '/region_' + str(i) + '.nii.gz' nib.save(vol, out_path) i = i + 1 num_vols_pres = float(len(next(os.walk(volumes_dir))[2])) while num_vols_pres < float(num_vols): time.sleep(1) num_vols_pres = float(len(next(os.walk(volumes_dir))[2])) return save_parcel_vols(bedpostx_dir, parcel_list, net_parcels_map_nifti) ##Delete any existing roi spheres del_files_spheres = glob.glob(volumes_dir + '/roi_sphere*') try: for i in del_files_spheres: os.remove(i) except: pass del_files_parcels = glob.glob(volumes_dir + '/roi_parcel*') try: for i in del_files_parcels: os.remove(i) except: pass del_files_points = glob.glob(volumes_dir + '/roi_point*') try: for i in del_files_points: os.remove(i) except: pass if parc == False: x_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[0] y_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[1] z_vox = np.diagonal( masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[2] def mmToVox(mmcoords): voxcoords = ['', '', ''] voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45) voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63) voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36) return voxcoords ##Convert coords back to voxels coords_vox = [] for coord in coords: coords_vox.append(mmToVox(coord)) coords = list(tuple(x) for x in coords_vox) j = 0 for i in coords: ##Grow spheres at ROI X = coords[j][0] Y = coords[j][1] Z = coords[j][2] out_file1 = volumes_dir + '/roi_point_' + str(j) + '.nii.gz' args = '-mul 0 -add 1 -roi ' + str(X) + ' 1 ' + str( Y) + ' 1 ' + str(Z) + ' 1 0 1' maths = fsl.ImageMaths(in_file=input_MNI, op_string=args, out_file=out_file1) os.system(maths.cmdline + ' -odt float') out_file2 = volumes_dir + '/roi_sphere_' + str(j) + '.nii.gz' args = '-kernel sphere ' + str(node_size) + ' -fmean -bin' maths = fsl.ImageMaths(in_file=out_file1, op_string=args, out_file=out_file2) os.system(maths.cmdline + ' -odt float') ##Map ROIs from Standard Space to diffusion Space: ##Applying xfm and input matrix to transform ROI's between diff and MNI using FLIRT, flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'), name='coregister') flirt.inputs.reference = nodif_brain_mask_path flirt.inputs.in_file = out_file2 out_file_diff = out_file2.split('.nii')[0] + '_diff.nii.gz' flirt.inputs.out_file = out_file_diff flirt.inputs.apply_xfm = True flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat' flirt.run() j = j + 1 del_files_points = glob.glob(volumes_dir + '/roi_point*') try: for i in del_files_points: os.remove(i) except: pass else: i = 0 for parcel in os.listdir(volumes_dir): out_file = volumes_dir + '/roi_parcel_' + str(i) + '_diff.nii.gz' flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'), name='coregister') flirt.inputs.reference = nodif_brain_mask_path flirt.inputs.in_file = volumes_dir + '/' + parcel out_file_diff = out_file.split('.nii')[0] + '_diff.nii.gz' flirt.inputs.out_file = out_file_diff flirt.inputs.apply_xfm = True flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat' flirt.run() i = i + 1 def create_seed_mask_file(bedpostx_dir, network): if network: probtrackx_output_dir_path = bedpostx_dir + '/probtrackx_' + network else: probtrackx_output_dir_path = bedpostx_dir + '/probtrackx_Whole_brain' if not os.path.exists(probtrackx_output_dir_path): os.makedirs(probtrackx_output_dir_path) seed_files = glob.glob(bedpostx_dir + '/volumes/*diff.nii.gz') seeds_text = probtrackx_output_dir_path + '/masks.txt' try: os.remove(seeds_text) except OSError: pass seeds_file_list = [] for seed_file in seed_files: seeds_file_list.append(seed_file) f = open(seeds_text, 'w') l1 = map(lambda x: x + '\n', seeds_file_list) f.writelines(l1) f.close() return (seeds_text, probtrackx_output_dir_path) [seeds_text, probtrackx_output_dir_path ] = create_seed_mask_file(bedpostx_dir, network) return (seeds_text, probtrackx_output_dir_path)
def parcel_masker(roi, coords, parcel_list, label_names, dir_path, ID, mask, perc_overlap): from pynets import nodemaker from nilearn.image import resample_img from nilearn import masking import os.path as op if mask and roi == mask: perc_overlap = 0.9 mask_img = nib.load(roi) mask_data, _ = masking._load_mask_img(roi) i = 0 indices = [] for parcel in parcel_list: parcel_vol = np.zeros(mask_data.shape, dtype=bool) parcel_data_reshaped = resample_img( parcel, target_affine=mask_img.affine, target_shape=mask_data.shape).get_fdata() parcel_vol[parcel_data_reshaped == 1] = 1 # Count number of unique voxels where overlap of parcel and mask occurs overlap_count = len( np.unique( np.where((mask_data.astype('uint8') == 1) & (parcel_vol.astype('uint8') == 1)))) # Count number of total unique voxels within the parcel total_count = len( np.unique(np.where((parcel_vol.astype('uint8') == 1)))) # Calculate % overlap try: overlap = float(overlap_count / total_count) except RuntimeWarning: print('\nWarning: No overlap with roi mask!\n') overlap = float(0) if overlap >= perc_overlap: print("%.2f%s%s%s" % (100 * overlap, '% of parcel ', label_names[i], ' falls within roi mask...')) else: indices.append(i) i = i + 1 label_names_adj = list(label_names) coords_adj = list(tuple(x) for x in coords) parcel_list_adj = parcel_list try: for ix in sorted(indices, reverse=True): print("%s%s%s%s" % ('Removing: ', label_names_adj[ix], ' at ', coords_adj[ix])) label_names_adj.pop(ix) coords_adj.pop(ix) parcel_list_adj.pop(ix) except RuntimeError: print( 'ERROR: Restrictive masking. No parcels remain after masking with brain mask/roi...' ) # Create a resampled 3D atlas that can be viewed alongside mask img for QA resampled_parcels_nii_path = "%s%s%s%s%s%s" % ( dir_path, '/', ID, '_parcels_resampled2roimask_', op.basename(roi).split('.')[0], '.nii.gz') resampled_parcels_atlas, _ = nodemaker.create_parcel_atlas(parcel_list_adj) resampled_parcels_map_nifti = resample_img(resampled_parcels_atlas, target_affine=mask_img.affine, target_shape=mask_data.shape) nib.save(resampled_parcels_map_nifti, resampled_parcels_nii_path) mask_img.uncache() resampled_parcels_map_nifti.uncache() if not coords_adj: raise ValueError( '\nERROR: ROI mask was likely too restrictive and yielded < 2 remaining parcels' ) return coords_adj, label_names_adj, parcel_list_adj
def _apply_mask_and_get_affinity(seeds, niimg, radius, allow_overlap, mask_img=None): seeds = list(seeds) affine = niimg.affine # Compute world coordinates of all in-mask voxels. if mask_img is not None: mask_img = check_niimg_3d(mask_img) mask_img = image.resample_img(mask_img, target_affine=affine, target_shape=niimg.shape[:3], interpolation='nearest') mask, _ = masking._load_mask_img(mask_img) mask_coords = list(zip(*np.where(mask != 0))) X = masking._apply_mask_fmri(niimg, mask_img) else: if np.isnan(np.sum(_safe_get_data(niimg))): warnings.warn('The imgs you have fed into fit_transform() contains' ' NaN values which will be converted to zeroes ') X = _safe_get_data(niimg, True).reshape([-1, niimg.shape[3]]).T else: X = _safe_get_data(niimg).reshape([-1, niimg.shape[3]]).T mask_coords = list(np.ndindex(niimg.shape[:3])) # For each seed, get coordinates of nearest voxel nearests = [] for sx, sy, sz in seeds: nearest = np.round(coord_transform(sx, sy, sz, np.linalg.inv(affine))) nearest = nearest.astype(int) nearest = (nearest[0], nearest[1], nearest[2]) try: nearests.append(mask_coords.index(nearest)) except ValueError: nearests.append(None) mask_coords = np.asarray(list(zip(*mask_coords))) mask_coords = coord_transform(mask_coords[0], mask_coords[1], mask_coords[2], affine) mask_coords = np.asarray(mask_coords).T clf = neighbors.NearestNeighbors(radius=radius) A = clf.fit(mask_coords).radius_neighbors_graph(seeds) A = A.tolil() for i, nearest in enumerate(nearests): if nearest is None: continue A[i, nearest] = True # Include the voxel containing the seed itself if not masked mask_coords = mask_coords.astype(int).tolist() for i, seed in enumerate(seeds): try: A[i, mask_coords.index(seed)] = True except ValueError: # seed is not in the mask pass if not allow_overlap: if np.any(A.sum(axis=0) >= 2): raise ValueError('Overlap detected between spheres') return X, A