def calc_compcor_components(data_filename, num_components, mask_filename): if num_components < 1: raise ValueError( 'Improper value for num_components ({0}), should be >= 1.'.format( num_components)) try: image_data = nb.load(data_filename).get_data().astype(np.float64) except: print('Unable to load data from {0}'.format(data_filename)) raise try: binary_mask = nb.load(mask_filename).get_data().astype(np.int16) except: print('Unable to load data from {0}'.format(mask_filename)) if not safe_shape(image_data, binary_mask): raise ValueError( 'The data in {0} and {1} do not have a consistent shape'.format( data_filename, mask_filename)) # make sure that the values in binary_mask are binary binary_mask[binary_mask > 0] = 1 binary_mask[binary_mask != 1] = 0 # reduce the image data to only the voxels in the binary mask image_data = image_data[binary_mask == 1, :] # filter out any voxels whose variance equals 0 print('Removing zero variance components') image_data = image_data[image_data.std(1) != 0, :] if image_data.shape.count(0): err = "\n\n[!] No wm or csf signals left after removing those " \ "with zero variance.\n\n" raise Exception(err) print('Detrending and centering data') Y = signal.detrend(image_data, axis=1, type='linear').T Yc = Y - np.tile(Y.mean(0), (Y.shape[0], 1)) Yc = Yc / np.tile( np.array(Yc.std(0)).reshape(1, Yc.shape[1]), (Yc.shape[0], 1)) print('Calculating SVD decomposition of Y*Y\'') U, S, Vh = np.linalg.svd(Yc, full_matrices=False) # write out the resulting regressor file regressor_file = os.path.join(os.getcwd(), 'compcor_regressors.1D') np.savetxt(regressor_file, U[:, :num_components], delimiter='\t', fmt='%16g') return regressor_file
def extract_tissue_data(data_file, ho_mask_file, wm_seg_file, csf_seg_file, gm_seg_file, wm_threshold=0.0, csf_threshold=0.0, gm_threshold=0.0): import numpy as np import nibabel as nb import os from CPAC.nuisance import erode_mask from CPAC.utils import safe_shape data = nb.load(data_file).get_data().astype('float64') ho_mask = nb.load(ho_mask_file).get_data().astype('float64') wm_seg = nb.load(wm_seg_file).get_data().astype('float64') csf_seg = nb.load(csf_seg_file).get_data().astype('float64') gm_seg = nb.load(gm_seg_file).get_data().astype('float64') print 'Tissues extraction thresholds wm %d, csf %d, gm %d' % (wm_threshold, csf_threshold, gm_threshold) if not safe_shape(data, ho_mask, wm_seg, csf_seg, gm_seg): raise ValueError('Spatial dimensions for data, masks and tissues do not match') wm_mask = erode_mask(wm_seg > wm_threshold) # Only take the CSF at the lateral ventricals as labled in the Harvard # Oxford parcellation regions 4 and 43 csf_mask = (csf_seg > csf_threshold)*((ho_mask==43) + (ho_mask == 4)) gm_mask = erode_mask(gm_seg > gm_threshold) wm_sigs = data[wm_mask] csf_sigs = data[csf_mask] gm_sigs = data[gm_mask] file_wm = os.path.join(os.getcwd(), 'wm_signals.npy') file_csf = os.path.join(os.getcwd(), 'csf_signals.npy') file_gm = os.path.join(os.getcwd(), 'gm_signals.npy') np.save(file_wm, wm_sigs) np.save(file_csf, csf_sigs) np.save(file_gm, gm_sigs) nii = nb.load(wm_seg_file) wm_mask_file = os.path.join(os.getcwd(), 'wm_mask.nii.gz') csf_mask_file = os.path.join(os.getcwd(), 'csf_mask.nii.gz') gm_mask_file = os.path.join(os.getcwd(), 'gm_mask.nii.gz') nb.Nifti1Image(wm_mask, header=nii.get_header(), affine=nii.get_affine()).to_filename(wm_mask_file) nb.Nifti1Image(csf_mask, header=nii.get_header(), affine=nii.get_affine()).to_filename(csf_mask_file) nb.Nifti1Image(gm_mask, header=nii.get_header(), affine=nii.get_affine()).to_filename(gm_mask_file) return file_wm, file_csf, file_gm
def nifti_individual_stability(subject_file, roi_mask_file, n_bootstraps, k_clusters, cbb_block_size = None, affinity_threshold = 0.5): """ Calculate the individual stability matrix for a single subject by using Circular Block Bootstrapping method for time-series data. Parameters ---------- subject_file : string Nifti file of a subject roi_mask_file : string Region of interest (this method is too computationally intensive to perform on a whole-brain volume) n_bootstraps : integer Number of bootstraps k_clusters : integer Number of clusters cbb_block_size : integer, optional Size of the time-series block when performing circular block bootstrap affinity_threshold : float, optional Minimum threshold for similarity matrix based on correlation to create an edge Returns ------- ism : array_like Individual stability matrix of shape (`V`, `V`), `V` voxels """ print(('Calculating individual stability matrix of:', subject_file)) from CPAC.basc import individual_stability_matrix from CPAC.utils import safe_shape import nibabel as nb import numpy as np import os data = nb.load(subject_file).get_data().astype('float64') roi_mask_file = nb.load(roi_mask_file).get_data().astype('float64').astype('bool') if not safe_shape(roi_mask_file, data): raise ValueError('Subject %s with volume shape %s conflicts with mask shape %s' % (subject_file, str(data.shape[:3]), str(roi_mask_file.shape)) ) Y = data[roi_mask_file].T print(('(%i timepoints, %i voxels) and %i bootstraps' % (Y.shape[0], Y.shape[1], n_bootstraps))) ism = individual_stability_matrix(Y, n_bootstraps, k_clusters, cbb_block_size=cbb_block_size, affinity_threshold=affinity_threshold) ism_file = os.path.join(os.getcwd(), 'individual_stability_matrix.npy') np.save(ism_file, ism) print(('Saving individual stability matrix %s for %s' % (ism_file, subject_file))) return ism_file
def nifti_individual_stability(subject_file, roi_mask_file, n_bootstraps, k_clusters, cbb_block_size = None, affinity_threshold = 0.5): """ Calculate the individual stability matrix for a single subject by using Circular Block Bootstrapping method for time-series data. Parameters ---------- subject_file : string Nifti file of a subject roi_mask_file : string Region of interest (this method is too computationally intensive to perform on a whole-brain volume) n_bootstraps : integer Number of bootstraps k_clusters : integer Number of clusters cbb_block_size : integer, optional Size of the time-series block when performing circular block bootstrap affinity_threshold : float, optional Minimum threshold for similarity matrix based on correlation to create an edge Returns ------- ism : array_like Individual stability matrix of shape (`V`, `V`), `V` voxels """ print 'Calculating individual stability matrix of:', subject_file from CPAC.basc import individual_stability_matrix from CPAC.utils import safe_shape import nibabel as nb import numpy as np import os data = nb.load(subject_file).get_data().astype('float64') roi_mask_file = nb.load(roi_mask_file).get_data().astype('float64').astype('bool') if not safe_shape(roi_mask_file, data): raise ValueError('Subject %s with volume shape %s conflicts with mask shape %s' % (subject_file, str(data.shape[:3]), str(roi_mask_file.shape)) ) Y = data[roi_mask_file].T print '(%i timepoints, %i voxels) and %i bootstraps' % (Y.shape[0], Y.shape[1], n_bootstraps) ism = individual_stability_matrix(Y, n_bootstraps, k_clusters, cbb_block_size=cbb_block_size, affinity_threshold=affinity_threshold) ism_file = os.path.join(os.getcwd(), 'individual_stability_matrix.npy') np.save(ism_file, ism) print 'Saving individual stability matrix %s for %s' % (ism_file, subject_file) return ism_file
def joint_mask(subjects_file_list, mask_file, dtype='float64'): """ Creates a joint mask (intersection) common to all the subjects in a provided list and a provided mask. The mask for each subject is created by first computing the standard deviation at each voxel (i.e., a voxelwise maps of the std across time). Then this standard deviation map is binarized and used as the mask. Parameters ---------- subjects_file_list : list of strings A length `N` list of file paths of the nifti files of subjects mask_file : string Path to a mask file in nifti format (this will serve as a prior mask) dtype : string Numpy data type, should be one of 'float16', 'float32', or 'float64' Returns ------- joint_mask : string Path to joint mask file in nifti format (this will be the current directory followed by join_mask.nii.gz) """ import nibabel as nb import numpy as np import os from CPAC.utils import safe_shape mask_img = nb.load(mask_file) mask = mask_img.get_data().astype('bool') for subject_file in subjects_file_list: subj_mask = nb.load(subject_file).get_data().astype(dtype).std(-1) if not safe_shape(subj_mask, mask): raise ValueError('Subject %s with volume shape %s conflicts \ with mask shape %s' % ( subject_file, str(subj_mask.shape), str(mask.shape) ) ) mask *= subj_mask.astype('bool') print '... joint subject/roi mask loaded' img = nb.Nifti1Image(mask, header=mask_img.get_header(), affine=mask_img.get_affine()) img_file = os.path.join(os.getcwd(), 'joint_mask.nii.gz') img.to_filename(img_file) return img_file
def joint_mask(subjects_file_list, mask_file): """ Creates a joint mask (intersection) common to all the subjects in a provided list and a provided mask Parameters ---------- subjects_file_list : list of strings A length `N` list of file paths of the nifti files of subjects mask_file : string Path to a mask file in nifti format Returns ------- joint_mask : string Path to joint mask file in nifti format """ import nibabel as nb import numpy as np import os from CPAC.utils import safe_shape nii = nb.load(mask_file) mask = nii.get_data().astype('bool') for subject_file in subjects_file_list: sdata = nb.load(subject_file).get_data().astype(np.float64).sum(-1) if not safe_shape(sdata, mask): raise ValueError('Subject %s with volume shape %s conflicts \ with mask shape %s' % (subject_file, str(sdata.shape), str(mask.shape))) mask *= sdata.astype('bool') print '... joint subject/roi mask loaded' img = nb.Nifti1Image(mask, header=nii.get_header(), affine=nii.get_affine()) img_file = os.path.join(os.getcwd(), 'joint_mask.nii.gz') img.to_filename(img_file) return img_file
def joint_mask(subjects_file_list, mask_file): """ Creates a joint mask (intersection) common to all the subjects in a provided list and a provided mask Parameters ---------- subjects_file_list : list of strings A length `N` list of file paths of the nifti files of subjects mask_file : string Path to a mask file in nifti format Returns ------- joint_mask : string Path to joint mask file in nifti format """ import nibabel as nb import numpy as np import os from CPAC.utils import safe_shape nii = nb.load(mask_file) mask = nii.get_data().astype("bool") for subject_file in subjects_file_list: sdata = nb.load(subject_file).get_data().astype(np.float64).sum(-1) if not safe_shape(sdata, mask): raise ValueError( "Subject %s with volume shape %s conflicts \ with mask shape %s" % (subject_file, str(sdata.shape), str(mask.shape)) ) mask *= sdata.astype("bool") print "... joint subject/roi mask loaded" img = nb.Nifti1Image(mask, header=nii.get_header(), affine=nii.get_affine()) img_file = os.path.join(os.getcwd(), "joint_mask.nii.gz") img.to_filename(img_file) return img_file
def extract_tissue_data(data_file, ventricles_mask_file, wm_seg_file, csf_seg_file, gm_seg_file, wm_threshold=0.0, csf_threshold=0.0, gm_threshold=0.0): import numpy as np import nibabel as nb import os from CPAC.nuisance import erode_mask from CPAC.utils import safe_shape print('Tissues extraction thresholds wm %d, csf %d, gm %d' % (wm_threshold, csf_threshold, gm_threshold)) try: data = nb.load(data_file).get_data().astype('float64') except: raise MemoryError('Unable to load %s' % data_file) try: lat_ventricles_mask = nb.load(ventricles_mask_file).get_data().astype('float64') except: raise MemoryError('Unable to load %s' % lat_ventricles_mask) if not safe_shape(data, lat_ventricles_mask): raise ValueError('Spatial dimensions for data and the lateral ventricles mask do not match') try: wm_seg = nb.load(wm_seg_file).get_data().astype('float64') except: raise MemoryError('Unable to load %s' % wm_seg) if not safe_shape(data, wm_seg): raise ValueError('Spatial dimensions for data, white matter segment do not match') wm_mask = erode_mask(wm_seg > wm_threshold) wm_sigs = data[wm_mask] file_wm = os.path.join(os.getcwd(), 'wm_signals.npy') np.save(file_wm, wm_sigs) del wm_sigs try: csf_seg = nb.load(csf_seg_file).get_data().astype('float64') except: raise MemoryError('Unable to load %s' % csf_seg) if not safe_shape(data, csf_seg): raise ValueError('Spatial dimensions for data, cerebral spinal fluid segment do not match') # Only take the CSF at the lateral ventricles as labeled in the Harvard # Oxford parcellation regions 4 and 43 csf_mask = (csf_seg > csf_threshold)*(lat_ventricles_mask==1) csf_sigs = data[csf_mask] file_csf = os.path.join(os.getcwd(), 'csf_signals.npy') np.save(file_csf, csf_sigs) del csf_sigs try: gm_seg = nb.load(gm_seg_file).get_data().astype('float64') except: raise MemoryError('Unable to load %s' % gm_seg) if not safe_shape(data, gm_seg): raise ValueError('Spatial dimensions for data, gray matter segment do not match') gm_mask = erode_mask(gm_seg > gm_threshold) gm_sigs = data[gm_mask] file_gm = os.path.join(os.getcwd(), 'gm_signals.npy') np.save(file_gm, gm_sigs) del gm_sigs nii = nb.load(wm_seg_file) wm_mask_file = os.path.join(os.getcwd(), 'wm_mask.nii.gz') csf_mask_file = os.path.join(os.getcwd(), 'csf_mask.nii.gz') gm_mask_file = os.path.join(os.getcwd(), 'gm_mask.nii.gz') nb.Nifti1Image(wm_mask, header=nii.get_header(), affine=nii.get_affine()).to_filename(wm_mask_file) nb.Nifti1Image(csf_mask, header=nii.get_header(), affine=nii.get_affine()).to_filename(csf_mask_file) nb.Nifti1Image(gm_mask, header=nii.get_header(), affine=nii.get_affine()).to_filename(gm_mask_file) return file_wm, file_csf, file_gm
def extract_tissue_data(data_file, ho_mask_file, wm_seg_file, csf_seg_file, gm_seg_file, wm_threshold=0.0, csf_threshold=0.0, gm_threshold=0.0): import numpy as np import nibabel as nb import os from CPAC.nuisance import erode_mask from CPAC.utils import safe_shape print 'Tissues extraction thresholds wm %d, csf %d, gm %d' % ( wm_threshold, csf_threshold, gm_threshold) try: data = nb.load(data_file).get_data().astype('float64') except: raise MemoryError('Unable to load %s' % data_file) try: ho_mask = nb.load(ho_mask_file).get_data().astype('float64') except: raise MemoryError('Unable to load %s' % ho_mask) if not safe_shape(data, ho_mask): raise ValueError( 'Spatial dimensions for data and ho_mask do not match') try: wm_seg = nb.load(wm_seg_file).get_data().astype('float64') except: raise MemoryError('Unable to load %s' % wm_seg) if not safe_shape(data, wm_seg): raise ValueError( 'Spatial dimensions for data, white matter segment do not match') wm_mask = erode_mask(wm_seg > wm_threshold) wm_sigs = data[wm_mask] file_wm = os.path.join(os.getcwd(), 'wm_signals.npy') np.save(file_wm, wm_sigs) del wm_sigs try: csf_seg = nb.load(csf_seg_file).get_data().astype('float64') except: raise MemoryError('Unable to load %s' % csf_seg) if not safe_shape(data, csf_seg): raise ValueError( 'Spatial dimensions for data, cerebral spinal fluid segment do not match' ) # Only take the CSF at the lateral ventricals as labled in the Harvard # Oxford parcellation regions 4 and 43 csf_mask = (csf_seg > csf_threshold) * ((ho_mask == 43) + (ho_mask == 4)) csf_sigs = data[csf_mask] file_csf = os.path.join(os.getcwd(), 'csf_signals.npy') np.save(file_csf, csf_sigs) del csf_sigs try: gm_seg = nb.load(gm_seg_file).get_data().astype('float64') except: raise MemoryError('Unable to load %s' % gm_seg) if not safe_shape(data, gm_seg): raise ValueError( 'Spatial dimensions for data, gray matter segment do not match') gm_mask = erode_mask(gm_seg > gm_threshold) gm_sigs = data[gm_mask] file_gm = os.path.join(os.getcwd(), 'gm_signals.npy') np.save(file_gm, gm_sigs) del gm_sigs nii = nb.load(wm_seg_file) wm_mask_file = os.path.join(os.getcwd(), 'wm_mask.nii.gz') csf_mask_file = os.path.join(os.getcwd(), 'csf_mask.nii.gz') gm_mask_file = os.path.join(os.getcwd(), 'gm_mask.nii.gz') nb.Nifti1Image(wm_mask, header=nii.get_header(), affine=nii.get_affine()).to_filename(wm_mask_file) nb.Nifti1Image(csf_mask, header=nii.get_header(), affine=nii.get_affine()).to_filename(csf_mask_file) nb.Nifti1Image(gm_mask, header=nii.get_header(), affine=nii.get_affine()).to_filename(gm_mask_file) return file_wm, file_csf, file_gm