def test_mask_to(self): mask = '../neurora/template/ch2.nii.gz' size = [57, 67, 56] affine = np.array([[3, 0, 0, -78], [0, 2.866, -0.887, -76], [0, 0.887, 2.866, -64], [0, 0, 0, 1]]) output = mask_to(mask, size, affine) self.assertEqual(output, 0)
def stats_save_nii(corrs, filename, affine, corr_mask=get_HOcort(), size=[60, 60, 60], ksize=[3, 3, 3], strides=[1, 1, 1], p=0.05, df=20, correct_method=None, smooth=False, plotrlt=True, img_background=None): """ Save the searchlight RSA statistical results as a NIfTI file for fMRI Parameters ---------- corrs : array The statistical results between behavioral data and fMRI data for searchlight. The shape of RDMs is [n_x, n_y, n_z, 2]. n_x, n_y, n_z represent the number of calculation units for searchlight along the x, y, z axis and 2 represents a t-value and a p-value. filename : string. Default is 'rsa_result.nii'. The file path+filename for the result .nii file. If the filename does not end in ".nii", it will be filled in automatically. affine : array or list The position information of the fMRI-image array data in a reference space. corr_mask : string The filename of a mask data for correcting the RSA result. It can just be one of your fMRI data files in your experiment for a mask file for ROI. If the corr_mask is a filename of a ROI mask file, only the RSA results in ROI will be visible. size : array or list [nx, ny, nz]. Default is [60, 60, 60]. The size of the fMRI-img in your experiments. ksize : array or list [kx, ky, kz]. Default is [3, 3, 3]. The size of the fMRI-img. nx, ny, nz represent the number of voxels along the x, y, z axis strides : array or list [sx, sy, sz]. Default is [1, 1, 1]. The strides for calculating along the x, y, z axis. p : float. Default is 0.05. The threshold of p-values. Only the results those p-values are lower than this value will be visible. df : int. Default is 20. The degree of freedom. correct_method : None or string 'FWE' or 'FDR'. Default is None. The method for correcting the RSA results. If correct_method='FWE', here the FWE-correction will be used. If correct_methd='FDR', here the FDR-correction will be used. If correct_method=None, no correction. Only when p<1, correct_method works. smooth : bool True or False. Default is False. Smooth the RSA result or not. plotrlt : bool True or False. Default is True. Plot the RSA result automatically or not. img_background : None or string. Default if None. The filename of a background image that the RSA results will be plotted on the top of it. If img_background=None, the background will be ch2.nii.gz. Only when plotrlt=True, img_background works. Returns ------- img : array The array of the statistical results t-values map. The shape is [nx, ny, nz]. nx, ny, nz represent the size of the fMRI-img. Notes ----- A result .nii file of searchlight statistical results will be generated at the corresponding address of filename. """ # get the size of the fMRI-img nx = size[0] ny = size[1] nz = size[2] # the size of the calculation units for searchlight kx = ksize[0] ky = ksize[1] kz = ksize[2] # strides for calculating along the x, y, z axis sx = strides[0] sy = strides[1] sz = strides[2] # calculate the number of the calculation units in the x, y, z directions n_x = np.shape(corrs)[0] n_y = np.shape(corrs)[1] n_z = np.shape(corrs)[2] # initialize the indexes to record the number of valid values for each voxel index = np.zeros([nx, ny, nz], dtype=np.int) # initialize the img array to save the sum-r-value for each voxel img_nii = np.zeros([nx, ny, nz], dtype=np.float64) # iterate through all the calculation units # calculate the indexs for i in range(n_x): for j in range(n_y): for k in range(n_z): x = i * sx y = j * sy z = k * sz if (math.isnan(corrs[i, j, k, 0]) is False): for k1 in range(kx): for k2 in range(ky): for k3 in range(kz): index[x + k1, y + k2, z + k3] = index[x + k1, y + k2, z + k3] + 1 # initialize a mask in order to record valid voxels (have qualified results) mask = np.zeros([nx, ny, nz], dtype=np.int) # get the p-values corrsp = corrs[:, :, :, 1] # calculate the number of voxels for correction fadeimg = np.zeros([nx, ny, nz], dtype=np.int) for i in range(n_x): for j in range(n_y): for k in range(n_z): x = i * sx y = j * sy z = k * sz # p-values<threshold-p if corrsp[i, j, k] < p: for k1 in range(kx): for k2 in range(ky): for k3 in range(kz): fadeimg[x + k1, y + k2, z + k3] = 1 n_corrected = 0 for i in range(nx): for j in range(ny): for k in range(nz): if fadeimg[i, j, k] == 1: n_corrected = n_corrected + 1 print(str(n_corrected) + " voxels corrected") # do the correction if p < 1: # FDR-correction if correct_method == "FDR": corrsp = fdr_correct(corrsp, p_threshold=p) # FWE-correction if correct_method == "FWE": corrsp = fwe_correct(corrsp, p_threshold=p) # iterate through all the calculation units again # record the valid voxels # [n_x, n_y, n_z] expanses into [nx, ny, nz] based on ksize & strides for i in range(n_x): for j in range(n_y): for k in range(n_z): x = i * sx y = j * sy z = k * sz # p-values<threshold-p if corrsp[i, j, k] < p: for k1 in range(kx): for k2 in range(ky): for k3 in range(kz): mask[x + k1, y + k2, z + k3] = 1 # sum of valid values in each calculation units for i in range(n_x): for j in range(n_y): for k in range(n_z): x = i * sx y = j * sy z = k * sz if (math.isnan(corrs[i, j, k, 0]) is False): for k1 in range(kx): for k2 in range(ky): for k3 in range(kz): img_nii[x + k1, y + k2, z + k3] = img_nii[x + k1, y + k2, z + k3] + corrs[i, j, k, 0] # initialize the newimg array to calculate the avg-r-value for each voxel newimg_nii = np.full([nx, ny, nz], np.nan) t_threshold = t.isf(p, df) print(t_threshold) # calculate the avg values of each valid voxel for i in range(nx): for j in range(ny): for k in range(nz): # valid voxel if mask[i, j, k] == 1: # sum-r-value/index newimg_nii[i, j, k] = float(img_nii[i, j, k] / index[i, j, k]) # set filename for result .nii file if filename == None: filename = "rsa_result.nii" else: q = ".nii" in filename if q == True: filename = filename else: filename = filename + ".nii" # corr_mask != None # use the mask file to correct RSA results # in order to avoid results showing outside of the brain if corr_mask == get_HOcort(): mask_to(get_bg_ch2bet(), filename, size, affine) mask = nib.load(filename).get_data() print(mask.shape) else: # load the array data of the mask file mask = nib.load(corr_mask).get_data() # do correction by the mask for i in range(nx): for j in range(ny): for k in range(nz): if (math.isnan(mask[i, j, k]) == True) or mask[i, j, k] == 0: newimg_nii[i, j, k] = np.nan # do correction by the mask for i in range(nx): for j in range(ny): for k in range(nz): if (math.isnan(mask[i, j, k]) == True) or mask[i, j, k] == 0: newimg_nii[i, j, k] = np.nan if newimg_nii[i, j, k] < t_threshold and newimg_nii[i, j, k] > 0: newimg_nii[i, j, k] = np.nan if newimg_nii[i, j, k] > -t_threshold and newimg_nii[i, j, k] < 0: newimg_nii[i, j, k] = np.nan print(filename) # save the .nii file for RSA results file = nib.Nifti1Image(newimg_nii, affine) if smooth == True: # smooth the img data of the .nii file file = smooth_img(file, fwhm='fast') # save the result nib.save(file, filename) # determine if it has results norlt = np.isnan(newimg_nii).all() if norlt == True: print("No RSA result.") # determine plot the results or not if norlt == False and plotrlt == True: plot_brainrsa_rlts(filename, background=img_background, type='t') print("File(" + filename + ") saves successfully!") return newimg_nii
def stats_save_nii(stats, affine, filename=None, corr_mask=get_HOcort(), size=[60, 60, 60], ksize=[3, 3, 3], strides=[1, 1, 1], p=0.05, correct_method=None, clusterp=0.05, smooth=False, plotrlt=True, img_background=None): """ Save the searchlight RSA statistical results as a NIfTI file for fMRI Parameters ---------- stats : array The statistical results between behavioral data and fMRI data for searchlight. The shape of RDMs is [n_x, n_y, n_z, 2]. n_x, n_y, n_z represent the number of calculation units for searchlight along the x, y, z axis and 2 represents a t-value and a p-value. If the filename does not end in ".nii", it will be filled in automatically. affine : array or list The position information of the fMRI-image array data in a reference space. filename : string. Default is None - 'rsa_result.nii'. The file path+filename for the result .nii file. corr_mask : string The filename of a mask data for correcting the RSA result. It can just be one of your fMRI data files in your experiment for a mask file for ROI. If the corr_mask is a filename of a ROI mask file, only the RSA results in ROI will be visible. size : array or list [nx, ny, nz]. Default is [60, 60, 60]. The size of the fMRI-img in your experiments. ksize : array or list [kx, ky, kz]. Default is [3, 3, 3]. The size of the calculation unit for searchlight. kx, ky, kz represent the number of voxels along the x, y, z axis. strides : array or list [sx, sy, sz]. Default is [1, 1, 1]. The strides for calculating along the x, y, z axis. p : float. Default is 0.05. The threshold of p-values. Only the results those p-values are lower than this value will be visible. correct_method : None or string 'FWE' or 'FDR' or 'Cluster-FWE' or 'Cluster-FDR'. Default is None. The method for correcting the RSA results. If correct_method='FWE', here the FWE-correction will be used. If correct_methd='FDR', here the FDR-correction will be used. If correct_method='Cluster-FWE', here the Cluster-wise FWE-correction will be used. If correct_methd='Cluster-FDR', here the Cluster-wise FDR-correction will be used. If correct_method=None, no correction. Only when p<1, correct_method works. clusterp : float. Default is 0.05. The threshold of p-value for cluster-wise correction. Only when correct_method='Cluster-FDR' or 'Cluster-FWE', clusterp works. smooth : bool True or False. Default is False. Smooth the RSA result or not. plotrlt : bool True or False. Default is True. Plot the RSA result automatically or not. img_background : None or string. Default if None. The filename of a background image that the RSA results will be plotted on the top of it. If img_background=None, the background will be ch2.nii.gz. Only when plotrlt=True, img_background works. Returns ------- img : array The array of the statistical results t-values map. The shape is [nx, ny, nz]. nx, ny, nz represent the size of the fMRI-img. Notes ----- A result .nii file of searchlight statistical results will be generated at the corresponding address of filename. """ if len(np.shape(stats)) != 4 or len(np.shape(affine)) != 2 or np.shape(affine)[0] != 4 or np.shape(affine)[1] != 4: return "Invalid input!" # get the size of the fMRI-img nx = size[0] ny = size[1] nz = size[2] # the size of the calculation units for searchlight kx = ksize[0] ky = ksize[1] kz = ksize[2] rx = int((kx-1)/2) ry = int((ky-1)/2) rz = int((kz-1)/2) # strides for calculating along the x, y, z axis sx = strides[0] sy = strides[1] sz = strides[2] # calculate the number of the calculation units in the x, y, z directions n_x = np.shape(stats)[0] n_y = np.shape(stats)[1] n_z = np.shape(stats)[2] img_nii = np.zeros([nx, ny, nz], dtype=np.float64) # initialize a mask in order to record valid voxels (have qualified results) mask = np.zeros([nx, ny, nz], dtype=np.int) # get the p-values statsp = stats[:, :, :, 1] statst = stats[:, :, :, 0] # calculate the number of voxels for correction fadeimg = np.zeros([nx, ny, nz], dtype=np.int) # iterate through all the calculation units # calculate the indexs for i in range(n_x): for j in range(n_y): for k in range(n_z): x = i*sx y = j*sy z = k*sz if statsp[i, j, k] < 1: img_nii[x + rx, y + ry, z + rz] = statst[i, j, k] if statsp[i, j, k] < p: fadeimg[x + rx, y + ry, z + rz] = 1 n_corrected = 0 for i in range(nx): for j in range(ny): for k in range(nz): if fadeimg[i, j, k] == 1: n_corrected = n_corrected + 1 print(str(n_corrected)+" voxels will be corrected.") # do the correction if p < 1: # FDR-correction if correct_method == "FDR": statsp = fdr_correct(statsp, p_threshold=p) # FWE-correction if correct_method == "FWE": statsp = fwe_correct(statsp, p_threshold=p) # Cluster-wise FDR-correction if correct_method == "Cluster-FDR": statsp = cluster_fdr_correct(statsp, p_threshold1=p, p_threshold2=clusterp) # Cluster-wise FWE-correction if correct_method == "Cluster-FWE": statsp = cluster_fwe_correct(statsp, p_threshold1=p, p_threshold2=clusterp) # iterate through all the calculation units again print("Record the valid voxels.") for i in range(n_x): for j in range(n_y): for k in range(n_z): x = i * sx y = j * sy z = k * sz if statsp[i, j, k] < p: mask[x + rx, y + ry, z + rz] = 1 # initialize the newimg array to calculate the avg-r-value for each voxel newimg_nii = np.full([nx, ny, nz], np.nan) # set filename for result .nii file if filename == None: filename = "rsa_result.nii" else: q = ".nii" in filename if q == True: filename = filename else: filename = filename + ".nii" # corr_mask != None # use the mask file to correct RSA results # in order to avoid results showing outside of the brain if corr_mask == get_HOcort(): mask_to(get_bg_ch2bet(), size, affine, filename) cmask = nib.load(filename).get_fdata() else: # load the array data of the mask file cmask = nib.load(corr_mask).get_fdata() # calculate the avg values of each valid voxel for i in range(nx): for j in range(ny): for k in range(nz): # valid voxel if (math.isnan(cmask[i, j, k]) == False) and cmask[i, j, k] != 0 and mask[i, j, k] == 1: # sum-r-value/index newimg_nii[i, j, k] = img_nii[i, j, k] print("Get RSA results.") print(filename) print("Save RSA results.") # save the .nii file for RSA results file = nib.Nifti1Image(newimg_nii, affine) if smooth == True: print("Smooth the results.") # smooth the img data of the .nii file file = smooth_img(file, fwhm='fast') # save the result nib.save(file, filename) # determine if it has results norlt = np.isnan(newimg_nii).all() if norlt == True: print("No RSA results.") print("File("+filename+") saves successfully!") # determine plot the results or not if norlt == False and plotrlt == True: print("Plot RSA results.") plot_brainrsa_rlts(filename, background=img_background, type='t') return newimg_nii