def test_compute_brain_mask(): img, _ = data_gen.generate_mni_space_img(res=8, random_state=0) brain_mask = compute_brain_mask(img, threshold=.2) gm_mask = compute_brain_mask(img, threshold=.2, mask_type="gm") wm_mask = compute_brain_mask(img, threshold=.2, mask_type="wm") brain_data, gm_data, wm_data = map(get_data, (brain_mask, gm_mask, wm_mask)) # Check that whole-brain mask is non-empty assert (brain_data != 0).any() for subset in gm_data, wm_data: # Test that gm and wm masks are included in the whole-brain mask assert (np.logical_and(brain_data, subset) == subset.astype(bool)).all() # Test that gm and wm masks are non-empty assert (subset != 0).any() # Test that gm and wm masks have empty intersection assert (np.logical_and(gm_data, wm_data) == 0).all() # Check that we get a useful warning for empty masks with pytest.warns(masking.MaskWarning): compute_brain_mask(img, threshold=1) # Check that masks obtained from same FOV are the same img1, _ = data_gen.generate_mni_space_img(res=8, random_state=1) mask_img1 = compute_brain_mask(img1, verbose=1, threshold=.2) assert (brain_data == get_data(mask_img1)).all() # Check that error is raised if mask type is unknown with pytest.raises(ValueError, match='Unknown mask type foo.'): compute_brain_mask(img, verbose=1, mask_type='foo')
def test_compute_brain_mask(): image = Nifti1Image(np.ones((9, 9, 9)), np.eye(4)) mask = compute_brain_mask(image, threshold=-1) mask1 = np.zeros((9, 9, 9)) mask1[2:-2, 2:-2, 2:-2] = 1 np.testing.assert_array_equal(mask1, get_data(mask)) # Check that we get a useful warning for empty masks with pytest.warns(masking.MaskWarning): compute_brain_mask(image, threshold=1) # Check that masks obtained from same FOV are the same img1 = Nifti1Image(np.full((9, 9, 9), np.random.rand()), np.eye(4)) img2 = Nifti1Image(np.full((9, 9, 9), np.random.rand()), np.eye(4)) mask_img1 = compute_brain_mask(img1) mask_img2 = compute_brain_mask(img2) np.testing.assert_array_equal(get_data(mask_img1), get_data(mask_img2))
def t1_pipeline(do_normalise_before=False, do_segment=True, do_normalise_after=False, do_plot=True, keep_tmp=True, sub_name='sub-11', sess_num='ses-17', root_path='/neurospin/ibc'): """ Preprocess qMRI t1 images and then run estimation to generate t1-maps, more details in scripts/qmri_README.md, only one of do_normalise_before and do_normalise_after should be True, both can be False """ DATA_LOC = join(root_path, 'sourcedata', sub_name, sess_num) SAVE_TO = join(root_path, 'derivatives', sub_name, sess_num) if do_normalise_before or do_normalise_after: space = "MNI152" else: space = "individual" if not exists(SAVE_TO): makedirs(SAVE_TO) start_time = time.time() # data files data_dir = DATA_LOC niftis = [] jsons = [] for fi in listdir(join(data_dir, 'anat')): if fi.split('_')[-1] == 'T1map.nii.gz': niftis.append(join(data_dir, 'anat', fi)) elif fi.split('_')[-1] == 'T1map.json': jsons.append(join(data_dir, 'anat', fi)) elif fi.split('_')[-1] == 'B1map.nii.gz': b1_map_nifti = join(data_dir, 'anat', fi) elif fi.split('_')[-1] == 'B1map.json': b1_map_json = join(data_dir, 'anat', fi) else: continue niftis.sort() jsons.sort() # preprocessing directory setup time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] copying necessary files...'.format(time_elapsed)) cwd = SAVE_TO preproc_dir = join(cwd, 'tmp_t1', 'preproc') if not exists(preproc_dir): makedirs(preproc_dir) # copy data files to tmp_t1 directory cnt = 0 for nii, json in zip(niftis, jsons): system('cp {} {}'.format(nii, preproc_dir)) niftis[cnt] = join(preproc_dir, nii.split(sep)[-1]) system('gunzip -df {}'.format(niftis[cnt])) niftis[cnt] = join(preproc_dir, nii.split(sep)[-1].split('.')[0] + '.nii') system('cp {} {}'.format(json, preproc_dir)) jsons[cnt] = join(preproc_dir, json.split(sep)[-1]) cnt += 1 system('cp {} {}'.format(b1_map_nifti, preproc_dir)) b1_map_nifti = join(preproc_dir, b1_map_nifti.split(sep)[-1]) system('gunzip -df {}'.format(b1_map_nifti)) b1_map_nifti = join(preproc_dir, b1_map_nifti.split(sep)[-1].split('.')[0] + '.nii') system('cp {} {}'.format(b1_map_json, preproc_dir)) b1_map_json = join(preproc_dir, b1_map_json.split(sep)[-1]) # preprocessing step: spatial normalization to MNI space # of T1 maps if do_normalise_before: time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] segmenting highest flip angle image'.format( time_elapsed)) image = niftis[-1] out_info = segment(image, True) # save normalised segments segments = [ join(preproc_dir, f"w{out_info[segment].split('/')[-1]}") for segment in ['gm', 'wm'] ] time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] transforming images to MNI space...'.format( time_elapsed)) normed_niftis = [] cnt = 0 for nii in niftis: image = nii if cnt == len(niftis) - 1: b1_map = b1_map_nifti out_info = to_MNI(image, data=out_info, func=b1_map) normed_b1_map = out_info['func'][0] else: out_info = to_MNI(image, data=out_info) normed_niftis.append(out_info['anat']) time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] \t transformed {}'.format( time_elapsed, nii.split(sep)[-1])) cnt = cnt + 1 # preprocessing step: segmenting largest flip angle image if do_segment: time_elapsed = time.time() - start_time if do_normalise_before: print('[INFO, t={:.2f}s] creating a mask'.format(time_elapsed)) image = normed_niftis[-1] mni = compute_brain_mask(image) closed_mni = closing(mni, 12) union = intersect_masks([mni, closed_mni], threshold=0) else: print('[INFO, t={:.2f}s] segmenting highest flip angle image'. format(time_elapsed)) image = niftis[-1] out_info = segment(image, True) segments = [out_info['gm'], out_info['wm']] time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] \t segmented {}'.format( time_elapsed, image.split(sep)[-1])) # preprocessing step: creating a mask print('[INFO, t={:.2f}s] creating a mask using segments'.format( time_elapsed)) add = math_img("img1 + img2", img1=segments[0], img2=segments[1]) if sub_name == 'sub-08': full = compute_epi_mask(add, exclude_zeros=True) else: full = compute_epi_mask(add) insides = compute_background_mask(full, opening=12) union = intersect_masks([full, insides], threshold=0) mask_file = join(preproc_dir, 'mask.nii') union.to_filename(mask_file) # estimation directory setup time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] starting estimation...'.format(time_elapsed)) recon_dir = join(cwd, 'tmp_t1', 'recon') if not exists(recon_dir): makedirs(recon_dir) jsons_str = ' '.join(jsons) if do_normalise_before: niftis_str = ' '.join(normed_niftis) b1_map_str = normed_b1_map else: niftis_str = ' '.join(niftis) b1_map_str = b1_map_nifti if do_segment == False: mask_file = None # estimation: parameter extraction system(f"python3 ../scripts/qmri_t1_map_b1_params.py\ -v 1\ -s {sub_name}\ -o {recon_dir}\ -g {jsons_str}\ -b {b1_map_json}") # estimation: t1 estimation system(f"python3 ../scripts/qmri_t1_map_b1.py\ -v 1\ -s {sub_name}\ -o {recon_dir}\ -g {niftis_str}\ -b {b1_map_str}\ -r {join(recon_dir,f'{sub_name}_t1_map_b1.json')}\ -d fit\ -m {mask_file}") recon_map = join(recon_dir, f'{sub_name}_T1map.nii.gz') # postprocessing: normalization of reconstructed t1 map if do_normalise_after: postproc_dir = join(cwd, 'tmp_t1', 'postproc') if not exists(postproc_dir): makedirs(postproc_dir) recon_map = join(recon_dir, f'{sub_name}_T1map.nii.gz') system('cp {} {}'.format(recon_map, postproc_dir)) time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] normalizing reconstructed t1 map...'.format( time_elapsed)) image = join(postproc_dir, f'{sub_name}_T1map.nii.gz') system('gunzip -df {}'.format(image)) image = join(postproc_dir, f'{sub_name}_T1map.nii') out_info = to_MNI(image, segmented=out_info.nipype_results['segment']) norm_recon_map = out_info['anat'] # doing the plots if do_plot: time_elapsed = time.time() - start_time print('\n[INFO, t={:.2f}s] plotting the map...'.format(time_elapsed)) plot_dir = join(cwd, 'tmp_t1', 'plot') if not exists(plot_dir): makedirs(plot_dir) if do_normalise_after: t1_img = norm_recon_map else: t1_img = join(recon_dir, f'{sub_name}_T1map.nii.gz') plot_thresholded_qmap(img=t1_img, thresh="99", map=f"{sub_name}_T1map_fit", interactive=True, coords=(10, 56, 43), output_folder=plot_dir) time_elapsed = time.time() - start_time print('\n[INFO, t={:.2f}s] DONE'.format(time_elapsed)) # move derived files out and delete tmp_t1 directory final_recon_map = join(SAVE_TO, f'{sub_name}_space-{space}_T1map.nii.gz') if do_normalise_after: system('gzip {}'.format(norm_recon_map)) recon_map = norm_recon_map + '.gz' shutil.move(recon_map, final_recon_map) if do_plot: for fi in listdir(plot_dir): plot_name = join(plot_dir, fi) final_plot_name = join( SAVE_TO, final_recon_map.split(sep)[-1].split('.')[0] + '_' + fi.split('_')[-1]) shutil.move(plot_name, final_plot_name) if not keep_tmp: shutil.rmtree(join(SAVE_TO, 'tmp_t1')) time_elapsed = time.time() - start_time print('\n[INFO, t={:.2f}s] created {} \n\n'.format( time_elapsed, final_recon_map))
def t2_pipeline(do_coreg=True, do_normalise_before=False, do_segment=True, do_normalise_after=False, do_plot=True, keep_tmp=True, sub_name='sub-11', sess_num='ses-17', root_path='/neurospin/ibc'): """ Preprocess qMRI t2 images and then run estimation to generate t2-maps, more details in scripts/qmri_README.md, only one of do_normalise_before and do_normalise_after should be True, both can be False """ DATA_LOC = join(root_path, 'sourcedata', sub_name, sess_num) SAVE_TO = join(root_path, 'derivatives', sub_name, sess_num) if do_normalise_before or do_normalise_after: space = "MNI152" else: space = "individual" if not exists(SAVE_TO): makedirs(SAVE_TO) start_time = time.time() # data files data_dir = DATA_LOC niftis = [] jsons = [] for fi in listdir(join(data_dir, 'anat')): if fi.split('_')[-1] == 'T2map.nii.gz': niftis.append(join(data_dir, 'anat', fi)) elif fi.split('_')[-1] == 'T2map.json': jsons.append(join(data_dir, 'anat', fi)) else: continue niftis.sort() jsons.sort() run_count = 0 for nifti in niftis: # preprocessing directory setup time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] copying necessary files...'.format( time_elapsed)) cwd = SAVE_TO preproc_dir = join(cwd, 'tmp_t2', 'preproc') if not exists(preproc_dir): makedirs(preproc_dir) system('cp {} {}'.format(nifti, preproc_dir)) nifti = join(preproc_dir, nifti.split(sep)[-1]) system('gunzip -df {}'.format(nifti)) nifti = join(preproc_dir, nifti.split(sep)[-1].split('.')[0] + '.nii') if do_coreg: # t1 image as an anatomical image t1_niftis = [] for fi in listdir(join(data_dir, 'anat')): if fi.split('_')[-1] == 'T1map.nii.gz': t1_niftis.append(join(data_dir, 'anat', fi)) t1_niftis.sort() t1_nifti = t1_niftis[-1] system('cp {} {}'.format(t1_nifti, preproc_dir)) t1_nifti = join(preproc_dir, t1_nifti.split(sep)[-1]) system('gunzip -df {}'.format(t1_nifti)) t1_nifti = join(preproc_dir, t1_nifti.split(sep)[-1].split('.')[0] + '.nii') # preprocessing step: spatial normalization to MNI space # of T1 maps if do_normalise_before: image = nifti if do_coreg: t1_img = t1_nifti time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] segmenting the t1 image'.format( time_elapsed)) out_info = segment(t1_img, False) time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] transforming images to MNI space...'. format(time_elapsed)) out_info = to_MNI(image=t1_img, data=out_info, func=image) normed_t1_img = out_info['anat'] normed_nifti = out_info['func'][0] else: time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] segmenting the t2 image'.format( time_elapsed)) out_info = segment(image, False) time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] transforming images to MNI space...'. format(time_elapsed)) out_info = to_MNI(image, data=out_info) normed_nifti = out_info['anat'] time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] \t transformed {}'.format( time_elapsed, nifti.split(sep)[-1])) # preprocessing step: transform t1 image to t2 space if do_coreg: time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] transforming t1 image to t2 space...'. format(time_elapsed)) if do_normalise_before: t2_img = normed_nifti t1_img = normed_t1_img else: t2_img = nifti t1_img = t1_nifti mean_t2 = mean_img(t2_img) mean_t2_img = join(preproc_dir, 'mean_{}'.format(t2_img.split(sep)[-1])) mean_t2.to_filename(mean_t2_img) out_info = to_T2space(t2_img=mean_t2_img, t1_img=t1_img, output_dir=preproc_dir) print('[INFO, t={:.2f}s] \t transformed {} to {} space'.format( time_elapsed, t1_img.split(sep)[-1], mean_t2_img.split(sep)[-1])) # preprocessing step: segmenting largest flip angle image if do_segment: if do_normalise_before: time_elapsed = time.time() - start_time print( '[INFO, t={:.2f}s] creating a mask'.format(time_elapsed)) if do_coreg: image = normed_t1_img else: image = normed_nifti mni = compute_brain_mask(image) closed_mni = closing(mni, 12) union = intersect_masks([mni, closed_mni], threshold=0) else: if do_coreg: image = t1_img else: image = nifti time_elapsed = time.time() - start_time print( '[INFO, t={:.2f}s] segmenting the image for creating a mask' .format(time_elapsed)) out_info = segment(image, False) segments = [out_info['gm'], out_info['wm']] time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] \t segmented {}'.format( time_elapsed, image.split(sep)[-1])) # preprocessing step: creating a mask time_elapsed = time.time() - start_time print( '[INFO, t={:.2f}s] creating a mask using segments'.format( time_elapsed)) add = math_img("img1 + img2", img1=segments[0], img2=segments[1]) if sub_name == 'sub-08': full = compute_epi_mask(add, exclude_zeros=True) else: full = compute_epi_mask(add) insides = compute_background_mask(full, opening=12) union = intersect_masks([full, insides], threshold=0) mask_file = join(preproc_dir, 'mask.nii') union.to_filename(mask_file) if do_coreg: resampled_mask = resample_to_img(mask_file, mean_t2_img, clip=True) rounded_resampled_mask = math_img('np.around(img1)', img1=resampled_mask) resampled_mask_img = join(preproc_dir, 'resampled_mask.nii') rounded_resampled_mask.to_filename(resampled_mask_img) else: resampled_mask_img = mask_file # estimation directory setup time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] starting estimation...'.format(time_elapsed)) recon_dir = join(cwd, 'tmp_t2', 'recon') if not exists(recon_dir): makedirs(recon_dir) if do_normalise_before: niftis_str = normed_nifti else: niftis_str = nifti if do_segment == False: mask_file = None # estimation: t2 estimation system(f"python3 ../scripts/qmri_t2_map.py\ -v 1\ -s {sub_name}\ -o {recon_dir}\ -n {niftis_str}\ -m {resampled_mask_img}") recon_map = join(recon_dir, f'{sub_name}_T2map.nii.gz') # postprocessing: normalization of reconstructed t1 map if do_normalise_after: postproc_dir = join(cwd, 'tmp_t2', 'postproc') if not exists(postproc_dir): makedirs(postproc_dir) system('cp {} {}'.format(recon_map, postproc_dir)) time_elapsed = time.time() - start_time print('[INFO, t={:.2f}s] normalizing reconstructed map...'.format( time_elapsed)) image = join(postproc_dir, f'{sub_name}_T2map.nii.gz') system('gunzip -df {}'.format(image)) image = join(postproc_dir, f'{sub_name}_T2map.nii') out_info = to_MNI(image, segmented=out_info.nipype_results['segment']) norm_recon_map = out_info['anat'] # doing the plots if do_plot: time_elapsed = time.time() - start_time print('\n[INFO, t={:.2f}s] plotting the map...'.format( time_elapsed)) plot_dir = join(cwd, 'tmp_t2', 'plot') if not exists(plot_dir): makedirs(plot_dir) if do_normalise_after: t2_img = norm_recon_map else: t2_img = recon_map plot_thresholded_qmap(img=t2_img, thresh="95", map=f"{sub_name}_T2map", interactive=True, coords=(10, 56, 43), output_folder=plot_dir) time_elapsed = time.time() - start_time print('\n[INFO, t={:.2f}s] DONE'.format(time_elapsed)) # move derived files out and delete tmp_t2 directory final_recon_map = join( SAVE_TO, f'{sub_name}_run-0{run_count+1}_space-{space}_T2map.nii.gz') if do_normalise_after: system('gzip {}'.format(norm_recon_map)) recon_map = norm_recon_map + '.gz' shutil.move(recon_map, final_recon_map) if do_plot: for fi in listdir(plot_dir): plot_name = join(plot_dir, fi) final_plot_name = join( SAVE_TO, final_recon_map.split(sep)[-1].split('.')[0] + '_' + fi.split('_')[-1]) shutil.move(plot_name, final_plot_name) if not keep_tmp: shutil.rmtree(join(SAVE_TO, 'tmp_t2')) time_elapsed = time.time() - start_time print('\n[INFO, t={:.2f}s] created {} \n\n'.format( time_elapsed, final_recon_map)) run_count = run_count + 1