def ward_adni_rs_fmri(func_files, n_clusters=200): masker = NiftiMasker(mask_strategy='epi', mask_args=dict(opening=1)) masker.fit(func_files) func_masked = masker.transform(func_files) #func_masked = masker.transform_niimgs(func_files, n_jobs=4) func_masked = np.vstack(func_masked) ########################################################################### # Ward ########################################################################### mask = masker.mask_img_.get_data().astype(np.bool) shape = mask.shape connectivity = image.grid_to_graph(n_x=shape[0], n_y=shape[1], n_z=shape[2], mask=mask) # Computing the ward for the first time, this is long... ward = WardAgglomeration(n_clusters=n_clusters, connectivity=connectivity, memory='nilearn_cache') ward.fit(func_masked) ward_labels_unique = np.unique(ward.labels_) ward_labels = ward.labels_ ward_filename = '_'.join(['ward', str(n_clusters)]) img_ward = masker.inverse_transform(ward.labels_) img_ward.to_filename(os.path.join(CACHE_DIR, ward_filename))
def oneSample_ttest(map_list, timeseries, coord): print("hOLII") template = ld.load_timserie_mask() print("alooooo") design_matrix = pd.DataFrame([1] * len(map_list), columns=['intercept']) print("Hasta aqui si") nifti_masker = NiftiMasker(standardize=True, mask_strategy='epi', memory="nilearn_cache", memory_level=2, smoothing_fwhm=8) print("me iamgino que hasta aqui llega.") ts = ants.matrix_to_timeseries(template, timeseries[0]) print("Esto es nuevo") nifti_masker.fit(ts) print("No estoy seguro de donde ha reventado") zf = np.asmatrix(map_list[0].transpose()) imgUsar = nifti_masker.inverse_transform(zf) print("No estoy seguro de donde ha reventado 2") second_level_model = SecondLevelModel().fit(pd.DataFrame(zf), design_matrix=design_matrix) print("Creo que peta aqui") z_map = second_level_model.compute_contrast(output_type='z_score') return z_map
def create_rois_from_clusters(contrast_tmap, mask, threshold=3.09, height_control='brute', cluster_threshold=10, save_path=None): if save_path is not None: if not os.path.exists(save_path): os.makedirs(save_path) thresholded = map_threshold(contrast_tmap, mask, threshold, height_control, cluster_threshold) cluster_map, n_cluster = label(thresholded.get_data() > 0) clusters = [] masker = NiftiMasker(mask_img=mask) masker.fit() mask_affine = nib.load(mask).get_affine() for label_ in range(1, n_cluster + 1): cluster = cluster_map.copy() cluster[cluster_map != label_] = 0 cluster[cluster_map == label_] = 1 cluster = nib.Nifti1Image(cluster, mask_affine) clusters.append(cluster) if save_path is not None: nib.save(cluster, os.path.join(save_path, 'cluster_{0}.nii'.format(label_))) return clusters
def init(subject,layer,filename_irm,filename_mask,filename_stimuli): #we transform the layer and subject variables in order to use them in the input path if subject < 10: subject = '0' + str(subject) else: subject = str(subject) if layer < 10: layer = '0' + str(layer) else: layer = str(layer) print("Initializing tests for subject " + subject + " and layer " + layer + " ...") #we dig out our data from these files and we create the mask in order to have a better rendering in the future plots meanepi = (mean_img(filename_irm)) loaded_stimuli = np.load(filename_stimuli) masker = NiftiMasker(mask_img=filename_mask, detrend=True,standardize=True) masker.fit() fmri_data = masker.transform(filename_irm) fmri_ready = fmri_data[17:-(fmri_data.shape[0]-17-loaded_stimuli.shape[0])] # building the encoding models middle = int(loaded_stimuli.shape[0]/2) y_train = fmri_ready[:middle] y_test = fmri_ready[middle:] X_train = (loaded_stimuli[:middle]) X_test = (loaded_stimuli[middle:]) print("Init done") return X_train,X_test,y_train,y_test,masker,meanepi
def global_mean_within_mni(img: niimg_like) -> float: """Compute the standard deviation of a Nifti 4D file. This is the numerator of the second term of the SFS expression.""" masker = NiftiMasker(mask_strategy="template") masker.fit(img) masked_img = masker.transform(img) return masked_img.mean()
def plot_results(scores, data_path, Y_dim): #plot the result provided by the optimized model unique, counts = np.unique(scores, return_counts=True) maxi = max(unique) occurence = max(counts) print('\nscores max: ', maxi) print('scores equals to 0: ', occurence) print('scores above 0: ', Y_dim[1] - occurence, '\n') #plotting results filename_mask = "/home/brain/datasets/SherlockMerlin_ds001110/sub-12/func/sub-12_task-SherlockMovie_bold_space-MNI152NLin2009cAsym_brainmask.nii.gz" masker = NiftiMasker(mask_img=filename_mask, detrend=True, standardize=True) masker.fit() meanepi = os.path.join(data_path, 'meanepi.nii.gz') score_img = masker.inverse_transform(scores) plotting.plot_roi(score_img, bg_img=meanepi, title="Results of the clustering", cut_coords=5, display_mode='z', aspect=1.25) plt.show() plt.close()
def get_masker(mask): """ Get an initialized, fitted nilearn Masker instance from passed argument. Parameters ---------- mask : str, Nifti1nibabel.nifti1.Nifti1Image, or any nilearn Masker Returns ------- masker : an initialized, fitted instance of a subclass of `nilearn.input_data.base_masker.BaseMasker` """ if isinstance(mask, str): mask = nib.load(mask) if isinstance(mask, nib.nifti1.Nifti1Image): mask = NiftiMasker(mask) if not (hasattr(mask, 'transform') and hasattr(mask, 'inverse_transform')): raise ValueError("mask argument must be a string, a nibabel image," " or a Nilearn Masker instance.") # Fit the masker if needed if not hasattr(mask, 'mask_img_'): mask.fit() return mask
def prior_classifier(meta_file, meta_category): np.random.seed(42) # reproducible parallelisation niimask = nib.load(project_dir + '/data/processed/' + prior_group + mapname + os.sep + prior_group + '_' + str(k) + os.sep + prior_group + '_' + meta_category + '_' + str(k) + '_' + title + '.nii.gz') masker = NiftiMasker(niimask) masker.fit() voxels_in_metaprior = (niimask.get_data() > 0).sum() print('%s: %i non-zero voxels' % (meta_category, voxels_in_metaprior)) FS_stack = None batch_size = 50. n_batches = np.ceil(len(vbm_path) / batch_size) for i_batch in range(int(n_batches)): i_start = i_batch * batch_size i_end = min(i_start + batch_size, len(vbm_path)) FS_batch = masker.transform(vbm_path[int(i_start):int(i_end)]) if FS_stack is None: print 'starting a batch' FS_stack = FS_batch else: FS_stack = np.vstack((FS_stack, FS_batch)) from sklearn.preprocessing import StandardScaler FS_stack = StandardScaler().fit_transform(FS_stack) FS_prior = FS_stack print FS_prior.shape return (meta_category, FS_prior)
def preprocess(num, subj, subj_dir, subj_warp_dir, force_warp=False): bold_path = 'BOLD/task001_run00%i/bold_dico_bold7Tp1_to_subjbold7Tp1.nii.gz' % (num+1) bold_path = os.path.join(DATA_DIR, subj, bold_path) template_path = os.path.join(DATA_DIR, 'templates', 'grpbold7Tp1', 'brain.nii.gz') warp_path = os.path.join(DATA_DIR, subj, 'templates', 'bold7Tp1', 'in_grpbold7Tp1', 'subj2tmpl_warp.nii.gz') output_path = os.path.join(subj_warp_dir, 'run00%i.nii.gz' % num) if force_warp or not os.path.exists(output_path): print 'Warping image #%i...' % num subprocess.call(['fsl5.0-applywarp', '-i', bold_path, '-o', output_path, '-r', template_path, '-w', warp_path, '-d', 'float']) else: print 'Reusing cached warp image #%i' % num print 'Loading image #%i...' % num bold = load(output_path) masker = NiftiMasker(load(MASK_FILE)) # masker = niftimasker(load(MASK_FILE), detrend=true, smoothing_fwhm=4.0, # high_pass=0.01, t_r=2.0, standardize=true) masker.fit() print 'Removing confounds from image #%i...' % num data = masker.transform(bold, confounds(num, subj)) print 'Detrending image #%i...' % num filtered = np.float32(savgol_filter(data, 61, 5, axis=0)) img = masker.inverse_transform(data-filtered) print 'Smoothing image #%i...' % num img = image.smooth_img(img, 4.0) print 'Saving image #%i...' % num save(img, os.path.join(subj_dir, 'run00%i.nii.gz' % num)) print 'Finished with image #%i' % num
def __img_to_tseries(self, filename_img, mask_img, confounds_filename=None, smoothing_fwhm=None, strategy=["minimal"], chunksize=3000): img = nb.load(filename_img) img = resample_to_img(img, mask_img) if confounds_filename is not None: confounds = load_confounds(confounds_filename, strategy=strategy) masker = NiftiMasker(mask_img, smoothing_fwhm=smoothing_fwhm) masker.fit(img) masker.mask_img_ = mask_img tseries = masker.transform(img) if confounds_filename is not None: confounds=confounds.values tseries = clean(tseries, confounds=confounds) else: tseries = clean(tseries) tseries = self.__normalize_data(tseries) darr_tseries = da.from_array(tseries, chunks=(chunksize, tseries.shape[1])) return darr_tseries
def test_masking_first_level_model(): """ Checks that using NiftiMasker when instantiating FirstLevelModel doesn't raise Error when calling generate_report(). """ with InTemporaryDirectory(): shapes, rk = ((7, 8, 7, 15), (7, 8, 7, 16)), 3 mask, fmri_data, design_matrices =\ write_fake_fmri_data_and_design(shapes, rk) masker = NiftiMasker(mask_img=mask) masker.fit(fmri_data) flm = FirstLevelModel(mask_img=masker).fit( fmri_data, design_matrices=design_matrices ) contrast = np.eye(3)[1] report_flm = flm.generate_report( contrast, plot_type='glass', height_control=None, min_distance=15, alpha=0.001, threshold=2.78 ) report_iframe = report_flm.get_iframe() # So flake8 doesn't complain about not using variable (F841) report_iframe del mask, flm, fmri_data, masker
def test_template_closer_to_target(): n_samples = 6 subject_1, mask_img = random_niimg((6, 5, 3, n_samples)) subject_2, _ = random_niimg((6, 5, 3, n_samples)) masker = NiftiMasker(mask_img=mask_img) masker.fit() # Calculate metric between each subject and the average sub_1 = masker.transform(subject_1) sub_2 = masker.transform(subject_2) subs = [subject_1, subject_2] average_img = _rescaled_euclidean_mean(subs, masker) avg_data = masker.transform(average_img) mean_distance_1 = zero_mean_coefficient_determination(sub_1, avg_data) mean_distance_2 = zero_mean_coefficient_determination(sub_2, avg_data) for alignment_method in [ 'permutation', 'ridge_cv', 'scaled_orthogonal', 'optimal_transport', 'diagonal' ]: algo = TemplateAlignment(alignment_method=alignment_method, n_pieces=3, n_bags=2, mask=masker) # Learn template algo.fit(subs) # Assess template is closer to mean than both images template_data = masker.transform(algo.template) template_mean_distance = zero_mean_coefficient_determination( avg_data, template_data) assert template_mean_distance >= mean_distance_1 assert template_mean_distance >= mean_distance_2
def load_data(subjects): subject_ids = list(subjects.keys()) subject_files = list(subjects[i] for i in subject_ids) if subject_files[0].endswith('.csv'): data = np.array([ np.genfromtxt(img).T for img in subject_files ]) voxel_masker = None else: images = [nb.load(img) for img in subject_files] voxel_masker = NiftiMasker() voxel_masker.fit(images) data = np.array([ voxel_masker.transform(img).T for img in images ]) # Reshape to voxel x time x subject data = np.moveaxis(data, 0, -1).copy(order='C') data_file = os.path.abspath('./data.npy') np.save(data_file, data) return subject_ids, data_file, voxel_masker
def get_masker(mask): """Get an initialized, fitted nilearn Masker instance from passed argument. Parameters ---------- mask : str, :class:`nibabel.nifti1.Nifti1Image`, or any nilearn Masker Returns ------- masker : an initialized, fitted instance of a subclass of `nilearn.input_data.base_masker.BaseMasker` """ if isinstance(mask, str): mask = nib.load(mask) if isinstance(mask, nib.nifti1.Nifti1Image): # Coerce to array-image mask = nib.Nifti1Image(mask.get_fdata(), affine=mask.affine, header=mask.header) mask = NiftiMasker(mask) if not (hasattr(mask, "transform") and hasattr(mask, "inverse_transform")): raise ValueError( "mask argument must be a string, a nibabel image, or a Nilearn Masker instance." ) # Fit the masker if needed if not hasattr(mask, "mask_img_"): mask.fit() return mask
def nii2cmu(nifti_file, mask_file=None): with warnings.catch_warnings(): warnings.simplefilter("ignore") image = nib.load(nifti_file) mask = NiftiMasker(mask_strategy='background') if mask_file is None: mask.fit(nifti_file) else: mask.fit(mask_file) header = image.header sform = image.get_sform() voxel_size = header.get_zooms() voxel_activations = np.float64(mask.transform(nifti_file)).transpose() vmask = np.nonzero( np.array( np.reshape(mask.mask_img_.dataobj, (1, np.prod(mask.mask_img_.shape)), order='C')))[1] voxel_coordinates = full_fact(image.shape[0:3])[vmask, ::-1] - 1 voxel_locations = np.array(np.dot(voxel_coordinates, sform[0:3, 0:3])) + sform[:3, 3] return {'data': voxel_activations, 'R': voxel_locations}
def test_overlaid_report(data_img_3d): pytest.importorskip('matplotlib') masker = NiftiMasker(target_affine=np.eye(3) * 8) html = masker.generate_report() assert "Please `fit` the object" in str(html) masker.fit(data_img_3d) html = masker.generate_report() assert '<div class="overlay">' in str(html)
def load_data_VS_whb(pipeline, subj, newmask): # datapath=input("Please enter the path to the preprocessed data:") # mask_path=input("Please enter the path to the MNI based mask files:") # protocol_path=input("Please enter the path to the protocol files:") # ExpType=input("Please enter experiment type you wish to analyze - Perc or Im:") filename_pattern=".nii.gz" datapath="/home/elena/ATTEND/validataset/data/VS/" mask_path="/home/elena/ATTEND/MASKS/" print (subj) print ("Loading the data") # print mask #MNI SPACE subj_path=os.path.join(datapath, subj) #NATIVE SPACE #subj_path=os.path.join(datapath, subjName, 'preprocessed_native') print (subj_path) # path, dirs, files = os.walk(subj_path).next() #NATIVE SPACE #n_run = len(files)/2 #MNI SPACE n_run = 4 #int(len(dirs)) #int(len(files))#len(files)-2 print (n_run) #because apart from run files, coregistration files are also saved in the preprocessed folder, might be subject to change nifti_masker = NiftiMasker(mask_img=newmask, detrend=True, standardize=True) #, memory_level=1, memory="/home/elena/ATTEND/validataset/TEMP/") #print current_mask.shape masked_data=[0]*n_run masked_data_scaled=[0]*n_run min_max_scaler = preprocessing.MinMaxScaler() for r in range (0, n_run): #NATIVE SPACE #run_image = nibabel.load(os.path.join(subj_path, subj+'_native_run'+str(r+1)+filename_pattern)) #smoothed #run_image = nibabel.load(os.path.join(subj_path, subj+'_native_run'+str(r+1)+'_sps6'+filename_pattern)) if pipeline=='fts': run_image = nibabel.load(os.path.join(subj_path, 'r0'+str(r+1), 'to_standard_fts',subj+'.VS''.r0'+str(r+1)+'.tstost.fts' +filename_pattern)) else: if pipeline=='stf': run_image = nibabel.load(os.path.join(subj_path, 'r0'+str(r+1), 'to_standard_stf', 'VS.'+subj+'.r0'+str(r+1)+'.tost_stf' +filename_pattern)) nifti_masker.fit(run_image) masked_data[r] = nifti_masker.transform(run_image) masked_data_scaled[r] = min_max_scaler.fit_transform(masked_data[r]) print (len(masked_data_scaled[r])) print (masked_data_scaled[r].shape) return n_run, masked_data_scaled, nifti_masker
def load_masker(path, **kwargs): params = read_yaml(path + '.yml') mask_img = nib.load(path + '.nii.gz') masker = NiftiMasker(mask_img) masker.set_params(**params) if kwargs: masker.set_params(**kwargs) masker.fit() return masker
def glass_brain(r2_voxels, subject, current_ROI, ROI_name, name): """ Input : Masked results of r2score Take masked data and project it again in a 3D space Ouput : 3D glassbrain of r2score """ # Get one mask and fit it to the corresponding ROI if current_ROI != -1 and current_ROI <= 5: masks_ROIs_filenames = sorted( glob.glob(os.path.join(paths.path2Data, "en/ROIs_masks/", "*.nii"))) ROI_mask = masks_ROIs_filenames[current_ROI] ROI_mask = NiftiMasker(ROI_mask, detrend=True, standardize=True) ROI_mask.fit() unmasked_data = ROI_mask.inverse_transform(r2_voxels) # Get masks and fit a global mask else: masks = [] masks_filenames = sorted( glob.glob( os.path.join(paths.path2Data, "en/fmri_data/masks", "sub_{}".format(subject), "resample*.pkl"))) for file in masks_filenames: with open(file, 'rb') as f: mask = pickle.load(f) masks.append(mask) global_mask = math_img('img>0.5', img=mean_img(masks)) masker = MultiNiftiMasker(global_mask, detrend=True, standardize=True) masker.fit() unmasked_data = masker.inverse_transform(r2_voxels) display = plot_glass_brain(unmasked_data, display_mode='lzry', threshold='auto', colorbar=True, title='Sub_{}'.format(subject)) if not os.path.exists( os.path.join(paths.path2Figures, 'glass_brain', 'Sub_{}'.format(subject), ROI_name)): os.makedirs( os.path.join(paths.path2Figures, 'glass_brain', 'Sub_{}'.format(subject), ROI_name)) display.savefig( os.path.join(paths.path2Figures, 'glass_brain', 'Sub_{}'.format(subject), ROI_name, 'R_squared_test_{}.png'.format(name))) print( 'Figure Path : ', os.path.join(paths.path2Figures, 'glass_brain', 'Sub_{}'.format(subject), ROI_name, 'R_squared_test_{}.png'.format(name))) display.close()
def compute_global_masker(rootdir, FWHM=None): ''' Define the mask that will be applied onto fMRI data ''' mask = os.path.join(rootdir, 'spm12/tpm/mask_ICV.nii') global_mask = math_img('img>0', img=mask) masker = NiftiMasker(mask_img=global_mask, smoothing_fwhm=FWHM) masker.fit() return masker
def assert_algo_transform_almost_exactly(algo, img1, img2, mask=None): """ Tests that the given algorithm manage to transform almost exactly Nifti\ image img1 into Nifti Image img2 """ algo.fit(img1, img2) imtest = algo.transform(img1) masker = NiftiMasker(mask_img=mask) masker.fit() assert_array_almost_equal(masker.transform( img2), masker.transform(imtest), decimal=6)
def nii2cmu(nifti_file, mask_file=None): def fullfact(dims): ''' Replicates MATLAB's fullfact function (behaves the same way) ''' vals = np.asmatrix(range(1, dims[0] + 1)).T if len(dims) == 1: return vals else: aftervals = np.asmatrix(fullfact(dims[1:])) inds = np.asmatrix(np.zeros((np.prod(dims), len(dims)))) row = 0 for i in range(aftervals.shape[0]): inds[row:(row + len(vals)), 0] = vals inds[row:(row + len(vals)), 1:] = np.tile(aftervals[i, :], (len(vals), 1)) row += len(vals) return inds with warnings.catch_warnings(): warnings.simplefilter("ignore") img = nib.load(nifti_file) mask = NiftiMasker(mask_strategy='background') if mask_file is None: mask.fit(nifti_file) else: mask.fit(mask_file) hdr = img.header S = img.get_sform() vox_size = hdr.get_zooms() im_size = img.shape if len(img.shape) > 3: N = img.shape[3] else: N = 1 Y = np.float64(mask.transform(nifti_file)).copy() vmask = np.nonzero( np.array( np.reshape(mask.mask_img_.dataobj, (1, np.prod(mask.mask_img_.shape)), order='C')))[1] vox_coords = fullfact(img.shape[0:3])[vmask, ::-1] - 1 R = np.array(np.dot(vox_coords, S[0:3, 0:3])) + S[:3, 3] null_inds = ~np.all(Y == Y[0, :], axis=0) Y = Y[:, null_inds] R = R[null_inds] return Y, R
def _nifti_to_brain(nifti, mask_file=None): """ Takes or loads nifti file and converts to brain object Parameters ---------- nifti : str or nifti image If nifti is a nifti filepath, loads nifti and returns brain object If nifti is a nifti image, it returns a brain object Returns ---------- results: brain object """ from .nifti import Nifti if type(nifti) is Nifti: img = nifti elif type(nifti) is nib.nifti1.Nifti1Image: img = nifti elif type(nifti) is str: if os.path.exists(nifti): img = nib.load(nifti) else: warnings.warn('Nifti format not supported') else: warnings.warn('Nifti format not supported') mask = NiftiMasker(mask_strategy='background') if mask_file is None: mask.fit(nifti) else: mask.fit(mask_file) hdr = img.header S = img.get_sform() Y = np.float64(mask.transform(nifti)).copy() vmask = np.nonzero( np.array( np.reshape(mask.mask_img_.dataobj, (1, np.prod(mask.mask_img_.shape)), order='C')))[1] vox_coords = _fullfact(img.shape[0:3])[vmask, ::-1] - 1 R = np.array(np.dot(vox_coords, S[0:3, 0:3])) + S[:3, 3] return Y, R, {'header': hdr, 'unscaled_timing': True}
def compute_global_masker(files, **kwargs): # [[path, path2], [path3, path4]] """Returns a NiftiMasker object from list (of list) of files. Arguments: - files: list (of list of str) Returns: - masker: NiftiMasker """ masks = [compute_epi_mask(f) for f in files] global_mask = math_img('img>0.95', img=mean_img(masks)) # take the average mask and threshold at 0.5 masker = NiftiMasker(global_mask, **kwargs) masker.fit() return masker
def _gen_report(): """ Generate an empty HTMLReport for testing """ data = np.zeros((9, 9, 9)) data[3:-3, 3:-3, 3:-3] = 10 data_img_3d = Nifti1Image(data, np.eye(4)) # turn off reporting mask = NiftiMasker() mask.fit(data_img_3d) report = mask.generate_report() return report
def load_data(): with open(expanduser('~/data/HCP_unmasked/data.json'), 'r') as f: data = json.load(f) for this_data in data: this_data['array'] += '.npy' mask_img = expanduser('~/data/HCP_mask/mask_img.nii.gz') masker = NiftiMasker(mask_img=mask_img, smoothing_fwhm=4, standardize=True) masker.fit() smith2009 = fetch_atlas_smith_2009() init = smith2009.rsn70 dict_init = masker.transform(init) return masker, dict_init, sorted(data, key=lambda t: t['filename'])
def save_difference(model1, model2, FWHM=None): """ Compute the group-level significance of the paired difference between two models """ # Compute masker for data mask = os.path.join(spm_dir, 'spm12/tpm/mask_ICV.nii') global_mask = math_img('img>0', img=mask) masker = NiftiMasker(mask_img=global_mask, smoothing_fwhm=FWHM) masker.fit() # compute and save the difference of two models compute_model_difference(model1, model2, masker)
def assert_model_align_better_than_identity(algo, img1, img2, mask=None): """ Tests that the given algorithm align Nifti image img1 into Nifti \ Image img2 better than identity. Proficiency is measured through r2 score. """ algo.fit(img1, img2) im_test = algo.transform(img1) masker = NiftiMasker(mask) masker.fit() identity_baseline_score = zero_mean_coefficient_determination( masker.transform(img2), masker.transform(img1)) algo_score = zero_mean_coefficient_determination( masker.transform(img2), masker.transform(im_test)) assert algo_score >= identity_baseline_score
def make_ttest(reg1, reg2): masker = NiftiMasker(nib.load(MASK_FILE), standardize=False) masker.fit() subjects = [1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] a = np.arctanh(join_all_subjects(reg1, subjects, masker)) b = np.arctanh(join_all_subjects(reg2, subjects, masker)) t, prob = ttest_rel(a, b) tt = masker.inverse_transform(t) pp = masker.inverse_transform(prob) return tt, pp
def prepare(): F = glob(DATA_PATH) N = [int(i.split('/')[-1].split('_')[0]) for i in F] print('loaded ukbb files') template = load_mni152_template() mask_img = MASK_PATH m = NiftiMasker(mask_img=mask_img) m.fit() dim = numpy.sum(m.mask_img_.get_data()) print('fitted grey matter mask') with h5py.File(OUT_PATH, "a") as store: if 'name' in store: dname = store['name'] ddata = store['data'] else: dname = store.create_dataset('name', (0, ), maxshape=(None, ), dtype='i') ddata = store.create_dataset('data', (0, dim), maxshape=(None, dim), dtype='f') print('opened hdf5 storage') done = dname[:] for fn, sn in zip(F, N): if sn in done: print(sn, 'exists') continue r = resample_to_img(fn, template) s = smooth_img(r, 8) # disabled for some subanalyses x = m.transform(s) try: i = dname.shape[0] dname.resize(i + 1, axis=0) ddata.resize(i + 1, axis=0) ddata[i] = x dname[i] = sn print(sn, 'processed') except: dname.resize(i - 1, axis=0) ddata.resize(i - 1, axis=0) print('roll back changes and exit') sys.exit() print('finished')
def prior_classifier(meta_file, meta_category): np.random.seed(42) # reprodicible parallelisation print '-' * 80 print 'Current meta prior is %s' % meta_category img = load_img(meta_file) img_data = img.get_data() img_data[img.get_data() < 0] = 0 img_data[img.get_data() > 0] = 1 prior_mask = new_img_like(img, img_data, affine=img.get_affine()) print 'Created NiftiMasker with %i voxels for %s' % ( (prior_mask.get_data() > 0).sum(), meta_category) masker = NiftiMasker(prior_mask) masker.fit() masked_data = masker.transform(vbm_path) z_vbm_data_array = StandardScaler().fit_transform(masked_data) # matrix decomposition method if method == 'pca': matdecomp = PCA(n_components=k, random_state=42) elif method == 'ica': matdecomp = FastICA(n_components=k, random_state=42) elif method == 'sparse_pca': matdecomp = SparsePCA(n_components=k, tol=0.1, random_state=42) matdecomp_loadings = matdecomp.fit_transform(z_vbm_data_array) # visualisation of components matdecomp_weights = matdecomp.components_ nifti_4d_components = masker.inverse_transform(matdecomp_weights) for ii in range(0, k, 9): print 'visualisation of component %i of %i' % (ii + 1, k) cur_nifti = index_img(nifti_4d_components, ii) fname = '%s_%s_%i_comp_%i' % (meta_category, method, k, ii + 1) vis_dir1 = data_dir + '/data/processed/%s_%s_%s_%i/%s' % ( modality, method, prior_group, k, meta_category) if not os.path.exists(vis_dir1): os.makedirs(vis_dir1) plot_stat_map(cur_nifti, cut_coords=(0, 0, 0), display_mode='ortho', colorbar=True, black_bg=True, draw_cross=True, bg_img=project_dir + '/data/raw/colin.nii', output_file='%s/%s.png' % (vis_dir1, fname)) cur_nifti.to_filename('%s/%s.nii.gz' % (vis_dir1, fname)) FS_prior = matdecomp_loadings return (meta_category, FS_prior)
def generate_fmri_data_for_subject(subject, current_ROI): """ Input : Take as input each fmri file. One file = One block Load all fmri data and apply a global mask mak on it. The global mask is computed using the mask from each fmri run (block). Applying a global mask for a subject uniformize the data. Output: Output fmri_runs for a subject, corrected using a global mask """ # Get all paths for fmri data fmri_filenames = sorted(glob.glob(os.path.join(paths.rootpath, "fmri-data/en", "sub-%03d" % subject, "func", "resampled*.nii"))) # Process for All brain if current_ROI == -1: # Get paths for masks masks_filenames = sorted(glob.glob(os.path.join(paths.path2Data, "en/fmri_data/masks", "sub_{}".format(subject), "resample*.pkl"))) masks = [] for file in masks_filenames: with open(file, 'rb') as f: mask = pickle.load(f) masks.append(mask) # Compute a global mask for all subject. This way the data will be uniform global_mask = math_img('img>0.5', img=mean_img(masks)) masker = MultiNiftiMasker(global_mask, detrend=True, standardize=True) masker.fit() # Apply the mask to each fmri run (block) fmri_runs = [masker.transform(f) for f in tqdm(fmri_filenames)] # Process for a specific ROI else: # get paths of ROIs masks masks_ROIs_filenames = sorted(glob.glob(os.path.join(paths.path2Data, "en/ROIs_masks/", "*.nii"))) # Choose the mask ROI_mask = masks_ROIs_filenames[current_ROI] ROI_mask = NiftiMasker(ROI_mask, detrend=True, standardize=True) ROI_mask.fit() # Apply the mask to each fmri run (block) fmri_runs = [ROI_mask.transform(f) for f in fmri_filenames] return fmri_runs
class SmoothResampleMasker(BaseMasker): def __init__(self, mask_img=None, smoothing_fwhm=None, resampling=None, searchlight=False): self.mask_img = mask_img self.smoothing_fwhm = smoothing_fwhm self.resampling = resampling self.searchlight = searchlight self.masker = None def fit(self): if self.resampling is not None: self.mask_img = resample_img(self.mask_img, target_affine=np.diag(self.resampling * np.ones(3))) self.masker = NiftiMasker(mask_img=self.mask_img) self.masker.fit() return self def transform(self, imgs, confounds=None): smooth_prefix = '' if self.smoothing_fwhm is None else 's%g' % self.smoothing_fwhm resample_prefix = '' if self.smoothing_fwhm is None else 'r%g' % self.smoothing_fwhm if not isinstance(imgs, list): imgs = [imgs] path_first = imgs[0] if isinstance(imgs[0], str) else imgs[0].get_filename() path_first_resampled = os.path.join(os.path.dirname(path_first), resample_prefix + os.path.basename(path_first)) path_first_smoothed = os.path.join(os.path.dirname(path_first), smooth_prefix + resample_prefix + os.path.basename(path_first)) if self.resampling is not None and self.smoothing_fwhm is not None: if self.resampling is not None: if not os.path.exists(path_first_resampled) and not os.path.exists(path_first_smoothed): imgs = resample_img(imgs, target_affine=np.diag(self.resampling * np.ones(3))) else: imgs = [] if self.smoothing_fwhm is not None: if not os.path.exists(path_first_smoothed): imgs = smooth_img(imgs, self.smoothing_fwhm) else: imgs = [] else: imgs = [check_niimg_3d(img) for img in imgs] return self.masker.transform(imgs)
def main(output_dir, n_jobs): dir_list = [join(output_dir, f) for f in os.listdir(output_dir) if os.path.isdir(join(output_dir, f))] mask, func_filenames = get_hcp_data(raw=True) masker = NiftiMasker(mask_img=mask, smoothing_fwhm=None, standardize=False) masker.fit() test_data = func_filenames[(-n_test_records * 2)::2] n_samples, n_voxels = np.load(test_data[-1], mmap_mode='r').shape X = np.empty((n_test_records * n_samples, n_voxels)) for i, this_data in enumerate(test_data): X[i * n_samples:(i + 1) * n_samples] = np.load(this_data, mmap_mode='r') Parallel(n_jobs=n_jobs, verbose=1, temp_folder='/dev/shm')( delayed(analyse_dir)(dir_name, X, masker) for dir_name in dir_list)
def get_init_objective(output_dir): mask, func_filenames = get_hcp_data(raw=True) masker = NiftiMasker(mask_img=mask, smoothing_fwhm=None, standardize=False) masker.fit() rsn70 = fetch_atlas_smith_2009().rsn70 components = masker.transform(rsn70) print(components.shape) enet_scale(components.T, inplace=True) print(np.sum(np.abs(components), axis=1)) test_data = func_filenames[(-n_test_records * 2)::2] n_samples, n_voxels = np.load(test_data[-1], mmap_mode='r').shape X = np.empty((n_test_records * n_samples, n_voxels)) for i, this_data in enumerate(test_data): X[i * n_samples:(i + 1) * n_samples] = np.load(this_data, mmap_mode='r') exp_var = {} for alpha in [1e-2, 1e-3, 1e-4]: exp_var[alpha] = objective_function(X, components, alpha) json.dump(open(join(output_dir, 'init_objective.json'), 'r'))
# From already masked data from nilearn.input_data import NiftiMasker # Load Miyawaki dataset miyawaki = datasets.fetch_miyawaki2008() miyawaki_img = nibabel.load(miyawaki.func[0]) miyawaki_func = miyawaki_img.get_data() background = np.mean(miyawaki_func, axis=-1)[..., 14] # This time, we can use the NiftiMasker without changing the default mask # strategy, as the data has already been masked, and thus lies on a # homogeneous background masker = NiftiMasker() masker.fit(miyawaki_img) default_mask = masker.mask_img_.get_data().astype(np.bool) plt.figure(figsize=(4, 4.5)) display_mask(background, default_mask[..., 14], 'Default background mask') plt.tight_layout() ############################################################################### # From raw EPI data # Load NYU resting-state dataset nyu = datasets.fetch_nyu_rest(n_subjects=1) nyu_img = nibabel.load(nyu.func[0]) # Restrict nyu to 100 frames to speed up computation nyu_func = nyu_img.get_data()[..., :100]
class SecondLevelModel(BaseEstimator, TransformerMixin, CacheMixin): """ Implementation of the General Linear Model for multiple subject fMRI data Parameters ---------- mask: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional, Mask to be used on data. If an instance of masker is passed, then its mask will be used. If no mask is given, it will be computed automatically by a MultiNiftiMasker with default parameters. Automatic mask computation assumes first level imgs have already been masked. smoothing_fwhm: float, optional If smoothing_fwhm is not None, it gives the size in millimeters of the spatial smoothing to apply to the signal. memory: string, optional Path to the directory used to cache the masking process and the glm fit. By default, no caching is done. Creates instance of joblib.Memory. memory_level: integer, optional Rough estimator of the amount of memory used by caching. Higher value means more memory for caching. verbose : integer, optional Indicate the level of verbosity. By default, nothing is printed. If 0 prints nothing. If 1 prints final computation time. If 2 prints masker computation details. n_jobs : integer, optional The number of CPUs to use to do the computation. -1 means 'all CPUs', -2 'all CPUs but one', and so on. minimize_memory : boolean, optional Gets rid of some variables on the model fit results that are not necessary for contrast computation and would only be useful for further inspection of model details. This has an important impact on memory consumption. True by default. """ def __init__(self, mask=None, smoothing_fwhm=None, memory=Memory(None), memory_level=1, verbose=0, n_jobs=1, minimize_memory=True): self.mask = mask self.smoothing_fwhm = smoothing_fwhm if isinstance(memory, _basestring): self.memory = Memory(memory) else: self.memory = memory self.memory_level = memory_level self.verbose = verbose self.n_jobs = n_jobs self.minimize_memory = minimize_memory self.second_level_input_ = None self.confounds_ = None def fit(self, second_level_input, confounds=None, design_matrix=None): """ Fit the second-level GLM 1. create design matrix 2. do a masker job: fMRI_data -> Y 3. fit regression to (Y, X) Parameters ---------- second_level_input: list of `FirstLevelModel` objects or pandas DataFrame or list of Niimg-like objects. Giving FirstLevelModel objects will allow to easily compute the second level contast of arbitrary first level contrasts thanks to the first_level_contrast argument of the compute_contrast method. Effect size images will be computed for each model to contrast at the second level. If a pandas DataFrame, then they have to contain subject_label, map_name and effects_map_path. It can contain multiple maps that would be selected during contrast estimation with the argument first_level_contrast of the compute_contrast function. The DataFrame will be sorted based on the subject_label column to avoid order inconsistencies when extracting the maps. So the rows of the automatically computed design matrix, if not provided, will correspond to the sorted subject_label column. If list of Niimg-like objects then this is taken literally as Y for the model fit and design_matrix must be provided. confounds: pandas DataFrame, optional Must contain a subject_label column. All other columns are considered as confounds and included in the model. If design_matrix is provided then this argument is ignored. The resulting second level design matrix uses the same column names as in the given DataFrame for confounds. At least two columns are expected, "subject_label" and at least one confound. design_matrix: pandas DataFrame, optional Design matrix to fit the GLM. The number of rows in the design matrix must agree with the number of maps derived from second_level_input. Ensure that the order of maps given by a second_level_input list of Niimgs matches the order of the rows in the design matrix. """ # Check parameters # check first level input if isinstance(second_level_input, list): if len(second_level_input) < 2: raise ValueError('A second level model requires a list with at' 'least two first level models or niimgs') # Check FirstLevelModel objects case if isinstance(second_level_input[0], FirstLevelModel): models_input = enumerate(second_level_input) for model_idx, first_level_model in models_input: if (first_level_model.labels_ is None or first_level_model.results_ is None): raise ValueError( 'Model %s at index %i has not been fit yet' '' % (first_level_model.subject_label, model_idx)) if not isinstance(first_level_model, FirstLevelModel): raise ValueError(' object at idx %d is %s instead of' ' FirstLevelModel object' % (model_idx, type(first_level_model))) if confounds is not None: if first_level_model.subject_label is None: raise ValueError( 'In case confounds are provided, first level ' 'objects need to provide the attribute ' 'subject_label to match rows appropriately.' 'Model at idx %d does not provide it. ' 'To set it, you can do ' 'first_level_model.subject_label = "01"' '' % (model_idx)) # Check niimgs case elif isinstance(second_level_input[0], (str, Nifti1Image)): if design_matrix is None: raise ValueError('List of niimgs as second_level_input' ' require a design matrix to be provided') for model_idx, niimg in enumerate(second_level_input): if not isinstance(niimg, (str, Nifti1Image)): raise ValueError(' object at idx %d is %s instead of' ' Niimg-like object' % (model_idx, type(niimg))) # Check pandas dataframe case elif isinstance(second_level_input, pd.DataFrame): for col in ['subject_label', 'map_name', 'effects_map_path']: if col not in second_level_input.columns: raise ValueError('second_level_input DataFrame must have' ' columns subject_label, map_name and' ' effects_map_path') # Make sure subject_label contain strings second_level_columns = second_level_input.columns.tolist() labels_index = second_level_columns.index('subject_label') labels_dtype = second_level_input.dtypes[labels_index] if not isinstance(labels_dtype, np.object): raise ValueError('subject_label column must be of dtype ' 'object instead of dtype %s' % labels_dtype) elif isinstance(second_level_input, (str, Nifti1Image)): if design_matrix is None: raise ValueError('List of niimgs as second_level_input' ' require a design matrix to be provided') second_level_input = check_niimg(niimg=second_level_input, ensure_ndim=4) else: raise ValueError('second_level_input must be a list of' ' `FirstLevelModel` objects, a pandas DataFrame' ' or a list Niimg-like objects. Instead %s ' 'was provided' % type(second_level_input)) # check confounds if confounds is not None: if not isinstance(confounds, pd.DataFrame): raise ValueError('confounds must be a pandas DataFrame') if 'subject_label' not in confounds.columns: raise ValueError('confounds DataFrame must contain column' '"subject_label"') if len(confounds.columns) < 2: raise ValueError('confounds should contain at least 2 columns' 'one called "subject_label" and the other' 'with a given confound') # Make sure subject_label contain strings labels_index = confounds.columns.tolist().index('subject_label') labels_dtype = confounds.dtypes[labels_index] if not isinstance(labels_dtype, np.object): raise ValueError('subject_label column must be of dtype ' 'object instead of dtype %s' % labels_dtype) # check design matrix if design_matrix is not None: if not isinstance(design_matrix, pd.DataFrame): raise ValueError('design matrix must be a pandas DataFrame') # sort a pandas dataframe by subject_label to avoid inconsistencies # with the design matrix row order when automatically extracting maps if isinstance(second_level_input, pd.DataFrame): columns = second_level_input.columns.tolist() column_index = columns.index('subject_label') sorted_matrix = sorted( second_level_input.values, key=lambda x: x[column_index]) sorted_input = pd.DataFrame(sorted_matrix, columns=columns) second_level_input = sorted_input self.second_level_input_ = second_level_input self.confounds_ = confounds # Report progress t0 = time.time() if self.verbose > 0: sys.stderr.write("Fitting second level model. " "Take a deep breath\r") # Select sample map for masker fit and get subjects_label for design if isinstance(second_level_input, pd.DataFrame): sample_map = second_level_input['effects_map_path'][0] labels = second_level_input['subject_label'] subjects_label = labels.values.tolist() elif isinstance(second_level_input, Nifti1Image): sample_map = mean_img(second_level_input) elif isinstance(second_level_input[0], FirstLevelModel): sample_model = second_level_input[0] sample_condition = sample_model.design_matrices_[0].columns[0] sample_map = sample_model.compute_contrast( sample_condition, output_type='effect_size') labels = [model.subject_label for model in second_level_input] subjects_label = labels else: # In this case design matrix had to be provided sample_map = mean_img(second_level_input) # Create and set design matrix, if not given if design_matrix is None: design_matrix = make_second_level_design_matrix(subjects_label, confounds) self.design_matrix_ = design_matrix # Learn the mask. Assume the first level imgs have been masked. if not isinstance(self.mask, NiftiMasker): self.masker_ = NiftiMasker( mask_img=self.mask, smoothing_fwhm=self.smoothing_fwhm, memory=self.memory, verbose=max(0, self.verbose - 1), memory_level=self.memory_level) else: self.masker_ = clone(self.mask) for param_name in ['smoothing_fwhm', 'memory', 'memory_level']: our_param = getattr(self, param_name) if our_param is None: continue if getattr(self.masker_, param_name) is not None: warn('Parameter %s of the masker overriden' % param_name) setattr(self.masker_, param_name, our_param) self.masker_.fit(sample_map) # Report progress if self.verbose > 0: sys.stderr.write("\nComputation of second level model done in " "%i seconds\n" % (time.time() - t0)) return self def compute_contrast( self, second_level_contrast=None, first_level_contrast=None, second_level_stat_type=None, output_type='z_score'): """Generate different outputs corresponding to the contrasts provided e.g. z_map, t_map, effects and variance. Parameters ---------- second_level_contrast: str or array of shape (n_col), optional Where ``n_col`` is the number of columns of the design matrix, The string can be a formula compatible with the linear constraint of the Patsy library. Basically one can use the name of the conditions as they appear in the design matrix of the fitted model combined with operators /\*+- and numbers. Please check the patsy documentation for formula examples: http://patsy.readthedocs.io/en/latest/API-reference.html#patsy.DesignInfo.linear_constraint The default (None) is accepted if the design matrix has a single column, in which case the only possible contrast array([1]) is applied; when the design matrix has multiple columns, an error is raised. first_level_contrast: str or array of shape (n_col) with respect to FirstLevelModel, optional In case a list of FirstLevelModel was provided as second_level_input, we have to provide a contrast to apply to the first level models to get the corresponding list of images desired, that would be tested at the second level. In case a pandas DataFrame was provided as second_level_input this is the map name to extract from the pandas dataframe map_name column. It has to be a 't' contrast. second_level_stat_type: {'t', 'F'}, optional Type of the second level contrast output_type: str, optional Type of the output map. Can be 'z_score', 'stat', 'p_value', 'effect_size' or 'effect_variance' Returns ------- output_image: Nifti1Image The desired output image """ if self.second_level_input_ is None: raise ValueError('The model has not been fit yet') # first_level_contrast check if isinstance(self.second_level_input_[0], FirstLevelModel): if first_level_contrast is None: raise ValueError('If second_level_input was a list of ' 'FirstLevelModel, then first_level_contrast ' 'is mandatory. It corresponds to the ' 'second_level_contrast argument of the ' 'compute_contrast method of FirstLevelModel') # check contrast definition if second_level_contrast is None: if self.design_matrix_.shape[1] == 1: second_level_contrast = np.ones([1]) else: raise ValueError('No second-level contrast is specified.') if isinstance(second_level_contrast, np.ndarray): con_val = second_level_contrast if np.all(con_val == 0): raise ValueError('Contrast is null') else: design_info = DesignInfo(self.design_matrix_.columns.tolist()) constraint = design_info.linear_constraint(second_level_contrast) con_val = constraint.coefs # check output type if isinstance(output_type, _basestring): if output_type not in ['z_score', 'stat', 'p_value', 'effect_size', 'effect_variance']: raise ValueError( 'output_type must be one of "z_score", "stat"' ', "p_value", "effect_size" or "effect_variance"') else: raise ValueError('output_type must be one of "z_score", "stat",' ' "p_value", "effect_size" or "effect_variance"') # Get effect_maps appropriate for chosen contrast effect_maps = _infer_effect_maps(self.second_level_input_, first_level_contrast) # Check design matrix X and effect maps Y agree on number of rows if len(effect_maps) != self.design_matrix_.shape[0]: raise ValueError( 'design_matrix does not match the number of maps considered. ' '%i rows in design matrix do not match with %i maps' % (self.design_matrix_.shape[0], len(effect_maps))) # Fit an Ordinary Least Squares regression for parametric statistics Y = self.masker_.transform(effect_maps) if self.memory: mem_glm = self.memory.cache(run_glm, ignore=['n_jobs']) else: mem_glm = run_glm labels, results = mem_glm(Y, self.design_matrix_.values, n_jobs=self.n_jobs, noise_model='ols') # We save memory if inspecting model details is not necessary if self.minimize_memory: for key in results: results[key] = SimpleRegressionResults(results[key]) self.labels_ = labels self.results_ = results # We compute contrast object if self.memory: mem_contrast = self.memory.cache(compute_contrast) else: mem_contrast = compute_contrast contrast = mem_contrast(self.labels_, self.results_, con_val, second_level_stat_type) # We get desired output from contrast object estimate_ = getattr(contrast, output_type)() # Prepare the returned images output = self.masker_.inverse_transform(estimate_) contrast_name = str(con_val) output.header['descrip'] = ( '%s of contrast %s' % (output_type, contrast_name)) return output
def get_masker(): masker = NiftiMasker(nib.load(MASK_FILE), standardize=True, memory=memory) masker.fit() return masker
The mask is computed and visualized. """ ### Load nyu_rest dataset ##################################################### from nilearn import datasets from nilearn.input_data import NiftiMasker dataset = datasets.fetch_nyu_rest(n_subjects=1) ### Compute the mask ########################################################## # As this is raw resting-state EPI, the background is noisy and we cannot # rely on the 'background' masking strategy. We need to use the 'epi' one nifti_masker = NiftiMasker(standardize=False, mask_strategy='epi', memory="nilearn_cache", memory_level=2) nifti_masker.fit(dataset.func[0]) mask = nifti_masker.mask_img_.get_data() ### Visualize the mask ######################################################## import matplotlib.pyplot as plt import numpy as np import nibabel plt.figure() plt.axis('off') plt.imshow(np.rot90(nibabel.load(dataset.func[0]).get_data()[..., 20, 0]), interpolation='nearest', cmap=plt.cm.gray) ma = np.ma.masked_equal(mask, False) plt.imshow(np.rot90(ma[..., 20]), interpolation='nearest', cmap=plt.cm.autumn, alpha=0.5) plt.title("Mask")
class Hurst_Estimator(BaseEstimator, TransformerMixin): """This class makes Hurst coefficient estimation for Niftii file easier. First one should initialise the Niftii Masker with the corresponding elements: detrend low_pass high_pass t_r smoothing_fwhm memory memory_level See nilearn.input_data.NiftiMasker for more details One must choose the metric and the regulation: metric: 'wavelet', 'dfa' or 'welch' regu: 'tv', 'l2', 'off' lambda: the ponderation for the regulation cost function Than one can use the fit function and compute the Hurst Exponent load_map for each signal contained in imgs niftii file. """ def __init__(self, mask=None, metric='wavelet', regu='tv', lbda=1, detrend=True, low_pass=.1, high_pass=.01, t_r=1.05, smoothing_fwhm=6., memory='', memory_level=0, n_jobs=1, nb_vanishmoment=2, norm=1, q=np.array(2), nbvoies=None, distn=1, wtype=1, j1=2, j2=8): self.metric = metric self.mask = mask self.n_jobs = n_jobs self.nb_vanishmoment = nb_vanishmoment self.norm = norm self.q = q self.nbvoies = nbvoies self.distn = distn self.wtype = wtype self.j1 = j1 self.j2 = j2 self.regu = regu self.lbda = lbda if self.mask is None: self.masker = NiftiMasker(detrend=detrend, low_pass=low_pass, high_pass=high_pass, t_r=t_r, smoothing_fwhm=smoothing_fwhm, standardize=False, memory_level=memory_level, verbose=0) else: self.masker = NiftiMasker(mask_img=self.mask, detrend=detrend, low_pass=low_pass, high_pass=high_pass, t_r=t_r, smoothing_fwhm=smoothing_fwhm, standardize=False, memory_level=memory_level, verbose=0) self.masker.fit(self.mask) def fit(self, imgs): """ compute connectivities """ if self.metric == 'wavelet': jobs = (delayed(wavelet_worker)(img, self.masker, self.regu, self.lbda, self.nb_vanishmoment, self.norm, self.q, self.nbvoies, self.distn, self.wtype, self.j1, self.j2) for img in imgs) elif self.metric == 'dfa': jobs = (delayed(dfa_worker)(img, self.masker, self.regu, self.lbda, self.wtype, self.j1, self.j2) for img in imgs) elif self.metric=='welch': jobs = (delayed(welch_worker)(img, self.masker, self.regu, self.lbda, ) for img in imgs) else: raise ValueError("the metric dico = %s is not yet implemented" % (self.metric,)) ts = Parallel(n_jobs=5, verbose=5)(jobs) self.hurst = ts return self.hurst def save(self, save_path='', save_file=None): if not 'hurst' in dir(self): os.write(1, 'Nothing to save !!') return if save_file is None: save_file = 'hurstmap_metric_' + self.metric +'_regu_'+ self.regu + str(self.lbda) save_file = os.path.join(save_path, save_file) with open(save_file,'wb') as myfile: monpickler = pickle.Pickler(myfile) monpickler.dump(self.hurst) def load_map(self, INPUT_PATH='', save_file=None): if save_file is None: save_file = 'hurstmap_metric_' + self.metric +'_regu_'+ self.regu save_file = os.path.join(INPUT_PATH, save_file) with open(save_file,'rb') as myfile: monunpickler = pickle.Unpickler(myfile) self.hurst = monunpickler.load()
###################################################################### # Reshape and mask images # ----------------------- print("\nReshaping and masking images.\n") with warnings.catch_warnings(): warnings.simplefilter('ignore', UserWarning) warnings.simplefilter('ignore', DeprecationWarning) mask_img = load_mni152_brain_mask() masker = NiftiMasker( mask_img=mask_img, memory='nilearn_cache', memory_level=1) masker = masker.fit() # Images may fail to be transformed, and are of different shapes, # so we need to transform one-by-one and keep track of failures. X = [] is_usable = np.ones((len(images),), dtype=bool) for index, image_path in enumerate(images): # load image and remove nan and inf values. # applying smooth_img to an image with fwhm=None simply cleans up # non-finite values but otherwise doesn't modify the image. image = smooth_img(image_path, fwhm=None) try: X.append(masker.transform(image)) except Exception as e: meta = nv_data['images_meta'][index]
data = pd.read_csv(os.path.join(BASE_DIR, 'description_file.csv')) pet_files = [] pet_img = [] for idx, row in data.iterrows(): pet_file = glob.glob(os.path.join(BASE_DIR, 'I' + str(row.Image_ID_y), 'I*.nii')) if len(pet_file)>0: pet_files.append(pet_file[0]) img = nib.load(pet_file[0]) pet_img.append(img) masker = NiftiMasker(mask_strategy='epi', mask_args=dict(opening=8)) masker.fit(pet_files) pet_masked = masker.transform_niimgs(pet_files, n_jobs=2) #pet_masked = np.vstack(pet_masked) mask = masker.mask_img_.get_data().astype(np.bool) shape = mask.shape connectivity = image.grid_to_graph(n_x=shape[0], n_y=shape[1], n_z=shape[2], mask=mask) # Computing the ward for the first time, this is long... start = time.time() ward = WardAgglomeration(n_clusters=1000, connectivity=connectivity, memory='nilearn_cache') ward.fit(pet_masked[0])
# Load Miyawaki dataset miyawaki_dataset = datasets.fetch_miyawaki2008() # print basic information on the dataset print('First functional nifti image (4D) is located at: %s' % miyawaki_dataset.func[0]) # 4D data miyawaki_filename = miyawaki_dataset.func[0] miyawaki_mean_img = image.mean_img(miyawaki_filename) # This time, we can use the NiftiMasker without changing the default mask # strategy, as the data has already been masked, and thus lies on a # homogeneous background masker = NiftiMasker() masker.fit(miyawaki_filename) plot_roi(masker.mask_img_, miyawaki_mean_img, title="Mask from already masked data") ############################################################################### # From raw EPI data # Load NYU resting-state dataset nyu_dataset = datasets.fetch_nyu_rest(n_subjects=1) nyu_filename = nyu_dataset.func[0] nyu_img = nibabel.load(nyu_filename) # Restrict nyu to 100 frames to speed up computation from nilearn.image import index_img
# Display helper background = np.mean(haxby_func, axis=-1)[..., 27] def display_mask(background, mask, title): pl.axis('off') pl.imshow(np.rot90(background), interpolation='nearest', cmap=pl.cm.gray) ma = np.ma.masked_equal(mask, False) pl.imshow(np.rot90(ma), interpolation='nearest', cmap=pl.cm.autumn, alpha=0.5) pl.title(title) # Generate mask with default parameters from nilearn.input_data import NiftiMasker masker = NiftiMasker() masker.fit(haxby_img) default_mask = masker.mask_img_.get_data().astype(np.bool) pl.figure(figsize=(3, 5)) display_mask(background, default_mask[..., 27], 'Default mask') # Generate mask with opening masker = NiftiMasker(mask_opening=0) masker.fit(haxby_img) opening_mask = masker.mask_img_.get_data().astype(np.bool) pl.figure(figsize=(3, 5)) display_mask(background, opening_mask[..., 27], 'Mask without opening') # Generate mask with upper cutoff masker = NiftiMasker(mask_opening=True, mask_upper_cutoff=0.8) masker.fit(haxby_img) cutoff_mask = masker.mask_img_.get_data().astype(np.bool)
class SecondLevelModel(BaseEstimator, TransformerMixin, CacheMixin): """ Implementation of the General Linear Model for multiple subject fMRI data Parameters ---------- mask_img: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional, Mask to be used on data. If an instance of masker is passed, then its mask will be used. If no mask is given, it will be computed automatically by a MultiNiftiMasker with default parameters. Automatic mask computation assumes first level imgs have already been masked. smoothing_fwhm: float, optional If smoothing_fwhm is not None, it gives the size in millimeters of the spatial smoothing to apply to the signal. memory: string, optional Path to the directory used to cache the masking process and the glm fit. By default, no caching is done. Creates instance of joblib.Memory. memory_level: integer, optional Rough estimator of the amount of memory used by caching. Higher value means more memory for caching. verbose : integer, optional Indicate the level of verbosity. By default, nothing is printed. If 0 prints nothing. If 1 prints final computation time. If 2 prints masker computation details. n_jobs : integer, optional The number of CPUs to use to do the computation. -1 means 'all CPUs', -2 'all CPUs but one', and so on. minimize_memory : boolean, optional Gets rid of some variables on the model fit results that are not necessary for contrast computation and would only be useful for further inspection of model details. This has an important impact on memory consumption. True by default. """ @replace_parameters({'mask': 'mask_img'}, end_version='next') def __init__(self, mask_img=None, smoothing_fwhm=None, memory=Memory(None), memory_level=1, verbose=0, n_jobs=1, minimize_memory=True): self.mask_img = mask_img self.smoothing_fwhm = smoothing_fwhm if isinstance(memory, _basestring): self.memory = Memory(memory) else: self.memory = memory self.memory_level = memory_level self.verbose = verbose self.n_jobs = n_jobs self.minimize_memory = minimize_memory self.second_level_input_ = None self.confounds_ = None def fit(self, second_level_input, confounds=None, design_matrix=None): """ Fit the second-level GLM 1. create design matrix 2. do a masker job: fMRI_data -> Y 3. fit regression to (Y, X) Parameters ---------- second_level_input: list of `FirstLevelModel` objects or pandas DataFrame or list of Niimg-like objects. Giving FirstLevelModel objects will allow to easily compute the second level contast of arbitrary first level contrasts thanks to the first_level_contrast argument of the compute_contrast method. Effect size images will be computed for each model to contrast at the second level. If a pandas DataFrame, then they have to contain subject_label, map_name and effects_map_path. It can contain multiple maps that would be selected during contrast estimation with the argument first_level_contrast of the compute_contrast function. The DataFrame will be sorted based on the subject_label column to avoid order inconsistencies when extracting the maps. So the rows of the automatically computed design matrix, if not provided, will correspond to the sorted subject_label column. If list of Niimg-like objects then this is taken literally as Y for the model fit and design_matrix must be provided. confounds: pandas DataFrame, optional Must contain a subject_label column. All other columns are considered as confounds and included in the model. If design_matrix is provided then this argument is ignored. The resulting second level design matrix uses the same column names as in the given DataFrame for confounds. At least two columns are expected, "subject_label" and at least one confound. design_matrix: pandas DataFrame, optional Design matrix to fit the GLM. The number of rows in the design matrix must agree with the number of maps derived from second_level_input. Ensure that the order of maps given by a second_level_input list of Niimgs matches the order of the rows in the design matrix. """ # check second_level_input _check_second_level_input(second_level_input, design_matrix, confounds=confounds) # check confounds _check_confounds(confounds) # check design matrix _check_design_matrix(design_matrix) # sort a pandas dataframe by subject_label to avoid inconsistencies # with the design matrix row order when automatically extracting maps if isinstance(second_level_input, pd.DataFrame): columns = second_level_input.columns.tolist() column_index = columns.index('subject_label') sorted_matrix = sorted( second_level_input.values, key=lambda x: x[column_index]) sorted_input = pd.DataFrame(sorted_matrix, columns=columns) second_level_input = sorted_input self.second_level_input_ = second_level_input self.confounds_ = confounds # Report progress t0 = time.time() if self.verbose > 0: sys.stderr.write("Fitting second level model. " "Take a deep breath\r") # Select sample map for masker fit and get subjects_label for design if isinstance(second_level_input, pd.DataFrame): sample_map = second_level_input['effects_map_path'][0] labels = second_level_input['subject_label'] subjects_label = labels.values.tolist() elif isinstance(second_level_input, Nifti1Image): sample_map = mean_img(second_level_input) elif isinstance(second_level_input[0], FirstLevelModel): sample_model = second_level_input[0] sample_condition = sample_model.design_matrices_[0].columns[0] sample_map = sample_model.compute_contrast( sample_condition, output_type='effect_size') labels = [model.subject_label for model in second_level_input] subjects_label = labels else: # In this case design matrix had to be provided sample_map = mean_img(second_level_input) # Create and set design matrix, if not given if design_matrix is None: design_matrix = make_second_level_design_matrix(subjects_label, confounds) self.design_matrix_ = design_matrix # Learn the mask. Assume the first level imgs have been masked. if not isinstance(self.mask_img, NiftiMasker): self.masker_ = NiftiMasker( mask_img=self.mask_img, smoothing_fwhm=self.smoothing_fwhm, memory=self.memory, verbose=max(0, self.verbose - 1), memory_level=self.memory_level) else: self.masker_ = clone(self.mask_img) for param_name in ['smoothing_fwhm', 'memory', 'memory_level']: our_param = getattr(self, param_name) if our_param is None: continue if getattr(self.masker_, param_name) is not None: warn('Parameter %s of the masker overriden' % param_name) setattr(self.masker_, param_name, our_param) self.masker_.fit(sample_map) # Report progress if self.verbose > 0: sys.stderr.write("\nComputation of second level model done in " "%i seconds\n" % (time.time() - t0)) return self def compute_contrast( self, second_level_contrast=None, first_level_contrast=None, second_level_stat_type=None, output_type='z_score'): """Generate different outputs corresponding to the contrasts provided e.g. z_map, t_map, effects and variance. Parameters ---------- second_level_contrast: str or array of shape (n_col), optional Where ``n_col`` is the number of columns of the design matrix, The string can be a formula compatible with the linear constraint of the Patsy library. Basically one can use the name of the conditions as they appear in the design matrix of the fitted model combined with operators /\*+- and numbers. Please check the patsy documentation for formula examples: http://patsy.readthedocs.io/en/latest/API-reference.html#patsy.DesignInfo.linear_constraint The default (None) is accepted if the design matrix has a single column, in which case the only possible contrast array([1]) is applied; when the design matrix has multiple columns, an error is raised. first_level_contrast: str or array of shape (n_col) with respect to FirstLevelModel, optional In case a list of FirstLevelModel was provided as second_level_input, we have to provide a contrast to apply to the first level models to get the corresponding list of images desired, that would be tested at the second level. In case a pandas DataFrame was provided as second_level_input this is the map name to extract from the pandas dataframe map_name column. It has to be a 't' contrast. second_level_stat_type: {'t', 'F'}, optional Type of the second level contrast output_type: str, optional Type of the output map. Can be 'z_score', 'stat', 'p_value', 'effect_size', 'effect_variance' or 'all' Returns ------- output_image: Nifti1Image The desired output image(s). If ``output_type == 'all'``, then the output is a dictionary of images, keyed by the type of image. """ if self.second_level_input_ is None: raise ValueError('The model has not been fit yet') # check first_level_contrast _check_first_level_contrast(self.second_level_input_, first_level_contrast) # check contrast and obtain con_val con_val = _get_con_val(second_level_contrast, self.design_matrix_) # check output type # 'all' is assumed to be the final entry; # if adding more, place before 'all' valid_types = ['z_score', 'stat', 'p_value', 'effect_size', 'effect_variance', 'all'] _check_output_type(output_type, valid_types) # Get effect_maps appropriate for chosen contrast effect_maps = _infer_effect_maps(self.second_level_input_, first_level_contrast) # Check design matrix X and effect maps Y agree on number of rows _check_effect_maps(effect_maps, self.design_matrix_) # Fit an Ordinary Least Squares regression for parametric statistics Y = self.masker_.transform(effect_maps) if self.memory: mem_glm = self.memory.cache(run_glm, ignore=['n_jobs']) else: mem_glm = run_glm labels, results = mem_glm(Y, self.design_matrix_.values, n_jobs=self.n_jobs, noise_model='ols') # We save memory if inspecting model details is not necessary if self.minimize_memory: for key in results: results[key] = SimpleRegressionResults(results[key]) self.labels_ = labels self.results_ = results # We compute contrast object if self.memory: mem_contrast = self.memory.cache(compute_contrast) else: mem_contrast = compute_contrast contrast = mem_contrast(self.labels_, self.results_, con_val, second_level_stat_type) output_types = \ valid_types[:-1] if output_type == 'all' else [output_type] outputs = {} for output_type_ in output_types: # We get desired output from contrast object estimate_ = getattr(contrast, output_type_)() # Prepare the returned images output = self.masker_.inverse_transform(estimate_) contrast_name = str(con_val) output.header['descrip'] = ( '%s of contrast %s' % (output_type, contrast_name)) outputs[output_type_] = output return outputs if output_type == 'all' else output
def non_parametric_inference( second_level_input, confounds=None, design_matrix=None, second_level_contrast=None, mask=None, smoothing_fwhm=None, model_intercept=True, n_perm=10000, two_sided_test=False, random_state=None, n_jobs=1, verbose=0): """Generate p-values corresponding to the contrasts provided based on permutation testing. This fuction reuses the 'permuted_ols' function Nilearn. Parameters ---------- second_level_input: pandas DataFrame or list of Niimg-like objects. If a pandas DataFrame, then they have to contain subject_label, map_name and effects_map_path. It can contain multiple maps that would be selected during contrast estimation with the argument first_level_contrast of the compute_contrast function. The DataFrame will be sorted based on the subject_label column to avoid order inconsistencies when extracting the maps. So the rows of the automatically computed design matrix, if not provided, will correspond to the sorted subject_label column. If list of Niimg-like objects then this is taken literally as Y for the model fit and design_matrix must be provided. confounds: pandas DataFrame, optional Must contain a subject_label column. All other columns are considered as confounds and included in the model. If design_matrix is provided then this argument is ignored. The resulting second level design matrix uses the same column names as in the given DataFrame for confounds. At least two columns are expected, "subject_label" and at least one confound. design_matrix: pandas DataFrame, optional Design matrix to fit the GLM. The number of rows in the design matrix must agree with the number of maps derived from second_level_input. Ensure that the order of maps given by a second_level_input list of Niimgs matches the order of the rows in the design matrix. second_level_contrast: str or array of shape (n_col), optional Where ``n_col`` is the number of columns of the design matrix. The default (None) is accepted if the design matrix has a single column, in which case the only possible contrast array([1]) is applied; when the design matrix has multiple columns, an error is raised. mask: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional, Mask to be used on data. If an instance of masker is passed, then its mask will be used. If no mask is given, it will be computed automatically by a MultiNiftiMasker with default parameters. Automatic mask computation assumes first level imgs have already been masked. smoothing_fwhm: float, optional If smoothing_fwhm is not None, it gives the size in millimeters of the spatial smoothing to apply to the signal. model_intercept : bool, If True, a constant column is added to the confounding variates unless the tested variate is already the intercept. n_perm : int, Number of permutations to perform. Permutations are costly but the more are performed, the more precision one gets in the p-values estimation. two_sided_test : boolean, If True, performs an unsigned t-test. Both positive and negative effects are considered; the null hypothesis is that the effect is zero. If False, only positive effects are considered as relevant. The null hypothesis is that the effect is zero or negative. random_state : int or None, Seed for random number generator, to have the same permutations in each computing units. n_jobs : int, Number of parallel workers. If -1 is provided, all CPUs are used. A negative number indicates that all the CPUs except (abs(n_jobs) - 1) ones will be used. verbose: int, optional verbosity level (0 means no message). Returns ------- neg_log_corrected_pvals_img: Nifti1Image The image which contains negative logarithm of the corrected p-values """ _check_second_level_input(second_level_input, design_matrix, flm_object=False, df_object=False) _check_confounds(confounds) _check_design_matrix(design_matrix) # Report progress t0 = time.time() if verbose > 0: sys.stderr.write("Fitting second level model...") # Select sample map for masker fit and get subjects_label for design sample_map = mean_img(second_level_input) # Learn the mask. Assume the first level imgs have been masked. if not isinstance(mask, NiftiMasker): masker = NiftiMasker( mask_img=mask, smoothing_fwhm=smoothing_fwhm, memory=Memory(None), verbose=max(0, verbose - 1), memory_level=1) else: masker = clone(mask) if smoothing_fwhm is not None: if getattr(masker, 'smoothing_fwhm') is not None: warn('Parameter smoothing_fwhm of the masker overriden') setattr(masker, 'smoothing_fwhm', smoothing_fwhm) masker.fit(sample_map) # Report progress if verbose > 0: sys.stderr.write("\nComputation of second level model done in " "%i seconds\n" % (time.time() - t0)) # Check and obtain the contrast contrast = _get_contrast(second_level_contrast, design_matrix) # Get effect_maps effect_maps = _infer_effect_maps(second_level_input, None) # Check design matrix and effect maps agree on number of rows _check_effect_maps(effect_maps, design_matrix) # Obtain tested_var if contrast in design_matrix.columns.tolist(): tested_var = np.asarray(design_matrix[contrast]) # Mask data target_vars = masker.transform(effect_maps) # Perform massively univariate analysis with permuted OLS neg_log_pvals_permuted_ols, _, _ = permuted_ols( tested_var, target_vars, model_intercept=model_intercept, n_perm=n_perm, two_sided_test=two_sided_test, random_state=random_state, n_jobs=n_jobs, verbose=max(0, verbose - 1)) neg_log_corrected_pvals_img = masker.inverse_transform( np.ravel(neg_log_pvals_permuted_ols)) return neg_log_corrected_pvals_img
from nilearn.input_data import NiftiMasker masker = NiftiMasker() masker.fit(func_file)
from nilearn import datasets miyawaki_dataset = datasets.fetch_miyawaki2008() # print basic information on the dataset print('First functional nifti image (4D) is located at: %s' % miyawaki_dataset.func[0]) # 4D data miyawaki_filename = miyawaki_dataset.func[0] miyawaki_mean_img = image.mean_img(miyawaki_filename) # This time, we can use the NiftiMasker without changing the default mask # strategy, as the data has already been masked, and thus lies on a # homogeneous background masker = NiftiMasker() masker.fit(miyawaki_filename) plot_roi(masker.mask_img_, miyawaki_mean_img, title="Mask from already masked data") ############################################################################### # From raw EPI data # Load ADHD resting-state dataset dataset = datasets.fetch_adhd(n_subjects=1) epi_filename = dataset.func[0] # Restrict to 100 frames to speed up computation from nilearn.image import index_img epi_img = index_img(epi_filename, slice(0, 100))
class FirstLevelModel(BaseEstimator, TransformerMixin, CacheMixin): """ Implementation of the General Linear Model for single session fMRI data Parameters ---------- t_r : float This parameter indicates repetition times of the experimental runs. In seconds. It is necessary to correctly consider times in the design matrix. This parameter is also passed to nilearn.signal.clean. Please see the related documentation for details. slice_time_ref : float, optional (default 0.) This parameter indicates the time of the reference slice used in the slice timing preprocessing step of the experimental runs. It is expressed as a percentage of the t_r (time repetition), so it can have values between 0. and 1. hrf_model : {'spm', 'spm + derivative', 'spm + derivative + dispersion', 'glover', 'glover + derivative', 'glover + derivative + dispersion', 'fir', None} String that specifies the hemodynamic response function. Defaults to 'glover'. drift_model : string, optional This parameter specifies the desired drift model for the design matrices. It can be 'polynomial', 'cosine' or None. period_cut : float, optional This parameter specifies the cut period of the high-pass filter in seconds for the design matrices. Used only if drift_model is 'cosine'. drift_order : int, optional This parameter specifices the order of the drift model (in case it is polynomial) for the design matrices. fir_delays : array of shape(n_onsets) or list, optional In case of FIR design, yields the array of delays used in the FIR model, in seconds. min_onset : float, optional This parameter specifies the minimal onset relative to the design (in seconds). Events that start before (slice_time_ref * t_r + min_onset) are not considered. mask_img : Niimg-like, NiftiMasker object or False, optional Mask to be used on data. If an instance of masker is passed, then its mask will be used. If no mask is given, it will be computed automatically by a NiftiMasker with default parameters. If False is given then the data will not be masked. target_affine : 3x3 or 4x4 matrix, optional This parameter is passed to nilearn.image.resample_img. Please see the related documentation for details. target_shape : 3-tuple of integers, optional This parameter is passed to nilearn.image.resample_img. Please see the related documentation for details. smoothing_fwhm : float, optional If smoothing_fwhm is not None, it gives the size in millimeters of the spatial smoothing to apply to the signal. memory : string, optional Path to the directory used to cache the masking process and the glm fit. By default, no caching is done. Creates instance of joblib.Memory. memory_level : integer, optional Rough estimator of the amount of memory used by caching. Higher value means more memory for caching. standardize : boolean, optional If standardize is True, the time-series are centered and normed: their variance is put to 1 in the time dimension. signal_scaling : False, int or (int, int), optional, If not False, fMRI signals are scaled to the mean value of scaling_axis given, which can be 0, 1 or (0, 1). 0 refers to mean scaling each voxel with respect to time, 1 refers to mean scaling each time point with respect to all voxels and (0, 1) refers to scaling with respect to voxels and time, which is known as grand mean scaling. Incompatible with standardize (standardize=False is enforced when signal_scaling is not False). noise_model : {'ar1', 'ols'}, optional The temporal variance model. Defaults to 'ar1' verbose : integer, optional Indicate the level of verbosity. By default, nothing is printed. If 0 prints nothing. If 1 prints progress by computation of each run. If 2 prints timing details of masker and GLM. If 3 prints masker computation details. n_jobs : integer, optional The number of CPUs to use to do the computation. -1 means 'all CPUs', -2 'all CPUs but one', and so on. minimize_memory : boolean, optional Gets rid of some variables on the model fit results that are not necessary for contrast computation and would only be useful for further inspection of model details. This has an important impact on memory consumption. True by default. subject_label : string, optional This id will be used to identify a `FirstLevelModel` when passed to a `SecondLevelModel` object. Attributes ---------- labels : array of shape (n_voxels,), a map of values on voxels used to identify the corresponding model results : dict, with keys corresponding to the different labels values values are RegressionResults instances corresponding to the voxels """ @replace_parameters({'mask': 'mask_img'}, end_version='next') def __init__(self, t_r=None, slice_time_ref=0., hrf_model='glover', drift_model='cosine', period_cut=128, drift_order=1, fir_delays=[0], min_onset=-24, mask_img=None, target_affine=None, target_shape=None, smoothing_fwhm=None, memory=Memory(None), memory_level=1, standardize=False, signal_scaling=0, noise_model='ar1', verbose=0, n_jobs=1, minimize_memory=True, subject_label=None): # design matrix parameters self.t_r = t_r self.slice_time_ref = slice_time_ref self.hrf_model = hrf_model self.drift_model = drift_model self.period_cut = period_cut self.drift_order = drift_order self.fir_delays = fir_delays self.min_onset = min_onset # glm parameters self.mask_img = mask_img self.target_affine = target_affine self.target_shape = target_shape self.smoothing_fwhm = smoothing_fwhm if isinstance(memory, _basestring): self.memory = Memory(memory) else: self.memory = memory self.memory_level = memory_level self.standardize = standardize if signal_scaling is False: self.signal_scaling = signal_scaling elif signal_scaling in [0, 1, (0, 1)]: self.scaling_axis = signal_scaling self.signal_scaling = True self.standardize = False else: raise ValueError('signal_scaling must be "False", "0", "1"' ' or "(0, 1)"') self.noise_model = noise_model self.verbose = verbose self.n_jobs = n_jobs self.minimize_memory = minimize_memory # attributes self.labels_ = None self.results_ = None self.subject_label = subject_label def fit(self, run_imgs, events=None, confounds=None, design_matrices=None): """ Fit the GLM For each run: 1. create design matrix X 2. do a masker job: fMRI_data -> Y 3. fit regression to (Y, X) Parameters ---------- run_imgs: Niimg-like object or list of Niimg-like objects, See http://nilearn.github.io/manipulating_images/input_output.html#inputing-data-file-names-or-image-objects Data on which the GLM will be fitted. If this is a list, the affine is considered the same for all. events: pandas Dataframe or string or list of pandas DataFrames or strings fMRI events used to build design matrices. One events object expected per run_img. Ignored in case designs is not None. If string, then a path to a csv file is expected. confounds: pandas Dataframe or string or list of pandas DataFrames or strings Each column in a DataFrame corresponds to a confound variable to be included in the regression model of the respective run_img. The number of rows must match the number of volumes in the respective run_img. Ignored in case designs is not None. If string, then a path to a csv file is expected. design_matrices: pandas DataFrame or list of pandas DataFrames, Design matrices that will be used to fit the GLM. If given it takes precedence over events and confounds. """ # Check arguments # Check imgs type if events is not None: _check_events_file_uses_tab_separators( events_files=events) if not isinstance(run_imgs, (list, tuple)): run_imgs = [run_imgs] if design_matrices is None: if events is None: raise ValueError('events or design matrices must be provided') if self.t_r is None: raise ValueError('t_r not given to FirstLevelModel object' ' to compute design from events') else: design_matrices = _check_run_tables(run_imgs, design_matrices, 'design_matrices') # Check that number of events and confound files match number of runs # Also check that events and confound files can be loaded as DataFrame if events is not None: events = _check_run_tables(run_imgs, events, 'events') if confounds is not None: confounds = _check_run_tables(run_imgs, confounds, 'confounds') # Learn the mask if self.mask_img is False: # We create a dummy mask to preserve functionality of api ref_img = check_niimg(run_imgs[0]) self.mask_img = Nifti1Image(np.ones(ref_img.shape[:3]), ref_img.affine) if not isinstance(self.mask_img, NiftiMasker): self.masker_ = NiftiMasker( mask_img=self.mask_img, smoothing_fwhm=self.smoothing_fwhm, target_affine=self.target_affine, standardize=self.standardize, mask_strategy='epi', t_r=self.t_r, memory=self.memory, verbose=max(0, self.verbose - 2), target_shape=self.target_shape, memory_level=self.memory_level) self.masker_.fit(run_imgs[0]) else: if self.mask_img.mask_img_ is None and self.masker_ is None: self.masker_ = clone(self.mask_img) for param_name in ['target_affine', 'target_shape', 'smoothing_fwhm', 't_r', 'memory', 'memory_level']: our_param = getattr(self, param_name) if our_param is None: continue if getattr(self.masker_, param_name) is not None: warn('Parameter %s of the masker' ' overriden' % param_name) setattr(self.masker_, param_name, our_param) self.masker_.fit(run_imgs[0]) else: self.masker_ = self.mask_img # For each run fit the model and keep only the regression results. self.labels_, self.results_, self.design_matrices_ = [], [], [] n_runs = len(run_imgs) t0 = time.time() for run_idx, run_img in enumerate(run_imgs): # Report progress if self.verbose > 0: percent = float(run_idx) / n_runs percent = round(percent * 100, 2) dt = time.time() - t0 # We use a max to avoid a division by zero if run_idx == 0: remaining = 'go take a coffee, a big one' else: remaining = (100. - percent) / max(0.01, percent) * dt remaining = '%i seconds remaining' % remaining sys.stderr.write( "Computing run %d out of %d runs (%s)\n" % (run_idx + 1, n_runs, remaining)) # Build the experimental design for the glm run_img = check_niimg(run_img, ensure_ndim=4) if design_matrices is None: n_scans = run_img.get_data().shape[3] if confounds is not None: confounds_matrix = confounds[run_idx].values if confounds_matrix.shape[0] != n_scans: raise ValueError('Rows in confounds does not match' 'n_scans in run_img at index %d' % (run_idx,)) confounds_names = confounds[run_idx].columns.tolist() else: confounds_matrix = None confounds_names = None start_time = self.slice_time_ref * self.t_r end_time = (n_scans - 1 + self.slice_time_ref) * self.t_r frame_times = np.linspace(start_time, end_time, n_scans) design = make_first_level_design_matrix(frame_times, events[run_idx], self.hrf_model, self.drift_model, self.period_cut, self.drift_order, self.fir_delays, confounds_matrix, confounds_names, self.min_onset) else: design = design_matrices[run_idx] self.design_matrices_.append(design) # Mask and prepare data for GLM if self.verbose > 1: t_masking = time.time() sys.stderr.write('Starting masker computation \r') Y = self.masker_.transform(run_img) if self.verbose > 1: t_masking = time.time() - t_masking sys.stderr.write('Masker took %d seconds \n' % t_masking) if self.signal_scaling: Y, _ = mean_scaling(Y, self.scaling_axis) if self.memory: mem_glm = self.memory.cache(run_glm, ignore=['n_jobs']) else: mem_glm = run_glm # compute GLM if self.verbose > 1: t_glm = time.time() sys.stderr.write('Performing GLM computation\r') labels, results = mem_glm(Y, design.values, noise_model=self.noise_model, bins=100, n_jobs=self.n_jobs) if self.verbose > 1: t_glm = time.time() - t_glm sys.stderr.write('GLM took %d seconds \n' % t_glm) self.labels_.append(labels) # We save memory if inspecting model details is not necessary if self.minimize_memory: for key in results: results[key] = SimpleRegressionResults(results[key]) self.results_.append(results) del Y # Report progress if self.verbose > 0: sys.stderr.write("\nComputation of %d runs done in %i seconds\n\n" % (n_runs, time.time() - t0)) return self def compute_contrast(self, contrast_def, stat_type=None, output_type='z_score'): """Generate different outputs corresponding to the contrasts provided e.g. z_map, t_map, effects and variance. In multi-session case, outputs the fixed effects map. Parameters ---------- contrast_def : str or array of shape (n_col) or list of (string or array of shape (n_col)) where ``n_col`` is the number of columns of the design matrix, (one array per run). If only one array is provided when there are several runs, it will be assumed that the same contrast is desired for all runs. The string can be a formula compatible with the linear constraint of the Patsy library. Basically one can use the name of the conditions as they appear in the design matrix of the fitted model combined with operators /\*+- and numbers. Please checks the patsy documentation for formula examples: http://patsy.readthedocs.io/en/latest/API-reference.html#patsy.DesignInfo.linear_constraint stat_type : {'t', 'F'}, optional type of the contrast output_type : str, optional Type of the output map. Can be 'z_score', 'stat', 'p_value', 'effect_size', 'effect_variance' or 'all' Returns ------- output : Nifti1Image or dict The desired output image(s). If ``output_type == 'all'``, then the output is a dictionary of images, keyed by the type of image. """ if self.labels_ is None or self.results_ is None: raise ValueError('The model has not been fit yet') if isinstance(contrast_def, (np.ndarray, str)): con_vals = [contrast_def] elif isinstance(contrast_def, (list, tuple)): con_vals = contrast_def else: raise ValueError('contrast_def must be an array or str or list of' ' (array or str)') # Translate formulas to vectors with patsy design_info = DesignInfo(self.design_matrices_[0].columns.tolist()) for cidx, con in enumerate(con_vals): if not isinstance(con, np.ndarray): con_vals[cidx] = design_info.linear_constraint(con).coefs n_runs = len(self.labels_) if len(con_vals) != n_runs: warn('One contrast given, assuming it for all %d runs' % n_runs) con_vals = con_vals * n_runs # 'all' is assumed to be the final entry; if adding more, place before 'all' valid_types = ['z_score', 'stat', 'p_value', 'effect_size', 'effect_variance', 'all'] if output_type not in valid_types: raise ValueError('output_type must be one of {}'.format(valid_types)) contrast = _fixed_effect_contrast(self.labels_, self.results_, con_vals, stat_type) output_types = valid_types[:-1] if output_type == 'all' else [output_type] outputs = {} for output_type_ in output_types: estimate_ = getattr(contrast, output_type_)() # Prepare the returned images output = self.masker_.inverse_transform(estimate_) contrast_name = str(con_vals) output.header['descrip'] = ( '%s of contrast %s' % (output_type_, contrast_name)) outputs[output_type_] = output return outputs if output_type == 'all' else output
n_events = 200 n_blank_events = 50 event_spacing = 6 jitter_min, jitter_max = -1, 1 t_r = 2 smoothing_fwhm = 1 sigma = 2 #sigma_noise = 0.000001 threshold = 0.7 period_cut = 512 drift_order = 1 mask_img = nb.Nifti1Image(np.ones((n_x, n_y, n_z)), affine=np.eye(4)) masker = NiftiMasker(mask_img=mask_img) masker.fit() #HRF peak peak_range_sim = np.arange(3, 11) peak_range = np.arange(3, 11) hrf_ushoot = 16. norm_resid = np.zeros((len(peak_range), len(peak_range))) i = 0 for sigma_noise in np.array([2., 10., 0.01]): for isim, hrf_peak_sim in enumerate(peak_range_sim): # Simulate with different hrf peaks
import joblib import time RES_NAME = 'nips3mm' WRITE_DIR = op.join(os.getcwd(), RES_NAME) if not op.exists(WRITE_DIR): os.mkdir(WRITE_DIR) ############################################################################## # load+preprocess data ############################################################################## mask_img = 'grey10_icbm_3mm_bin.nii.gz' nifti_masker = NiftiMasker(mask_img=mask_img, smoothing_fwhm=False, standardize=False) nifti_masker.fit() mask_nvox = nifti_masker.mask_img_.get_data().sum() print('Loading data...') # ARCHI task X_task, labels = joblib.load('preload_HT_3mm') labels = np.int32(labels) # contrasts are IN ORDER -> shuffle! new_inds = np.arange(0, X_task.shape[0]) np.random.shuffle(new_inds) X_task = X_task[new_inds] labels = labels[new_inds] # subs = subs[new_inds]
class Masker(object): """ Class that takes a binary mask.nii file and allows us to use it within a volumizer in order to reduce the dimensionality of our data in realtime. If we have other ROI masks (e.g. wm, csf), we can use them detrend the data by setting them as orthogonals. """ def __init__(self, mask_img, center=None, radius=8): self.mask_img = mask_img self.masker = NiftiMasker(mask_img=mask_img) self.fit = False # set the mask center if center is None: self.center = self.find_center_of_mass(self.masker) else: self.center = center print("Center=", center) print("COM calc=", self.find_center_of_mass(self.masker)) # the radius of the mask, used for determining what data to read. self.radius = radius self.orthogonals = [] self.use_orthogonal = False self.ortho_fits = [] def reduce_volume(self, volume, method='mean'): if not self.fit: self.masker.fit(volume) if method == 'mean': reduced = npm(self.masker.transform(volume['image'])) return reduced def find_center_of_mass(self, niftimasker): """ Find the center of mass of an image given a nifti masker object in the z plane. We can use this information to only select dicoms we need in a DicomFilter object. """ com = measurements.center_of_mass( nibabel.load(niftimasker.mask_img).get_data()) affine = nibabel.load(niftimasker.mask_img).affine offset = affine[0:3, 3] tcom = np.dot(affine[0:3, 0:3], com) + offset return tcom[2] def add_orthogonal(self, mask_img): # add another mask_img to our orthogonals with get_orthogonal self.use_orthogonal = True self.orthogonals.append(NiftiMasker(mask_img=mask_img)) self.ortho_fits.append(False) def get_orthogonals(self, volume): """ Return a list of ROI averages for a volume given a set of orthogonal masks """ for i, fit in enumerate(self.ortho_fits): if not fit: self.orthogonals[i].fit(volume) return [npm(x.transform(volume['image'])) for x in self.orthogonals]
from nilearn.input_data import NiftiMasker nyu_dataset = datasets.fetch_nyu_rest(n_subjects=1) # print basic information on the dataset print('First anatomical nifti image (3D) is at: %s' % nyu_dataset.anat_anon[0]) print('First functional nifti image (4D) is at: %s' % nyu_dataset.func[0]) # 4D data ### Compute the mask ########################################################## # As this is raw resting-state EPI, the background is noisy and we cannot # rely on the 'background' masking strategy. We need to use the 'epi' one nifti_masker = NiftiMasker(standardize=False, mask_strategy='epi', memory="nilearn_cache", memory_level=2) func_filename = nyu_dataset.func[0] nifti_masker.fit(func_filename) mask_img = nifti_masker.mask_img_ ### Visualize the mask ######################################################## import matplotlib.pyplot as plt from nilearn.plotting import plot_roi from nilearn.image.image import mean_img # calculate mean image for the background mean_func_img = mean_img(func_filename) plot_roi(mask_img, mean_func_img, display_mode='y', cut_coords=4, title="Mask") ### Preprocess data ########################################################### nifti_masker.fit(func_filename)
class FirstLevelGLM(BaseEstimator, TransformerMixin, CacheMixin): """ Implementation of the General Linear Model for Single-session fMRI data Parameters ---------- mask: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional, Mask to be used on data. If an instance of masker is passed, then its mask will be used. If no mask is given, it will be computed automatically by a MultiNiftiMasker with default parameters. target_affine: 3x3 or 4x4 matrix, optional This parameter is passed to nilearn.image.resample_img. Please see the related documentation for details. target_shape: 3-tuple of integers, optional This parameter is passed to nilearn.image.resample_img. Please see the related documentation for details. low_pass: False or float, optional This parameter is passed to nilearn.signal.clean. Please see the related documentation for details. high_pass: False or float, optional This parameter is passed to nilearn.signal.clean. Please see the related documentation for details. t_r: float, optional This parameter is passed to nilearn.signal.clean. Please see the related documentation for details. smoothing_fwhm: float, optional If smoothing_fwhm is not None, it gives the size in millimeters of the spatial smoothing to apply to the signal. memory: instance of joblib.Memory or string Used to cache the masking process. By default, no caching is done. If a string is given, it is the path to the caching directory. memory_level: integer, optional Rough estimator of the amount of memory used by caching. Higher value means more memory for caching. standardize : boolean, optional If standardize is True, the time-series are centered and normed: their variance is put to 1 in the time dimension. percent_signal_change: bool, optional, If True, fMRI signals are scaled to percent of the mean value Incompatible with standardize (standardize=False is enforced when\ percent_signal_change is True). n_jobs : integer, optional The number of CPUs to use to do the computation. -1 means 'all CPUs', -2 'all CPUs but one', and so on. verbose : integer, optional Indicate the level of verbosity. By default, nothing is printed. noise_model : {'ar1', 'ols'}, optional the temporal variance model. Defaults to 'ar1' Attributes ---------- labels : array of shape (n_voxels,), a map of values on voxels used to identify the corresponding model results : dict, with keys corresponding to the different labels values values are RegressionResults instances corresponding to the voxels """ def __init__(self, mask=None, target_affine=None, target_shape=None, low_pass=None, high_pass=None, t_r=None, smoothing_fwhm=None, memory=Memory(None), memory_level=1, standardize=False, percent_signal_change=True, verbose=1, n_jobs=1, noise_model='ar1'): self.mask = mask self.memory = memory self.memory_level = memory_level self.verbose = verbose self.standardize = standardize self.n_jobs = n_jobs self.low_pass = low_pass self.high_pass = high_pass self.t_r = t_r self.target_affine = target_affine self.target_shape = target_shape self.smoothing_fwhm = smoothing_fwhm self.noise_model = noise_model self.percent_signal_change = percent_signal_change if self.percent_signal_change: self.standardize = False def fit(self, imgs, design_matrices): """ Fit the GLM 1. does a masker job: fMRI_data -> Y 2. fit an ols regression to (Y, X) 3. fit an AR(1) regression of require This results in an internal (labels_, regression_results_) parameters Parameters ---------- imgs: Niimg-like object or list of Niimg-like objects, See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg. Data on which the GLM will be fitted. If this is a list, the affine is considered the same for all. design_matrices: pandas DataFrame or list of pandas DataFrames, fMRI design matrices """ # First, learn the mask if not isinstance(self.mask, NiftiMasker): self.masker_ = NiftiMasker( mask_img=self.mask, smoothing_fwhm=self.smoothing_fwhm, target_affine=self.target_affine, standardize=self.standardize, low_pass=self.low_pass, high_pass=self.high_pass, mask_strategy='epi', t_r=self.t_r, memory=self.memory, verbose=max(0, self.verbose - 1), target_shape=self.target_shape, memory_level=self.memory_level) else: self.masker_ = clone(self.mask) for param_name in ['target_affine', 'target_shape', 'smoothing_fwhm', 'low_pass', 'high_pass', 't_r', 'memory', 'memory_level']: our_param = getattr(self, param_name) if our_param is None: continue if getattr(self.masker_, param_name) is not None: warn('Parameter %s of the masker overriden' % param_name) setattr(self.masker_, param_name, our_param) # make design_matrices a list of arrays if isinstance(design_matrices, (_basestring, pd.DataFrame)): design_matrices_ = [design_matrices] else: design_matrices_ = [X for X in design_matrices] design_matrices = [] for design_matrix in design_matrices_: if isinstance(design_matrix, _basestring): loaded = pd.read_csv(design_matrix, index_col=0) design_matrices.append(loaded.values) elif isinstance(design_matrix, pd.DataFrame): design_matrices.append(design_matrix.values) else: raise TypeError( 'Design matrix can only be a pandas DataFrames or a' 'string. A %s was provided' % type(design_matrix)) # make imgs a list of Nifti1Images if isinstance(imgs, (Nifti1Image, _basestring)): imgs = [imgs] if len(imgs) != len(design_matrices): raise ValueError( 'len(imgs) %d does not match len(design_matrices) %d' % (len(imgs), len(design_matrices))) # Loop on imgs and design matrices self.labels_, self.results_ = [], [] self.masker_.fit(imgs) for X, img in zip(design_matrices, imgs): Y = self.masker_.transform(img) if self.percent_signal_change: Y, _ = percent_mean_scaling(Y) labels_, results_ = session_glm( Y, X, noise_model=self.noise_model, bins=100) self.labels_.append(labels_) self.results_.append(results_) return self def transform(self, con_vals, contrast_type=None, contrast_name='', output_z=True, output_stat=False, output_effects=False, output_variance=False): """Generate different outputs corresponding to the contrasts provided e.g. z_map, t_map, effects and variance. In multi-session case, outputs the fixed effects map. Parameters ---------- con_vals : array or list of arrays of shape (n_col) or (n_dim, n_col) where ``n_col`` is the number of columns of the design matrix, numerical definition of the contrast (one array per run) contrast_type : {'t', 'F'}, optional type of the contrast contrast_name : str, optional name of the contrast output_z : bool, optional Return or not the corresponding z-stat image output_stat : bool, optional Return or not the base (t/F) stat image output_effects : bool, optional Return or not the corresponding effect image output_variance : bool, optional Return or not the corresponding variance image Returns ------- output_images : list of Nifti1Images The desired output images """ if self.labels_ is None or self.results_ is None: raise ValueError('The model has not been fit yet') if isinstance(con_vals, np.ndarray): con_vals = [con_vals] if len(con_vals) != len(self.results_): raise ValueError( 'contrasts must be a sequence of %d session contrasts' % len(self.results_)) contrast = None for i, (labels_, results_, con_val) in enumerate(zip( self.labels_, self.results_, con_vals)): if np.all(con_val == 0): warn('Contrast for session %d is null' % i) contrast_ = compute_contrast(labels_, results_, con_val, contrast_type) if contrast is None: contrast = contrast_ else: contrast = contrast + contrast_ if output_z or output_stat: # compute the contrast and stat contrast.z_score() # Prepare the returned images do_outputs = [output_z, output_stat, output_effects, output_variance] estimates = ['z_score_', 'stat_', 'effect', 'variance'] descrips = ['z statistic', 'Statistical value', 'Estimated effect', 'Estimated variance'] output_images = [] for do_output, estimate, descrip in zip( do_outputs, estimates, descrips): if not do_output: continue estimate_ = getattr(contrast, estimate) if estimate_.ndim == 3: shape_ = estimate_.shape estimate_ = np.reshape(estimate_, (shape_[0] * shape_[1], shape_[2])) output = self.masker_.inverse_transform(estimate_) output.get_header()['descrip'] = ( '%s of contrast %s' % (descrip, contrast_name)) output_images.append(output) return output_images def fit_transform( self, design_matrices, fmri_images, con_vals, contrast_type=None, contrast_name='', output_z=True, output_stat=False, output_effects=False, output_variance=False): """ Fit then transform. For more details, see FirstLevelGLM.fit and FirstLevelGLM.transform documentation""" return self.fit(design_matrices, fmri_images).transform( con_vals, contrast_type, contrast_name, output_z=True, output_stat=False, output_effects=False, output_variance=False)
class FirstLevelModel(BaseEstimator, TransformerMixin, CacheMixin): """ Implementation of the General Linear Model for single session fMRI data Parameters ---------- t_r: float This parameter indicates repetition times of the experimental runs. In seconds. It is necessary to correctly consider times in the design matrix. This parameter is also passed to nilearn.signal.clean. Please see the related documentation for details. slice_time_ref: float, optional (default 0.) This parameter indicates the time of the reference slice used in the slice timing preprocessing step of the experimental runs. It is expressed as a percentage of the t_r (time repetition), so it can have values between 0. and 1. hrf_model : string, optional This parameter specifies the hemodynamic response function (HRF) for the design matrices. It can be 'canonical', 'canonical with derivative' or 'fir'. drift_model : string, optional This parameter specifies the desired drift model for the design matrices. It can be 'polynomial', 'cosine' or 'blank'. period_cut : float, optional This parameter specifies the cut period of the low-pass filter in seconds for the design matrices. drift_order : int, optional This parameter specifices the order of the drift model (in case it is polynomial) for the design matrices. fir_delays : array of shape(n_onsets) or list, optional In case of FIR design, yields the array of delays used in the FIR model, in seconds. min_onset : float, optional This parameter specifies the minimal onset relative to the design (in seconds). Events that start before (slice_time_ref * t_r + min_onset) are not considered. mask: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional, Mask to be used on data. If an instance of masker is passed, then its mask will be used. If no mask is given, it will be computed automatically by a MultiNiftiMasker with default parameters. target_affine: 3x3 or 4x4 matrix, optional This parameter is passed to nilearn.image.resample_img. Please see the related documentation for details. target_shape: 3-tuple of integers, optional This parameter is passed to nilearn.image.resample_img. Please see the related documentation for details. smoothing_fwhm: float, optional If smoothing_fwhm is not None, it gives the size in millimeters of the spatial smoothing to apply to the signal. memory: string, optional Path to the directory used to cache the masking process and the glm fit. By default, no caching is done. Creates instance of joblib.Memory. memory_level: integer, optional Rough estimator of the amount of memory used by caching. Higher value means more memory for caching. standardize : boolean, optional If standardize is True, the time-series are centered and normed: their variance is put to 1 in the time dimension. signal_scaling: False, int or (int, int), optional, If not False, fMRI signals are scaled to the mean value of scaling_axis given, which can be 0, 1 or (0, 1). 0 refers to mean scaling each voxel with respect to time, 1 refers to mean scaling each time point with respect to all voxels and (0, 1) refers to scaling with respect to voxels and time, which is known as grand mean scaling. Incompatible with standardize (standardize=False is enforced when signal_scaling is not False). noise_model : {'ar1', 'ols'}, optional The temporal variance model. Defaults to 'ar1' verbose : integer, optional Indicate the level of verbosity. By default, nothing is printed. n_jobs : integer, optional The number of CPUs to use to do the computation. -1 means 'all CPUs', -2 'all CPUs but one', and so on. minimize_memory : boolean, optional Gets rid of some variables on the model fit results that are not necessary for contrast computation and would only be useful for further inspection of model details. This has an important impact on memory consumption. True by default. Attributes ---------- labels : array of shape (n_voxels,), a map of values on voxels used to identify the corresponding model results : dict, with keys corresponding to the different labels values values are RegressionResults instances corresponding to the voxels """ def __init__(self, t_r=None, slice_time_ref=0., hrf_model='glover', drift_model='cosine', period_cut=128, drift_order=1, fir_delays=[0], min_onset=-24, mask=None, target_affine=None, target_shape=None, smoothing_fwhm=None, memory=Memory(None), memory_level=1, standardize=False, signal_scaling=0, noise_model='ar1', verbose=1, n_jobs=1, minimize_memory=True): # design matrix parameters self.t_r = t_r self.slice_time_ref = slice_time_ref self.hrf_model = hrf_model self.drift_model = drift_model self.period_cut = period_cut self.drift_order = drift_order self.fir_delays = fir_delays self.min_onset = min_onset # glm parameters self.mask = mask self.target_affine = target_affine self.target_shape = target_shape self.smoothing_fwhm = smoothing_fwhm if isinstance(memory, _basestring): self.memory = Memory(memory) else: self.memory = memory self.memory_level = memory_level self.standardize = standardize if signal_scaling in [0, 1, (0, 1)]: self.scaling_axis = signal_scaling self.signal_scaling = True self.standardize = False elif signal_scaling is False: self.signal_scaling = signal_scaling else: raise ValueError('signal_scaling must be "False", "0", "1"' ' or "(0, 1)"') self.noise_model = noise_model self.verbose = verbose self.n_jobs = n_jobs self.minimize_memory = minimize_memory # attributes self.labels_ = None self.results_ = None def fit(self, run_imgs, paradigms=None, confounds=None, design_matrices=None): """ Fit the GLM For each run: 1. create design matrix X 2. do a masker job: fMRI_data -> Y 3. fit regression to (Y, X) Parameters ---------- run_imgs: Niimg-like object or list of Niimg-like objects, See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg. Data on which the GLM will be fitted. If this is a list, the affine is considered the same for all. paradigms: pandas Dataframe or string or list of pandas DataFrames or strings, fMRI paradigms used to build design matrices. One paradigm expected per run_img. Ignored in case designs is not None. confounds: pandas Dataframe or string or list of pandas DataFrames or strings, Each column in a DataFrame corresponds to a confound variable to be included in the regression model of the respective run_img. The number of rows must match the number of volumes in the respective run_img. Ignored in case designs is not None. design_matrices: pandas DataFrame or list of pandas DataFrames, Design matrices that will be used to fit the GLM. """ # Check arguments # Check imgs type if not isinstance(run_imgs, (list, tuple)): run_imgs = [run_imgs] for rimg in run_imgs: if not isinstance(rimg, (_basestring, Nifti1Image)): raise ValueError('run_imgs must be Niimg-like object or list' ' of Niimg-like objects') # check all information necessary to build design matrices is available if design_matrices is None: if paradigms is None: raise ValueError('paradigms or design matrices must be provided') if self.t_r is None: raise ValueError('t_r not given to FirstLevelModel object' ' to compute design from paradigm') else: design_matrices = _check_run_tables(run_imgs, design_matrices, 'design_matrices') # check the number of paradigm and confound files match number of runs # Also check paradigm and confound files can be loaded as DataFrame if paradigms is not None: paradigms = _check_run_tables(run_imgs, paradigms, 'paradigms') if confounds is not None: confounds = _check_run_tables(run_imgs, confounds, 'confounds') # Learn the mask if not isinstance(self.mask, NiftiMasker): self.masker_ = NiftiMasker( mask_img=self.mask, smoothing_fwhm=self.smoothing_fwhm, target_affine=self.target_affine, standardize=self.standardize, mask_strategy='epi', t_r=self.t_r, memory=self.memory, verbose=max(0, self.verbose - 1), target_shape=self.target_shape, memory_level=self.memory_level) else: self.masker_ = clone(self.mask) for param_name in ['target_affine', 'target_shape', 'smoothing_fwhm', 'low_pass', 'high_pass', 't_r', 'memory', 'memory_level']: our_param = getattr(self, param_name) if our_param is None: continue if getattr(self.masker_, param_name) is not None: warn('Parameter %s of the masker overriden' % param_name) setattr(self.masker_, param_name, our_param) self.masker_.fit(run_imgs[0]) # For each run fit the model and keep only the regression results. self.labels_, self.results_, self.design_matrices_ = [], [], [] n_runs = len(run_imgs) t0 = time.time() for run_idx, run_img in enumerate(run_imgs): # Report progress if self.verbose > 0: percent = float(run_idx) / n_runs percent = round(percent * 100, 2) dt = time.time() - t0 # We use a max to avoid a division by zero if run_idx == 0: remaining = 'go take a coffee, a big one' else: remaining = (100. - percent) / max(0.01, percent) * dt remaining = '%i seconds remaining' % remaining sys.stderr.write(" " * 100 + "\r") sys.stderr.write( "Computing run %d out of %d runs (%s)\r" % (run_idx, n_runs, remaining)) # Build the experimental design for the glm run_img = check_niimg(run_img, ensure_ndim=4) if design_matrices is None: n_scans = run_img.get_data().shape[3] if confounds is not None: confounds_matrix = confounds[run_idx].values if confounds_matrix.shape[0] != n_scans: raise ValueError('Rows in confounds does not match' 'n_scans in run_img at index %d' % (run_idx,)) confounds_names = confounds[run_idx].columns else: confounds_matrix = None confounds_names = None start_time = self.slice_time_ref * self.t_r end_time = (n_scans - 1 + self.slice_time_ref) * self.t_r frame_times = np.linspace(start_time, end_time, n_scans) design = make_design_matrix(frame_times, paradigms[run_idx], self.hrf_model, self.drift_model, self.period_cut, self.drift_order, self.fir_delays, confounds_matrix, confounds_names, self.min_onset) else: design = design_matrices[run_idx] self.design_matrices_.append(design) # Compute GLM Y = self.masker_.transform(run_img) if self.signal_scaling: Y, _ = mean_scaling(Y, self.scaling_axis) if self.memory is not None: mem_glm = self.memory.cache(run_glm) else: mem_glm = run_glm labels, results = mem_glm(Y, design, noise_model=self.noise_model, bins=100, n_jobs=self.n_jobs) self.labels_.append(labels) # We save memory if inspecting model details is not necessary if self.minimize_memory: for key in results: results[key] = SimpleRegressionResults(results[key]) self.results_.append(results) del Y # Report progress if self.verbose > 0: sys.stderr.write("\nComputation of %d runs done in %i seconds\n" % (n_runs, time.time() - t0)) return self def compute_contrast(self, contrast_def, contrast_name=None, stat_type=None, output_type='z_score'): """Generate different outputs corresponding to the contrasts provided e.g. z_map, t_map, effects and variance. In multi-session case, outputs the fixed effects map. Parameters ---------- contrast_def : array or list of arrays of shape (n_col) or (n_run, n_col) where ``n_col`` is the number of columns of the design matrix, (one array per run). If only one array is provided when there are several runs, it will be assumed that the same contrast is desired for all runs contrast_name : str, optional name of the contrast stat_type : {'t', 'F'}, optional type of the contrast output_type : str, optional Type of the output map. Can be 'z_score', 'stat', 'p_value', 'effect_size' or 'effect_variance' Returns ------- output_image : Nifti1Image The desired output image """ if self.labels_ is None or self.results_ is None: raise ValueError('The model has not been fit yet') if isinstance(contrast_def, np.ndarray): con_vals = [contrast_def] elif isinstance(contrast_def, (list, tuple)): con_vals = contrast_def for cidx, con in enumerate(contrast_def): if not isinstance(con, np.ndarray): raise ValueError('contrast_def at index %i is not an' ' array' % cidx) else: raise ValueError('contrast_def must be an array or list of arrays') n_runs = len(self.labels_) if len(con_vals) != n_runs: warn('One contrast given, assuming it for all %d runs' % n_runs) con_vals = con_vals * n_runs if isinstance(output_type, _basestring): if output_type not in ['z_score', 'stat', 'p_value', 'effect_size', 'effect_variance']: raise ValueError('output_type must be one of "z_score", "stat",' ' "p_value","effect_size" or "effect_variance"') else: raise ValueError('output_type must be one of "z_score", "stat",' ' "p_value","effect_size" or "effect_variance"') if self.memory is not None: arg_ignore = ['labels', 'results'] mem_contrast = self.memory.cache(_fixed_effect_contrast, ignore=arg_ignore) else: mem_contrast = _fixed_effect_contrast contrast = mem_contrast(self.labels_, self.results_, con_vals, stat_type) estimate_ = getattr(contrast, output_type)() # Prepare the returned images output = self.masker_.inverse_transform(estimate_) if contrast_name is None: contrast_name = str(con_vals) output.get_header()['descrip'] = ( '%s of contrast %s' % (output_type, contrast_name)) return output
def plot_melodic_components(melodic_dir, in_file, tr=None, out_file='melodic_reportlet.svg', compress='auto', report_mask=None, noise_components_file=None): """ Plots the spatiotemporal components extracted by FSL MELODIC from functional MRI data. Parameters melodic_dir : str Path pointing to the outputs of MELODIC in_file : str Path pointing to the reference fMRI dataset. This file will be used to extract the TR value, if the ``tr`` argument is not set. This file will be used to calculate a mask if ``report_mask`` is not provided. tr : float Repetition time in seconds out_file : str Path where the resulting SVG file will be stored compress : ``'auto'`` or bool Whether SVG should be compressed. If ``'auto'``, compression will be executed if dependencies are installed (SVGO) report_mask : str Path to a brain mask corresponding to ``in_file`` noise_components_file : str A CSV file listing the indexes of components classified as noise by some manual or automated (e.g. ICA-AROMA) procedure. If a ``noise_components_file`` is provided, then components will be plotted with red/green colors (correspondingly to whether they are in the file -noise components, red-, or not -signal, green-). When all or none of the components are in the file, a warning is printed at the top. """ from nilearn.image import index_img, iter_img import nibabel as nb import numpy as np import pylab as plt import seaborn as sns from matplotlib.gridspec import GridSpec import os import re from io import StringIO sns.set_style("white") current_palette = sns.color_palette() in_nii = nb.load(in_file) if not tr: tr = in_nii.header.get_zooms()[3] units = in_nii.header.get_xyzt_units() if units: if units[-1] == 'msec': tr = tr / 1000.0 elif units[-1] == 'usec': tr = tr / 1000000.0 elif units[-1] != 'sec': NIWORKFLOWS_LOG.warning('Unknown repetition time units ' 'specified - assuming seconds') else: NIWORKFLOWS_LOG.warning( 'Repetition time units not specified - assuming seconds') from nilearn.input_data import NiftiMasker from nilearn.plotting import cm if not report_mask: nifti_masker = NiftiMasker(mask_strategy='epi') nifti_masker.fit(index_img(in_nii, range(2))) mask_img = nifti_masker.mask_img_ else: mask_img = nb.load(report_mask) mask_sl = [] for j in range(3): mask_sl.append(transform_to_2d(mask_img.get_data(), j)) timeseries = np.loadtxt(os.path.join(melodic_dir, "melodic_mix")) power = np.loadtxt(os.path.join(melodic_dir, "melodic_FTmix")) stats = np.loadtxt(os.path.join(melodic_dir, "melodic_ICstats")) n_components = stats.shape[0] Fs = 1.0 / tr Ny = Fs / 2 f = Ny * (np.array(list(range(1, power.shape[0] + 1)))) / (power.shape[0]) # Set default colors color_title = 'k' color_time = current_palette[0] color_power = current_palette[1] classified_colors = None warning_row = 0 # Do not allocate warning row # Only if the components file has been provided, a warning banner will # be issued if all or none of the components were classified as noise if noise_components_file: noise_components = np.loadtxt(noise_components_file, dtype=int, delimiter=',', ndmin=1) # Activate warning row if pertinent warning_row = int(noise_components.size == 0 or noise_components.size == n_components) classified_colors = {True: 'r', False: 'g'} n_rows = int((n_components + (n_components % 2)) / 2) fig = plt.figure(figsize=(6.5 * 1.5, (n_rows + warning_row) * 0.85)) gs = GridSpec(n_rows * 2 + warning_row, 9, width_ratios=[1, 1, 1, 4, 0.001, 1, 1, 1, 4, ], height_ratios=[5] * warning_row + [1.1, 1] * n_rows) if warning_row: ax = fig.add_subplot(gs[0, :]) ncomps = 'NONE of the' if noise_components.size == n_components: ncomps = 'ALL' ax.annotate( 'WARNING: {} components were classified as noise'.format(ncomps), xy=(0.0, 0.5), xycoords='axes fraction', xytext=(0.01, 0.5), textcoords='axes fraction', size=12, color='#ea8800', bbox=dict(boxstyle="round", fc='#f7dcb7', ec='#FC990E')) ax.axes.get_xaxis().set_visible(False) ax.axes.get_yaxis().set_visible(False) titlefmt = "C{id:d}{noise}: Tot. var. expl. {var:.2g}%".format for i, img in enumerate( iter_img(os.path.join(melodic_dir, "melodic_IC.nii.gz"))): col = i % 2 row = i // 2 l_row = row * 2 + warning_row is_noise = False if classified_colors: # If a noise components list is provided, assign red/green is_noise = (i + 1) in noise_components color_title = color_time = color_power = classified_colors[is_noise] data = img.get_data() for j in range(3): ax1 = fig.add_subplot(gs[l_row:l_row + 2, j + col * 5]) sl = transform_to_2d(data, j) m = np.abs(sl).max() ax1.imshow(sl, vmin=-m, vmax=+m, cmap=cm.cold_white_hot, interpolation="nearest") ax1.contour(mask_sl[j], levels=[0.5], colors='k', linewidths=0.5) plt.axis("off") ax1.autoscale_view('tight') if j == 0: ax1.set_title( titlefmt(id=i + 1, noise=' [noise]' * is_noise, var=stats[i, 1]), x=0, y=1.18, fontsize=7, horizontalalignment='left', verticalalignment='top', color=color_title) ax2 = fig.add_subplot(gs[l_row, 3 + col * 5]) ax3 = fig.add_subplot(gs[l_row + 1, 3 + col * 5]) ax2.plot(np.arange(len(timeseries[:, i])) * tr, timeseries[:, i], linewidth=min(200 / len(timeseries[:, i]), 1.0), color=color_time) ax2.set_xlim([0, len(timeseries[:, i]) * tr]) ax2.axes.get_yaxis().set_visible(False) ax2.autoscale_view('tight') ax2.tick_params(axis='both', which='major', pad=0) sns.despine(left=True, bottom=True) for tick in ax2.xaxis.get_major_ticks(): tick.label.set_fontsize(6) tick.label.set_color(color_time) ax3.plot(f[0:], power[0:, i], color=color_power, linewidth=min(100 / len(power[0:, i]), 1.0)) ax3.set_xlim([f[0], f.max()]) ax3.axes.get_yaxis().set_visible(False) ax3.autoscale_view('tight') ax3.tick_params(axis='both', which='major', pad=0) for tick in ax3.xaxis.get_major_ticks(): tick.label.set_fontsize(6) tick.label.set_color(color_power) sns.despine(left=True, bottom=True) plt.subplots_adjust(hspace=0.5) image_buf = StringIO() fig.savefig(image_buf, dpi=300, format='svg', transparent=True, bbox_inches='tight', pad_inches=0.01) fig.clf() image_svg = image_buf.getvalue() if compress is True or compress == 'auto': image_svg = svg_compress(image_svg, compress) image_svg = re.sub(' height="[0-9]+[a-z]*"', '', image_svg, count=1) image_svg = re.sub(' width="[0-9]+[a-z]*"', '', image_svg, count=1) image_svg = re.sub(' viewBox', ' preseveAspectRation="xMidYMid meet" viewBox', image_svg, count=1) Path(out_file).write_text(image_svg)