def test_save_vols(): # setup n_scans = 10 output_dir = os.path.join(OUTPUT_DIR, inspect.stack()[0][3]) if not os.path.exists(output_dir): os.makedirs(output_dir) # create 4D film film = create_random_image(ndim=4, n_scans=n_scans) threeD_vols = nibabel.four_to_three(film) # save vols manually film_filename = os.path.join(output_dir, "film.nii.gz") threeD_vols_filenames = [os.path.join(output_dir, "fMETHODS-%06i" % i) for i in range(len(threeD_vols))] # check saving seperate 3D vols for stuff in [film, threeD_vols]: if isinstance(stuff, list): basenames = [os.path.basename(x) for x in threeD_vols_filenames] else: basenames = os.path.basename(film_filename) for concat in [False, True]: for bn in [None, basenames]: saved_vols_filenames = save_vols(stuff, output_dir, ext=".nii.gz", concat=concat, basenames=bn) if not concat and isinstance(stuff, list): assert_true(isinstance(saved_vols_filenames, list)) assert_equal(len(saved_vols_filenames), n_scans) if not bn is None: assert_equal(os.path.basename(saved_vols_filenames[7]), "fMETHODS-000007.nii.gz") else: assert_true(isinstance(saved_vols_filenames, basestring)) assert_true(saved_vols_filenames.endswith(".nii.gz"), msg=saved_vols_filenames) assert_true(is_4D(check_niimg_4d(saved_vols_filenames)))
def load_vols(niimgs): """Loads a nifti image (or a bail of) into a list qof 3D volumes. Parameters ---------- niimgs: 3 or 4D Niimg-like object If niimgs is an iterable, checks if data is really 4D. Then, considering that it is a list of niimg and load them one by one. If niimg is a string, consider it as a path to Nifti image and call nibabel.load on it. If it is an object, check if get_data and get_affine methods are present, raise an Exception otherwise. Returns ------- niimgs_: list of nifti image objects The loaded volumes. """ # try loading 4d try: niimgs = list(check_niimg_4d(niimgs, return_iterator=True)) except TypeError: # probably not 4d niimgs = [check_niimg(niimgs)] except ValueError: # probably inconsisten affines pass try: # try loading volumes one-by-one if isinstance(niimgs, _basestring): niimgs = [niimgs] return [check_niimg(niimg, ensure_ndim=3) for niimg in niimgs] except TypeError: pass # collect the loaded volumes into a list if is_niimg(niimgs): # should be 3d, squash 4th dimension otherwise if niimgs.shape[-1] == 1: return [ nibabel.Nifti1Image(niimgs.get_data()[:, :, :, 0], niimgs.get_affine()) ] else: return list(iter_img(niimgs)) else: niimgs = list(niimgs) if len(niimgs) == 1: niimgs = niimgs[0] return list(iter_img(niimgs))
def load_vols(niimgs): """Loads a nifti image (or a bail of) into a list qof 3D volumes. Parameters ---------- niimgs: 3 or 4D Niimg-like object If niimgs is an iterable, checks if data is really 4D. Then, considering that it is a list of niimg and load them one by one. If niimg is a string, consider it as a path to Nifti image and call nibabel.load on it. If it is an object, check if get_data and get_affine methods are present, raise an Exception otherwise. Returns ------- niimgs_: list of nifti image objects The loaded volumes. """ # try loading 4d try: niimgs = list(check_niimg_4d(niimgs, return_iterator=True)) except TypeError: # probably not 4d niimgs = [check_niimg(niimgs)] except ValueError: # probably inconsisten affines pass try: # try loading volumes one-by-one if isinstance(niimgs, _basestring): niimgs = [niimgs] return [check_niimg(niimg, ensure_ndim=3) for niimg in niimgs] except TypeError: pass # collect the loaded volumes into a list if is_niimg(niimgs): # should be 3d, squash 4th dimension otherwise if niimgs.shape[-1] == 1: return [nibabel.Nifti1Image(niimgs.get_data()[:, :, :, 0], niimgs.get_affine())] else: return list(iter_img(niimgs)) else: niimgs = list(niimgs) if len(niimgs) == 1: niimgs = niimgs[0] return list(iter_img(niimgs))
def test_save_vols(): # setup n_scans = 10 output_dir = os.path.join(OUTPUT_DIR, inspect.stack()[0][3]) if not os.path.exists(output_dir): os.makedirs(output_dir) # create 4D film film = create_random_image(ndim=4, n_scans=n_scans) threeD_vols = nibabel.four_to_three(film) # save vols manually film_filename = os.path.join(output_dir, 'film.nii.gz') threeD_vols_filenames = [os.path.join(output_dir, 'fMETHODS-%06i' % i) for i in range(len(threeD_vols))] # check saving seperate 3D vols for stuff in [film, threeD_vols]: if isinstance(stuff, list): basenames = [os.path.basename(x) for x in threeD_vols_filenames] else: basenames = os.path.basename(film_filename) for concat in [False, True]: for bn in [None, basenames]: saved_vols_filenames = save_vols(stuff, output_dir, ext='.nii.gz', concat=concat, basenames=bn ) if not concat and isinstance(stuff, list): assert_true(isinstance( saved_vols_filenames, list)) assert_equal(len(saved_vols_filenames), n_scans) if not bn is None: assert_equal(os.path.basename(saved_vols_filenames[7]), 'fMETHODS-000007.nii.gz') else: assert_true(isinstance(saved_vols_filenames, basestring)) assert_true(saved_vols_filenames.endswith('.nii.gz'), msg=saved_vols_filenames) assert_true(is_4D(check_niimg_4d( saved_vols_filenames)))
def time_slice_diffs(img): ''' Time-point to time-point differences over volumes and slices We think of the passed array as an image. The last dimension is assumed to be time. Parameters ---------- img: 4D Niimg-like the input (4D) image Returns ------- results : dict ``T`` is the number of time points (``arr.shape[time_axis]``) ``S`` is the number of slices (``arr.shape[slice_axis]``) ``v`` is the shape of a volume (``rollimg(arr, time_axis)[0].shape``) ``d2[t]`` is the volume of squared differences between voxels at time point ``t`` and time point ``t+1`` `results` has keys: * 'volume_mean_diff2' : (T-1,) array array containing the mean (over voxels in volume) of the squared difference from one time point to the next * 'slice_mean_diff2' : (T-1, S) array giving the mean (over voxels in slice) of the squared difference from one time point to the next, one value per slice, per timepoint * 'volume_means' : (T,) array mean over voxels for each volume ``vol[t] for t in 0:T`` * 'slice_diff2_max_vol' : v[:] array volume, of same shape as input time point volumes, where each slice is is the slice from ``d2[t]`` for t in 0:T-1, that has the largest variance across ``t``. Thus each slice in the volume may well result from a different difference time point. * 'diff2_mean_vol`` : v[:] array volume with the mean of ``d2[t]`` across t for t in 0:T-1. ''' img = check_niimg_4d(img) shape = img.shape T = shape[-1] S = shape[-2] # presumably the slice axis -- to be reconsidered ? # loop over time points to save memory # initialize the results slice_squared_differences = np.empty((T - 1, S)) vol_mean = np.empty((T,)) diff_mean_vol = np.zeros(shape[:3]) slice_diff_max_vol = np.zeros(shape[:3]) slice_diff_max = np.zeros(S) arr = img.get_data() # inefficient ?? last_vol = arr[..., 0] vol_mean[0] = np.nanmean(last_vol) # loop over scans: increment statistics for vol_index in range(0, T - 1): current_vol = arr[..., vol_index + 1] # shape vol_shape vol_mean[vol_index + 1] = np.nanmean(current_vol) squared_diff = (current_vol - last_vol) ** 2 mask = np.isfinite(squared_diff) diff_mean_vol[mask] += squared_diff[mask] slice_squared_differences[vol_index] = np.nanmean( np.nanmean(squared_diff, 0), 0) # check whether we have found a highest-diff slice larger_diff = slice_squared_differences[vol_index] > slice_diff_max if any(larger_diff): slice_diff_max[larger_diff] =\ slice_squared_differences[vol_index][larger_diff] slice_diff_max_vol[..., larger_diff] =\ squared_diff[..., larger_diff] last_vol = current_vol vol_squared_differences = np.nanmean(slice_squared_differences, 1) diff_mean_vol /= (T - 1) # Remove remaining Nans # Nans may legitimally remain in slice_squared_differences slice_squared_differences[np.isnan(slice_squared_differences)] = 0 # and also in slice_diff_max_vol slice_diff_max_vol[np.isnan(slice_diff_max_vol)] = 0 # Return the outputs as images affine = img.get_affine() diff2_mean_vol = nib.Nifti1Image(diff_mean_vol, affine) slice_diff2_max_vol = nib.Nifti1Image(slice_diff_max_vol, affine) return {'volume_mean_diff2': vol_squared_differences, 'slice_mean_diff2': slice_squared_differences, 'volume_means': vol_mean, 'diff2_mean_vol': diff2_mean_vol, 'slice_diff2_max_vol': slice_diff2_max_vol, 'session_length': T}
def time_slice_diffs(img): ''' Time-point to time-point differences over volumes and slices We think of the passed array as an image. The last dimension is assumed to be time. Parameters ---------- img: 4D Niimg-like the input (4D) image Returns ------- results : dict ``T`` is the number of time points (``arr.shape[time_axis]``) ``S`` is the number of slices (``arr.shape[slice_axis]``) ``v`` is the shape of a volume (``rollimg(arr, time_axis)[0].shape``) ``d2[t]`` is the volume of squared differences between voxels at time point ``t`` and time point ``t+1`` `results` has keys: * 'volume_mean_diff2' : (T-1,) array array containing the mean (over voxels in volume) of the squared difference from one time point to the next * 'slice_mean_diff2' : (T-1, S) array giving the mean (over voxels in slice) of the squared difference from one time point to the next, one value per slice, per timepoint * 'volume_means' : (T,) array mean over voxels for each volume ``vol[t] for t in 0:T`` * 'slice_diff2_max_vol' : v[:] array volume, of same shape as input time point volumes, where each slice is is the slice from ``d2[t]`` for t in 0:T-1, that has the largest variance across ``t``. Thus each slice in the volume may well result from a different difference time point. * 'diff2_mean_vol`` : v[:] array volume with the mean of ``d2[t]`` across t for t in 0:T-1. ''' img = check_niimg_4d(img) shape = img.shape T = shape[-1] S = shape[-2] # presumably the slice axis -- to be reconsidered ? # loop over time points to save memory # initialize the results slice_squared_differences = np.empty((T - 1, S)) vol_mean = np.empty((T,)) diff_mean_vol = np.zeros(shape[:3]) slice_diff_max_vol = np.zeros(shape[:3]) slice_diff_max = np.zeros(S) arr = img.get_data() # inefficient ?? last_vol = arr[..., 0] vol_mean[0] = last_vol.mean() # loop over scans: increment statistics for vol_index in range(0, T - 1): current_vol = arr[..., vol_index + 1] # shape vol_shape vol_mean[vol_index + 1] = current_vol.mean() squared_diff = (current_vol - last_vol) ** 2 diff_mean_vol += squared_diff slice_squared_differences[vol_index] = squared_diff.mean(0).mean(0) # check whether we have found a highest-diff slice larger_diff = slice_squared_differences[vol_index] > slice_diff_max if any(larger_diff): slice_diff_max[larger_diff] =\ slice_squared_differences[vol_index][larger_diff] slice_diff_max_vol[..., larger_diff] =\ squared_diff[..., larger_diff] last_vol = current_vol vol_squared_differences = slice_squared_differences.mean(1) diff_mean_vol /= (T - 1) # Return the outputs as images affine = img.get_affine() diff2_mean_vol = nib.Nifti1Image(diff_mean_vol, affine) slice_diff2_max_vol = nib.Nifti1Image(slice_diff_max_vol, affine) return {'volume_mean_diff2': vol_squared_differences, 'slice_mean_diff2': slice_squared_differences, 'volume_means': vol_mean, 'diff2_mean_vol': diff2_mean_vol, 'slice_diff2_max_vol': slice_diff2_max_vol, 'session_length': T}