def eegRDM(EEG_data, sub_opt=1, chl_opt=0, time_opt=0, time_win=5, time_step=5, method="correlation", abs=False): """ Calculate the Representational Dissimilarity Matrix(Matrices) - RDM(s) based on EEG-like data Parameters ---------- EEG_data : array The EEG/MEG/fNIRS data. The shape of EEGdata must be [n_cons, n_subs, n_trials, n_chls, n_ts]. n_cons, n_subs, n_trials, n_chls & n_ts represent the number of conidtions, the number of subjects, the number of trials, the number of channels & the number of time-points, respectively. sub_opt: int 0 or 1. Default is 1. Return the subject-result or average-result. If sub_opt=0, return the average result. If sub_opt=1, return the results of each subject. chl_opt : int 0 or 1. Default is 0. Calculate the RDM for each channel or not. If chl_opt=0, calculate the RDM based on all channels'data. If chl_opt=1, calculate the RDMs based on each channel's data respectively. time_opt : int 0 or 1. Default is 0. Calculate the RDM for each time-point or not If time_opt=0, calculate the RDM based on whole time-points' data. If time_opt=1, calculate the RDMs based on each time-points respectively. time_win : int. Default is 5. Set a time-window for calculating the RDM for different time-points. Only when time_opt=1, time_win works. If time_win=5, that means each calculation process based on 5 time-points. time_step : int. Default is 5. The time step size for each time of calculating. Only when time_opt=1, time_step works. method : string 'correlation' or 'euclidean'. Default is 'correlation'. The method to calculate the dissimilarities. If method='correlation', the dissimilarity is calculated by Pearson Correlation. If method='euclidean', the dissimilarity is calculated by Euclidean Distance, the results will be normalized. abs : boolean True or False. Default is True. Calculate the absolute value of Pearson r or not. Returns ------- RDM(s) : array The EEG/MEG/fNIR/other EEG-like RDM. If sub_opt=0 & chl_opt=0 & time_opt=0, return only one RDM. The shape is [n_cons, n_cons]. If sub_opt=0 & chl_opt=0 & time_opt=1, return int((n_ts-time_win)/time_step)+1 RDM. The shape is [int((n_ts-time_win)/time_step)+1, n_cons, n_cons]. If sub_opt=0 & chl_opt=1 & time_opt=0, return n_chls RDM. The shape is [n_chls, n_cons, n_cons]. If sub_opt=0 & chl_opt=1 & time_opt=1, return n_chls*(int((n_ts-time_win)/time_step)+1) RDM. The shape is [n_chls, int((n_ts-time_win)/time_step)+1, n_cons, n_cons]. If sub_opt=1 & chl_opt=0 & time_opt=0, return n_subs RDM. The shape is [n_subs, n_cons, n_cons]. If sub_opt=1 & chl_opt=0 & time_opt=1, return n_subs*(int((n_ts-time_win)/time_step)+1) RDM. The shape is [n_subs, int((n_ts-time_win)/time_step)+1, n_cons, n_cons]. If sub_opt=1 & chl_opt=1 & time_opt=0, return n_subs*n_chls RDM. The shape is [n_subs, n_chls, n_cons, n_cons]. If sub_opt=1 & chl_opt=1 & time_opt=1, return n_subs*n_chls*(int((n_ts-time_win)/time_step)+1) RDM. The shape is [n_subs, n_chls, int((n_ts-time_win)/time_step)+1, n_cons, n_cons]. Notes ----- Sometimes, the numbers of trials under different conditions are not same. In NeuroRA, we recommend users to average the trials under a same condition firstly in this situation. Thus, the shape of input (EEG_data) should be [n_cons, n_subs, 1, n_chls, n_ts]. """ if len(np.shape(EEG_data)) != 5: print( "The shape of input for eegRDM() function must be [n_cons, n_subs, n_trials, n_chls, n_ts].\n" ) return "Invalid input!" # get the number of conditions, subjects, trials, channels and time points cons, subs, trials, chls, ts = np.shape(EEG_data) if time_opt == 1: print("\nComputing RDMs") # the time-points for calculating RDM ts = int((ts - time_win) / time_step) + 1 # initialize the data for calculating the RDM data = np.zeros([subs, chls, ts, cons, time_win], dtype=np.float64) # assignment for i in range(subs): for j in range(chls): for k in range(ts): for l in range(cons): for m in range(time_win): # average the trials data[i, j, k, l, m] = np.average(EEG_data[l, i, :, j, k * time_step + m]) if chl_opt == 1: total = subs * chls * ts # initialize the RDMs rdms = np.zeros([subs, chls, ts, cons, cons], dtype=np.float64) # calculate the values in RDMs for i in range(subs): for j in range(chls): for k in range(ts): # show the progressbar percent = (i * chls * ts + j * ts + k + 1) / total * 100 show_progressbar("Calculating", percent) for l in range(cons): for m in range(cons): if method is 'correlation': # calculate the Pearson Coefficient r = pearsonr(data[i, j, k, l], data[i, j, k, m])[0] # calculate the dissimilarity if abs == True: rdms[i, j, k, l, m] = limtozero(1 - np.abs(r)) else: rdms[i, j, k, l, m] = limtozero(1 - r) elif method == 'euclidean': rdms[i, j, k, l, m] = np.linalg.norm(data[i, j, k, l] - data[i, j, k, m]) """elif method == 'mahalanobis': X = np.transpose(np.vstack((data[i, j, k, l], data[i, j, k, m])), (1, 0)) X = np.dot(X, np.linalg.inv(np.cov(X, rowvar=False))) rdms[i, j, k, l, m] = np.linalg.norm(X[:, 0] - X[:, 1])""" if method == 'euclidean': max = np.max(rdms[i, j, k]) min = np.min(rdms[i, j, k]) rdms[i, j, k] = (rdms[i, j, k] - min) / (max - min) # time_opt=1 & chl_opt=1 & sub_opt=1 if sub_opt == 1: print("\nRDMs computing finished!") return rdms # time_opt=1 & chl_opt=1 & sub_opt=0 if sub_opt == 0: rdms = np.average(rdms, axis=0) print("\nRDMs computing finished!") return rdms # if chl_opt = 0 data = np.transpose(data, (0, 2, 3, 4, 1)) data = np.reshape(data, [subs, ts, cons, time_win * chls]) rdms = np.zeros([subs, ts, cons, cons], dtype=np.float64) total = subs * ts # calculate the values in RDMs for i in range(subs): for k in range(ts): # show the progressbar percent = (i * ts + k + 1) / total * 100 show_progressbar("Calculating", percent) for l in range(cons): for m in range(cons): if method == 'correlation': # calculate the Pearson Coefficient r = pearsonr(data[i, k, l], data[i, k, m])[0] # calculate the dissimilarity if abs is True: rdms[i, k, l, m] = limtozero(1 - np.abs(r)) else: rdms[i, k, l, m] = limtozero(1 - r) elif method == 'euclidean': rdms[i, k, l, m] = np.linalg.norm(data[i, k, l] - data[i, k, m]) if method == 'euclidean': max = np.max(rdms[i, k]) min = np.min(rdms[i, k]) rdms[i, k] = (rdms[i, k] - min) / (max - min) # time_opt=1 & chl_opt=0 & sub_opt=1 if sub_opt == 1: print("\nRDMs computing finished!") return rdms # time_opt=1 & chl_opt=0 & sub_opt=0 if sub_opt == 0: rdms = np.average(rdms, axis=0) print("\nRDM computing finished!") return rdms # if time_opt = 0 if chl_opt == 1: print("\nComputing RDMs") # average the trials data = np.average(EEG_data, axis=2) # initialize the RDMs rdms = np.zeros([subs, chls, cons, cons], dtype=np.float64) total = subs * chls # calculate the values in RDMs for i in range(subs): for j in range(chls): # show the progressbar percent = (i * chls + j + 1) / total * 100 show_progressbar("Calculating", percent) for k in range(cons): for l in range(cons): if method == 'correlation': # calculate the Pearson Coefficient r = pearsonr(data[k, i, j], data[l, i, j])[0] # calculate the dissimilarity if abs == True: rdms[i, j, k, l] = limtozero(1 - np.abs(r)) else: rdms[i, j, k, l] = limtozero(1 - r) elif method == 'euclidean': rdms[i, j, k, l] = np.linalg.norm(data[k, i, j] - data[k, i, j]) if method == 'euclidean': max = np.max(rdms[i, j]) min = np.min(rdms[i, j]) rdms[i, j] = (rdms[i, j] - min) / (max - min) # time_opt=0 & chl_opt=1 & sub_opt=1 if sub_opt == 1: print("\nRDM computing finished!") return rdms # time_opt=0 & chl_opt=1 & sub_opt=0 if sub_opt == 0: rdms = np.average(rdms, axis=0) print("\nRDM computing finished!") return rdms # if chl_opt = 0 if sub_opt == 1: print("\nComputing RDMs") else: print("\nComputing RDM") # average the trials data = np.average(EEG_data, axis=2) # flatten the data for different calculating conditions data = np.reshape(data, [cons, subs, chls * ts]) # initialize the RDMs rdms = np.zeros([subs, cons, cons], dtype=np.float64) # calculate the values in RDMs for i in range(subs): for j in range(cons): for k in range(cons): if method == 'correlation': # calculate the Pearson Coefficient r = pearsonr(data[j, i], data[k, i])[0] # calculate the dissimilarity if abs == True: rdms[i, j, k] = limtozero(1 - np.abs(r)) else: rdms[i, j, k] = limtozero(1 - r) elif method == 'euclidean': rdms[i, j, k] = np.linalg.norm(data[j, i] - data[k, i]) """elif method == 'mahalanobis': X = np.transpose(np.vstack((data[j, i], data[k, i])), (1, 0)) X = np.dot(X, np.linalg.inv(np.cov(X, rowvar=False))) rdms[i, j, k] = np.linalg.norm(X[:, 0] - X[:, 1])""" if method == 'euclidean': max = np.max(rdms[i]) min = np.min(rdms[i]) rdms[i] = (rdms[i] - min) / (max - min) if sub_opt == 1: print("\nRDMs computing finished!") return rdms if sub_opt == 0: rdms = np.average(rdms, axis=0) print("\nRDM computing finished!") return rdms
def fmriRDM(fmri_data, ksize=[3, 3, 3], strides=[1, 1, 1], sub_result=0, abs=True): """ Calculate the Representational Dissimilarity Matrices (RDMs) for fMRI data (Searchlight) Parameters ---------- fmri_data : array The fmri data. The shape of fmri_data must be [n_cons, n_subs, nx, ny, nz]. n_cons, nx, ny, nz represent the number of conditions, the number of subs & the size of fMRI-img, respectively. 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. sub_result: int 0 or 1. Default is 0. Return the subject-result or average-result. If sub_result=0, return the average result. If sub_result=1, return the results of each subject. abs : boolean True or False. Default is True. Calculate the absolute value of Pearson r or not. Returns ------- RDM : array The fMRI-Searchlight RDM. If sub_result=0, the shape of RDMs is [n_x, n_y, n_z, n_cons, n_cons]. If sub_result=1, the shape of RDMs is [n_subs, n_x, n_y, n_cons, n_cons] n_subs, n_x, n_y, n_z represent the number of subjects & the number of calculation units for searchlight along the x, y, z axis. """ # get the number of conditions, subjects and the size of the fMRI-img cons, subs, nx, ny, nz = np.shape(fmri_data) # 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 = int((nx - kx) / sx) + 1 n_y = int((ny - ky) / sy) + 1 n_z = int((nz - kz) / sz) + 1 # initialize the data for calculating the RDM data = np.full([n_x, n_y, n_z, cons, kx * ky * kz, subs], np.nan) # assignment for x in range(n_x): for y in range(n_y): for z in range(n_z): for i in range(cons): index = 0 for k1 in range(kx): for k2 in range(ky): for k3 in range(kz): for j in range(subs): data[x, y, z, i, index, j] = fmri_data[i, j, x + k1, y + k2, z + k3] index = index + 1 # shape of data: [n_x, n_y, n_z, cons, kx*ky*kz, subs] # ->[subs, n_x, n_y, n_z, cons, kx*ky*kz] data = np.transpose(data, (5, 0, 1, 2, 3, 4)) # flatten the data for different calculating conditions data = np.reshape(data, [subs, n_x, n_y, n_z, cons, kx * ky * kz]) # initialize the RDMs subrdms = np.full([subs, n_x, n_y, n_z, cons, cons], np.nan) for sub in range(subs): for x in range(n_x): for y in range(n_y): for z in range(n_z): for i in range(cons): for j in range(cons): # no NaN if (np.isnan(data[:, x, y, z, i]).any() == False) and (np.isnan( data[:, x, y, z, j]).any() == False): # calculate the Pearson Coefficient r = pearsonr(data[sub, x, y, z, i], data[sub, x, y, z, j])[0] # calculate the dissimilarity if abs == True: subrdms[sub, x, y, z, i, j] = limtozero(1 - np.abs(r)) else: subrdms[sub, x, y, z, i, j] = limtozero(1 - r) # average the RDMs rdms = np.average(subrdms, axis=0) if sub_result == 0: return rdms if sub_result == 1: return subrdms
def fmriRDM_roi(fmri_data, mask_data, sub_result=0, abs=True): """ Calculate the Representational Dissimilarity Matrix - RDM(s) for fMRI data (for ROI) Parameters ---------- fmri_data : array The fmri data. The shape of fmri_data must be [n_cons, n_subs, nx, ny, nz]. n_cons, nx, ny, nz represent the number of conditions, the number of subs & the size of fMRI-img, respectively. mask_data : array [nx, ny, nz]. The mask data for region of interest (ROI) The size of the fMRI-img. nx, ny, nz represent the number of voxels along the x, y, z axis. sub_result: int 0 or 1. Default is 0. Return the subject-result or average-result. If sub_result=0, return the average result. If sub_result=1, return the results of each subject. abs : boolean True or False. Default is True. Calculate the absolute value of Pearson r or not. Returns ------- RDM : array The fMRI-ROI RDM. If sub_result=0, the shape of RDM is [n_cons, n_cons]. If sub_result=1, the shape of RDM is [n_subs, n_cons, n_cons]. """ # get the number of conditions, subjects, the size of the fMRI-img ncons, nsubs, nx, ny, nz = fmri_data.shape # record the the number of voxels that is not 0 or NaN n = 0 for i in range(nx): for j in range(ny): for k in range(nz): # not 0 or NaN if (mask_data[i, j, k] != 0) and (math.isnan(mask_data[i, j, k]) == False)\ and (np.isnan(fmri_data[:, :, :, j, k]).any() == False): n = n + 1 # initialize the data for calculating the RDM data = np.zeros([ncons, nsubs, n], dtype=np.float) # assignment for p in range(ncons): for q in range(nsubs): n = 0 for i in range(nx): for j in range(ny): for k in range(nz): # not 0 or NaN if (mask_data[i, j, k] != 0) and (math.isnan(mask_data[i, j, k]) == False)\ and (np.isnan(fmri_data[:, :, :, j, k]).any() == False): data[p, q, n] = fmri_data[p, q, i, j, k] n = n + 1 # initialize the RDMs subrdms = np.zeros([nsubs, ncons, ncons], dtype=np.float) # shape of data: [ncons, nsubs, n] -> [nsubs, ncons, n] data = np.transpose(data, (1, 0, 2)) # calculate the values in RDM for sub in range(nsubs): for i in range(ncons): for j in range(ncons): if (np.isnan(data[:, i]).any() == False) and (np.isnan( data[:, j]).any() == False): # calculate the Pearson Coefficient r = pearsonr(data[sub, i], data[sub, j])[0] # calculate the dissimilarity if abs is True: subrdms[sub, i, j] = limtozero(1 - np.abs(r)) else: subrdms[sub, i, j] = limtozero(1 - r) # average the RDMs rdm = np.average(subrdms, axis=0) if sub_result == 0: return rdm if sub_result == 1: return subrdms
def bhvRDM(bhv_data, sub_opt=0, abs=True): """ Calculate the Representational Dissimilarity Matrix(Matrices) - RDM(s) for behavioral data Parameters ---------- bhv_data : array The behavioral data. The shape of bhv_data must be [n_cons, n_subs, n_trials]. n_cons, n_subs & n_trials represent the number of conidtions, the number of subjects & the number of trials, respectively. sub_opt : int 0 or 1. Default is 0. Calculate the RDM for each subject or not. If sub_opt=0, return only one RDM based on all data. If sub_opt=1, return n_subs RDMs based on each subject's data. abs : boolean True or False. Default is True. Calculate the absolute value of Pearson r or not. Returns ------- RDM(s) : array The behavioral RDM. If sub_opt=0, return only one RDM. The shape is [n_cons, n_cons]. If sub_opt=1, return n_subs RDMs. The shape is [n_subs, n_cons, n_cons]. Notes ----- This function can also be used to calculate the RDM for computational simulation data """ # get the number of conditions & the number of subjects cons = len(bhv_data) # get the number of conditions n_subs = [] for i in range(cons): n_subs.append(np.shape(bhv_data[i])[0]) subs = n_subs[0] # shape of bhv_data: [N_cons, N_subs, N_trials] # save the number of trials of each condition n_trials = [] for i in range(cons): n_trials.append(np.shape(bhv_data[i])[1]) # save the number of trials of each condition if len(set(n_trials)) != 1: return None # sub_opt=1 if sub_opt == 1: # initialize the RDMs rdms = np.zeros([subs, cons, cons], dtype=np.float64) # calculate the values in RDMs for sub in range(subs): rdm = np.zeros([cons, cons], dtype=np.float) for i in range(cons): for j in range(cons): # calculate the difference if abs is True: rdm[i, j] = np.abs( np.average(bhv_data[i, sub]) - np.average(bhv_data[j, sub])) else: rdm[i, j] = np.average(bhv_data[i, sub]) - np.average( bhv_data[j, sub]) # flatten the RDM vrdm = np.reshape(rdm, [cons * cons]) # array -> set -> list svrdm = set(vrdm) lvrdm = list(svrdm) lvrdm.sort() # get max & min maxvalue = lvrdm[-1] minvalue = lvrdm[1] # rescale if maxvalue != minvalue: for i in range(cons): for j in range(cons): # not on the diagnal if i != j: rdm[i, j] = float( (rdm[i, j] - minvalue) / (maxvalue - minvalue)) rdms[sub] = rdm return rdms # & sub_opt=0 # initialize the RDM rdm = np.zeros([cons, cons], dtype=np.float64) # judge whether numbers of trials of different conditions are same if len(set(n_subs)) != 1: return None # initialize the data for calculating the RDM data = np.zeros([cons, subs], dtype=np.float64) # assignment for i in range(cons): for j in range(subs): # save the data for each subject under each condition, average the trials data[i][j] = np.average(bhv_data[i][j]) # calculate the values in RDM for i in range(cons): for j in range(cons): # calculate the Pearson Coefficient r = pearsonr(data[i], data[j])[0] # calculate the dissimilarity if abs == True: rdm[i, j] = limtozero(1 - np.abs(r)) else: rdm[i, j] = limtozero(1 - r) return rdm
def ecogRDM(ele_data, opt="all", time_win=5, time_step=5, abs=True): """ Calculate the Representational Dissimilarity Matrix(Matrices) - RDM(s) for ECoG/sEEG/electrophysiology data Parameters ---------- ele_data : array The ECoG/sEEG/electrophysiology data. The shape of EEGdata must be [n_cons, n_trials, n_chls, n_ts]. n_cons, n_trials, n_chls & n_ts represent the number of conidtions, the number of trials, the number of channels & the number of time-points, respectively. opt : string 'channel', 'time' or 'all'. Default is 'all'. Calculate the RDM for each channel or for each time-point or for the whole data. If opt='channel', return n_chls RDMs based on each channel's data. If opt='time', return int(ts/time_win) RDMs based on each time-point's data respectively. If opt='allin', return only one RDM based on all data. time_win : int. Default is 5. Set a time-window for calculating the RDM for different time-points or not. Only when opt='time', time_win works. If time_win=5, that means each calculation process based on 5 time-points. time_step : int. Default is 5. The time step size for each time of calculating. Only when opt='time', time_step works. abs : boolean True or False. Default is True. Calculate the absolute value of Pearson r or not. Returns ------- RDM(s) : array The ECoG/sEEG/electrophysiology RDM. If opt='channel', return n_chls RDM. The shape is [n_chls, n_cons, n_cons]. If opt='time', return int((n_ts-time_win)/time_step)+1 RDM. The shape is [int((n_ts-time_win)/time_step)+1, n_cons, n_cons]. If opt='all', return one RDM. The shape is [n_cons, n_cons]. """ # get the number of conditins, trials, channels and time points cons, trials, chls, ts = np.shape(ele_data) # calculate for each channel if opt == "channel": # initialize the data for calculating the RDM data = np.zeros([chls, cons, ts], dtype=np.float64) # assignment for i in range(chls): for j in range(cons): for k in range(ts): # average the trials data[i, j, k] = np.average(ele_data[j, :, i, k]) # initialize the RDMs rdms = np.zeros([chls, cons, cons], dtype=np.float64) # calculate the values in RDMs for i in range(chls): for j in range(cons): for k in range(cons): # calculate the Pearson Coefficient r = pearsonr(data[i, j], data[i, k])[0] # calculate the dissimilarity if abs == True: rdms[i, j, k] = limtozero(1 - np.abs(r)) else: rdms[i, j, k] = limtozero(1 - r) return rdms # calculate for each time-point elif opt == "time": # the time-points for calculating RDM ts = int((ts - time_win) / time_step) + 1 # initialize the data for calculating the RDM data = np.zeros([ts, cons, chls, ts], dtype=np.float64) # assignment for i in range(ts): for j in range(cons): for k in range(chls): for l in range(ts): # average the trials data[i, j, k, l] = np.average(ele_data[j, :, k, i * time_step + l]) # flatten the data for different calculating conditions data = np.reshape(data, [ts, cons, chls * ts]) # initialize the RDMs rdms = np.zeros([ts, cons, cons], dtype=np.float64) # calculate the values in RDMs for i in range(ts): for j in range(cons): for k in range(cons): # calculate the Pearson Coefficient r = pearsonr(np.sort(data[i, j]), np.sort(data[i, k]))[0] # calculate the dissimilarity if abs == True: rdms[i, j, k] = limtozero(1 - np.abs(r)) else: rdms[i, j, k] = limtozero(1 - r) return rdms
def fmriRDM_roi(fmri_data, mask_data): """ Calculate the Representational Dissimilarity Matrix - RDM(s) for fMRI data (for ROI) Parameters ---------- fmri_data : array [nx, ny, nz]. The fmri data. The shape of fmri_data must be [n_cons, n_chls, nx, ny, nz]. n_cons, n_chls, nx, ny, nz represent the number of conidtions, the number of channels & the size of fMRI-img, respectively. mask_data : array [nx, ny, nz]. The mask data for region of interest (ROI) The size of the fMRI-img. nx, ny, nz represent the number of voxels along the x, y, z axis. Returns ------- RDM : array The fMRI-ROI RDM. The shape of RDM is [n_cons, n_cons]. """ # get the number of conditions, subjects, the size of the fMRI-img ncons, nsubs, nx, ny, nz = fmri_data.shape # record the the number of voxels that is not 0 or NaN n = 0 for i in range(nx): for j in range(ny): for k in range(nz): # not 0 or NaN if (mask_data[i, j, k] != 0) and (math.isnan(mask_data[i, j, k]) == False): n = n + 1 # initialize the data for calculating the RDM data = np.zeros([ncons, nsubs, n], dtype=np.float) # assignment for p in range(ncons): for q in range(nsubs): n = 0 for i in range(nx): for j in range(ny): for k in range(nz): # not 0 or NaN if (mask_data[i, j, k] != 0) and (math.isnan(mask_data[i, j, k]) == False): data[p, q, n] = fmri_data[p, q, i, j, k] n = n + 1 # initialize the RDMs rdm = np.zeros([ncons, ncons], dtype=np.float) # flatten the data for different calculating conditions data = np.reshape(data, [ncons, nsubs*n]) # calculate the values in RDM for i in range(ncons): for j in range(ncons): if (np.isnan(data[i]).any() == False) and (np.isnan(data[j]).any() == False): # calculate the Pearson Coefficient r = pearsonr(data[i], data[j])[0] # calculate the dissimilarity rdm[i, j] = limtozero(1 - abs(r)) return rdm
def eegRDM(EEG_data, sub_opt=0, chl_opt=0, time_opt=0, time_win=5, time_step=5, abs=True): """ Calculate the Representational Dissimilarity Matrix(Matrices) - RDM(s) for EEG/MEG/fNIRS data Parameters ---------- EEG_data : array The EEG/MEG/fNIRS data. The shape of EEGdata must be [n_cons, n_subs, n_trials, n_chls, n_ts]. n_cons, n_subs, n_trials, n_chls & n_ts represent the number of conidtions, the number of subjects, the number of trials, the number of channels & the number of time-points, respectively. sub_opt : int 0 or 1. Default is 0. Calculate the RDM for each subject or not. If sub_opt=0, return only one RDM based on all data. If sub_opt=1, return n_subs RDMs based on each subject's data chl_opt : int 0 or 1. Default is 0. Calculate the RDM for each channel or not. If chl_opt=0, calculate the RDM based on all channels'data. If chl_opt=1, calculate the RDMs based on each channel's data respectively. time_opt : int 0 or 1. Default is 0. Calculate the RDM for each time-point or not If time_opt=0, calculate the RDM based on whole time-points' data. If time_opt=1, calculate the RDMs based on each time-points respectively. time_win : int. Default is 5. Set a time-window for calculating the RDM for different time-points. Only when time_opt=1, time_win works. If time_win=5, that means each calculation process based on 5 time-points. time_step : int. Default is 5. The time step size for each time of calculating. Only when time_opt=1, time_step works. abs : boolean True or False. Default is True. Calculate the absolute value of Pearson r or not. Returns ------- RDM(s) : array The EEG/MEG/fNIR RDM. If sub_opt=0 & chl_opt=0 & time_opt=0, return only one RDM. The shape is [n_cons, n_cons]. If sub_opt=0 & chl_opt=0 & time_opt=1, return int((n_ts-time_win)/time_step)+1 RDM. The shape is [int((n_ts-time_win)/time_step)+1, n_cons, n_cons]. If sub_opt=0 & chl_opt=1 & time_opt=0, return n_chls RDM. The shape is [n_chls, n_cons, n_cons]. If sub_opt=0 & chl_opt=1 & time_opt=1, return n_chls*(int((n_ts-time_win)/time_step)+1) RDM. The shape is [n_chls, int((n_ts-time_win)/time_step)+1, n_cons, n_cons]. If sub_opt=1 & chl_opt=0 & time_opt=0, return n_subs RDM. The shape is [n_subs, n_cons, n_cons]. If sub_opt=1 & chl_opt=0 & time_opt=1, return n_subs*(int((n_ts-time_win)/time_step)+1) RDM. The shape is [n_subs, int((n_ts-time_win)/time_step)+1, n_cons, n_cons]. If sub_opt=1 & chl_opt=1 & time_opt=0, return n_subs*n_chls RDM. The shape is [n_subs, n_chls, n_cons, n_cons]. If sub_opt=1 & chl_opt=1 & time_opt=1, return n_subs*n_chls*(int((n_ts-time_win)/time_step)+1) RDM. The shape is [n_subs, n_chls, int((n_ts-time_win)/time_step)+1, n_cons, n_cons]. """ # get the number of conditions, subjects, trials, channels and time points cons, subs, trials, chls, ts = np.shape(EEG_data) if sub_opt == 1: if time_opt == 1: # the time-points for calculating RDM ts = int((ts - time_win) / time_step) + 1 if chl_opt == 1: # sub_opt=1 & time_opt=1 & chl_opt=1 # initialize the data for calculating the RDM data = np.zeros([subs, chls, ts, cons, time_win], dtype=np.float64) # assignment for i in range(subs): for j in range(chls): for k in range(ts): for l in range(cons): for m in range(time_win): # average the trials data[i, j, k, l, m] = np.average( EEG_data[l, i, :, j, k * time_step + m]) # initialize the RDMs rdms = np.zeros([subs, chls, ts, cons, cons], dtype=np.float64) # calculate the values in RDMs for i in range(subs): for j in range(chls): for k in range(ts): for l in range(cons): for m in range(cons): # calculate the Pearson Coefficient r = pearsonr(data[i, j, k, l], data[i, j, k, m])[0] # calculate the dissimilarity if abs == True: rdms[i, j, k, l, m] = limtozero(1 - np.abs(r)) else: rdms[i, j, k, l, m] = limtozero(1 - r) return rdms # sub_opt=1 & time_opt=1 & chl_opt=0 # initialize the data for calculating the RDM data = np.zeros([subs, ts, cons, chls, time_win], dtype=np.float64) # assignment for i in range(subs): for j in range(ts): for k in range(cons): for l in range(chls): for m in range(time_win): # average the trials data[i, j, k, l, m] = np.average( EEG_data[k, i, :, l, j * time_step + m]) # flatten the data for different calculating conditions data = np.reshape(data, [subs, ts, cons, chls * time_win]) # initialize the RDMs rdms = np.zeros([subs, ts, cons, cons], dtype=np.float64) # calculate the values in RDMs for i in range(subs): for j in range(ts): for k in range(cons): for l in range(cons): # calculate the Pearson Coefficient r = pearsonr(data[i, j, k], data[i, j, l])[0] # calculate the dissimilarity if abs == True: rdms[i, j, k, l] = limtozero(1 - np.abs(r)) else: rdms[i, j, k, l] = limtozero(1 - r) return rdms # if time_opt = 0 cons, subs, trials, chls, ts = np.shape(EEG_data) if chl_opt == 1: # sub_opt=1 & time_opt=0 & chl_opt=1 # initialize the data for calculating the RDM data = np.zeros([subs, chls, cons, ts], dtype=np.float64) # assignment for i in range(subs): for j in range(chls): for k in range(cons): for l in range(ts): # average the trials data[i, j, k, l] = np.average(EEG_data[k, i, :, j, l]) # initialize the RDMs rdms = np.zeros([subs, chls, cons, cons], dtype=np.float64) # calculate the values in RDMs for i in range(subs): for j in range(chls): for k in range(cons): for l in range(cons): # calculate the Pearson Coefficient r = pearsonr(data[i, j, k], data[i, j, l])[0] # calculate the dissimilarity if abs == True: rdms[i, j, k, l] = limtozero(1 - np.abs(r)) else: rdms[i, j, k, l] = limtozero(1 - r) return rdms # if chl_opt = 0 # sub_opt=1 & time_opt=0 & chl_opt=0 # initialize the data for calculating the RDM data = np.zeros([subs, cons, chls, ts], dtype=np.float64) # assignment for i in range(subs): for j in range(cons): for k in range(chls): for l in range(ts): # average the trials data[i, j, k, l] = np.average(EEG_data[j, i, :, k, l]) # flatten the data for different calculating conditions data = np.reshape(data, [subs, cons, chls * ts]) # initialize the RDMs rdms = np.zeros([subs, cons, cons], dtype=np.float64) # calculate the values in RDMs for i in range(subs): for j in range(cons): for k in range(cons): # calculate the Pearson Coefficient r = pearsonr(data[i, j], data[i, k])[0] # calculate the dissimilarity if abs == True: rdms[i, j, k] = limtozero(1 - np.abs(r)) else: rdms[i, j, k] = limtozero(1 - r) return rdms # if sub_opt = 0 if time_opt == 1: # the time-points for calculating RDM ts = int((ts - time_win) / time_step) + 1 if chl_opt == 1: # sub_opt=0 & time_opt=1 & chl_opt=1 # initialize the data for calculating the RDM data = np.zeros([chls, ts, cons, time_win], dtype=np.float64) # assignment for i in range(chls): for j in range(ts): for k in range(cons): for l in range(time_win): # average the trials & subs data[i, j, k, l] = np.average(EEG_data[k, :, :, i, j * time_step + l]) # initialize the RDMs rdms = np.zeros([chls, ts, cons, cons], dtype=np.float64) # calculate the values in RDMs for i in range(chls): for j in range(ts): for k in range(cons): for l in range(cons): # calculate the Pearson Coefficient r = pearsonr(data[i, j, k], data[i, j, l])[0] # calculate the dissimilarity if abs == True: rdms[i, j, k, l] = limtozero(1 - np.abs(r)) else: rdms[i, j, k, l] = limtozero(1 - r) return rdms # sub_opt=0 & time_opt=1 & chl_opt=0 # initialize the data for calculating the RDM data = np.zeros([ts, cons, chls, time_win], dtype=np.float64) # assignment for i in range(ts): for j in range(cons): for k in range(chls): for l in range(time_win): # average the subjects & trials data[i, j, k, l] = np.average(EEG_data[j, :, :, k, i * time_step + l]) # flatten the data for different calculating conditions data = np.reshape(data, [ts, cons, chls * time_win]) # initialize the RDMs rdms = np.zeros([ts, cons, cons], dtype=np.float64) # calculate the values in RDMs for i in range(ts): for j in range(cons): for k in range(cons): # calculate the Pearson Coefficient r = pearsonr(data[i, j], data[i, k])[0] # calculate the dissimilarity if abs == True: rdms[i, j, k] = limtozero(1 - np.abs(r)) else: rdms[i, j, k] = limtozero(1 - r) return rdms # if time_opt = 0 # sub_opt=0 & time_opt=0 & chl_opt=1 # get the number of conditions, subjects, trials, channels & time-points cons, subs, trials, chls, ts = np.shape(EEG_data) if chl_opt == 1: # initialize the data for calculating the RDM data = np.zeros([chls, cons, ts], dtype=np.float64) # assignment for i in range(chls): for j in range(cons): for k in range(ts): # average the subjects & trials data[i, j, k] = np.average(EEG_data[j, :, :, i, k]) # flatten the data for different calculating conditions data = np.reshape(data, [chls, cons, ts]) # initialize the RDMs rdms = np.zeros([chls, cons, cons], dtype=np.float64) # calculate the values in RDMs for i in range(chls): for j in range(cons): for k in range(cons): # calculate the Pearson Coefficient r = pearsonr(data[i, j], data[i, k])[0] # calculate the dissimilarity if abs == True: rdms[i, j, k] = limtozero(1 - np.abs(r)) else: rdms[i, j, k] = limtozero(1 - r) return rdms # if chl_opt = 0 # sub_opt=0 & time_opt=0 & chl_opt=0 # get the number of conditions, subjects, trials, channels & time-points cons, subs, trials, chls, ts = np.shape(EEG_data) # initialize the data for calculating the RDM data = np.zeros([cons, chls, ts], dtype=np.float64) # assignment for i in range(cons): for j in range(chls): for k in range(ts): # average the subjects & trials data[i, j, k] = np.average(EEG_data[i, :, :, j, k]) # flatten the data for different calculating condition data = np.reshape(data, [cons, chls * ts]) # initialize the RDM rdm = np.zeros([cons, cons], dtype=np.float64) # calculate the values in RDM for i in range(cons): for j in range(cons): # calculate the Pearson Coefficient r = pearsonr(data[i], data[j])[0] # calculate the dissimilarity if abs == True: rdm[i, j] = limtozero(1 - np.abs(r)) else: rdm[i, j] = limtozero(1 - r) return rdm
def eegRDM(EEG_data, sub_opt=0, chl_opt=0, time_opt=0): # shape of EEG_data: [n_cons, n_subs,_n_trials, n_chls, n_ts] # n_cons, n_subs, n_trials, n_chls, n_frqs, n_ts represent the number of # the conditions, subjects, trials, channels, frequencies and time-points # sub_opt : 0 : return only one rdm # 1 : each subject obtains a rdm # chl_opt : 0 : consider all the channels # 1 : each channel obtains a rdm # time_opt : 0 : consider the time sequence # 1 : each time-point obtains a rdm cons, subs, trials, chls, ts = np.shape(EEG_data) # get the number of conditions, subjects, trials, # channels and time points n_subs = [] n_trials = [] n_chls = [] n_ts = [] for i in range(cons): n_subs.append(np.shape(EEG_data[i])[0]) n_trials.append(np.shape(EEG_data[i])[1]) n_chls.append(np.shape(EEG_data[i])[2]) n_ts.append(np.shape(EEG_data[i])[3]) if len(set(n_chls)) != 1: return None if len(set(n_ts)) != 1: return None if sub_opt == 1: if time_opt == 1: if chl_opt == 1: return None data = np.zeros([subs, ts, cons, chls], dtype=np.float64) for i in range(subs): for j in range(ts): for k in range(cons): for l in range(chls): data[i, j, k, l] = np.average(EEG_data[k, i, :, l, j]) rdms = np.zeros([subs, ts, cons, cons], dtype=np.float64) for i in range(subs): for j in range(ts): for k in range(cons): for l in range(cons): r = np.corrcoef(data[i, j, k], data[i, j, l])[0][1] rdms[i, j, k, l] = limtozero(1 - abs(r)) return rdms # if time_opt = 0 if chl_opt == 1: data = np.zeros([subs, chls, cons, ts], dtype=np.float64) for i in range(subs): for j in range(chls): for k in range(cons): for l in range(ts): data[i, j, k, l] = np.average(EEG_data[k, i, :, j, l]) rdms = np.zeros([subs, chls, cons, cons], dtype=np.float64) for i in range(subs): for j in range(chls): for k in range(cons): for l in range(cons): r = np.corrcoef(data[i, j, k], data[i, j, l])[0][1] rdms[i, j, k, l] = limtozero(1 - abs(r)) return rdms # if chl_opt = 0 data = np.zeros([subs, cons, chls, ts], dtype=np.float64) for i in range(subs): for j in range(cons): for k in range(chls): for l in range(ts): data[i, j, k, l] = np.average(EEG_data[j, i, :, k, j]) data = np.reshape(data, [subs, cons, chls*ts]) rdms = np.zeros([subs, cons, cons], dtype=np.float64) for i in range(subs): for j in range(cons): for k in range(cons): r = np.corrcoef(data[i, j], data[i, k])[0][1] rdms[i, j, k] = limtozero(1 - abs(r)) return rdms # if sub_opt = 0 if len(set(n_subs)) != 1: return None if time_opt == 1: if chl_opt == 1: return None data = np.zeros([ts, cons, subs, chls], dtype=np.float64) for i in range(ts): for j in range(cons): for k in range(subs): for l in range(chls): data[i, j, k, l] = np.average(EEG_data[j, k, :, l, i]) data = np.reshape(data, [ts, cons, subs * chls]) rdms = np.zeros([ts, cons, cons], dtype=np.float64) for i in range(ts): for j in range(cons): for k in range(cons): r = np.corrcoef(data[i, j], data[i, k])[0][1] rdms[i, j, k] = limtozero(1 - abs(r)) return rdms # if time_opt = 0 if chl_opt == 1: data = np.zeros([chls, cons, subs, ts], dtype=np.float64) for i in range(chls): for j in range(cons): for k in range(subs): for l in range(ts): data[i, j, k, l] = np.average(EEG_data[j, k, :, i, l]) data = np.reshape(data, [chls, cons, subs*ts]) rdms = np.zeros([chls, cons, cons], dtype=np.float64) for i in range(chls): for j in range(cons): for k in range(cons): r = np.corrcoef(data[i, j], data[i, k])[0][1] rdms[i, j, k] = limtozero(1 - abs(r)) return rdms # if chl_opt = 0 data = np.zeros([cons, subs, chls, ts], dtype=np.float64) for i in range(cons): for j in range(subs): for k in range(chls): for l in range(ts): data[i, j, k, l] = np.average(EEG_data[i, j, :, k, j]) data = np.reshape(data, [cons, subs * chls * ts]) rdm = np.zeros([cons, cons], dtype=np.float64) for i in range(cons): for j in range(cons): r = np.corrcoef(data[i], data[j])[0][1] rdm[i, j] = limtozero(1 - abs(r)) return rdm
def bhvRDM(bhv_data, sub_opt=0, method="correlation", abs=False): """ Calculate the Representational Dissimilarity Matrix(Matrices) - RDM(s) for behavioral data Parameters ---------- bhv_data : array The behavioral data. The shape of bhv_data must be [n_cons, n_subs, n_trials]. n_cons, n_subs & n_trials represent the number of conidtions, the number of subjects & the number of trials, respectively. sub_opt: int 0 or 1. Default is 1. Return the subject-result or average-result. If sub_opt=0, return the average result. If sub_opt=1, return the results of each subject. method : string 'correlation' or 'euclidean' or 'mahalanobis'. Default is 'correlation'. The method to calculate the dissimilarities. If method='correlation', the dissimilarity is calculated by Pearson Correlation. If method='euclidean', the dissimilarity is calculated by Euclidean Distance, the results will be normalized. If method='mahalanobis', the dissimilarity is calculated by Mahalanobis Distance, the results will be normalized. abs : boolean True or False. Default is True. Calculate the absolute value of Pearson r or not. Only works when method='correlation'. Returns ------- RDM(s) : array The behavioral RDM. If sub_opt=0, return only one RDM. The shape is [n_cons, n_cons]. If sub_opt=1, return n_subs RDMs. The shape is [n_subs, n_cons, n_cons]. Notes ----- This function can also be used to calculate the RDM for computational simulation data """ if len(np.shape(bhv_data)) != 3: return "Invalid input!" # get the number of conditions & the number of subjects cons = len(bhv_data) # get the number of conditions n_subs = [] for i in range(cons): n_subs.append(np.shape(bhv_data[i])[0]) subs = n_subs[0] # shape of bhv_data: [N_cons, N_subs, N_trials] # save the number of trials of each condition n_trials = [] for i in range(cons): n_trials.append(np.shape(bhv_data[i])[1]) # save the number of trials of each condition if len(set(n_trials)) != 1: return None # sub_opt=1 if sub_opt == 1: # initialize the RDMs rdms = np.zeros([subs, cons, cons], dtype=np.float64) # calculate the values in RDMs for sub in range(subs): rdm = np.zeros([cons, cons], dtype=np.float) for i in range(cons): for j in range(cons): # calculate the difference if abs is True: rdm[i, j] = np.abs( np.average(bhv_data[i, sub]) - np.average(bhv_data[j, sub])) else: rdm[i, j] = np.average(bhv_data[i, sub]) - np.average( bhv_data[j, sub]) # flatten the RDM vrdm = np.reshape(rdm, [cons * cons]) # array -> set -> list svrdm = set(vrdm) lvrdm = list(svrdm) lvrdm.sort() # get max & min maxvalue = lvrdm[-1] minvalue = lvrdm[1] # rescale if maxvalue != minvalue: for i in range(cons): for j in range(cons): # not on the diagnal if i != j: rdm[i, j] = (rdm[i, j] - minvalue) / (maxvalue - minvalue) rdms[sub] = rdm return rdms # & sub_opt=0 # initialize the RDM rdm = np.zeros([cons, cons], dtype=np.float64) # judge whether numbers of trials of different conditions are same if len(set(n_subs)) != 1: return None # initialize the data for calculating the RDM data = np.zeros([cons, subs], dtype=np.float64) # assignment for i in range(cons): for j in range(subs): # save the data for each subject under each condition, average the trials data[i][j] = np.average(bhv_data[i][j]) # calculate the values in RDM for i in range(cons): for j in range(cons): if method is 'correlation': # calculate the Pearson Coefficient r = pearsonr(data[i], data[j])[0] # calculate the dissimilarity if abs == True: rdm[i, j] = limtozero(1 - np.abs(r)) else: rdm[i, j] = limtozero(1 - r) elif method is 'euclidean': rdm[i, j] = np.linalg.norm(data[i] - data[j]) elif method is 'mahalanobis': X = np.transpose(np.vstack((data[i], data[j])), (1, 0)) X = np.dot(X, np.linalg.inv(np.cov(X, rowvar=False))) rdm[i, j] = np.linalg.norm(X[:, 0] - X[:, 1]) if method is 'euclidean' or method is 'mahalanobis': max = np.max(rdm) min = np.min(rdm) rdm = (rdm - min) / (max - min) return rdm
def ecogRDM(ele_data, nchls, opt="all"): # all these calculations belong to only one subject # chls_num represent the number of channels of the data # the shape of ele_data : [N_cons, N_trials, N_chls, N_ts] # N_cons, N_trials, N_chls, N_ts represent the number of conditions, # the number of trials, the number of channels, the number of time-points cons, trials, chls, ts = np.shape(ele_data) # get the number of conditins, trials, channels and time points n_trials = [] n_chls = [] n_ts = [] for i in range(cons): n_trials.append(np.shape(ele_data[i])[0]) n_chls.append(np.shape(ele_data[i])[1]) n_ts.append(np.shape(ele_data[i])[2]) if len(set(n_chls)) != 1: return None if len(set(n_ts)) != 1: return None if n_chls[0] != nchls: return None if opt == "channel": data = np.zeros([chls, cons, ts], dtype=np.float64) for i in range(chls): for j in range(cons): for k in range(ts): data[i, j, k] = np.average(ele_data[j, :, i, k]) rdms = np.zeros([chls, cons, cons], dtype=np.float64) for i in range(chls): for j in range(cons): for k in range(cons): r = np.corrcoef(data[i, j], data[i, k])[0][1] rdms[i, j, k] = limtozero(1 - abs(r)) return rdms elif opt == "time": data = np.zeros([ts, cons, chls], dtype=np.float64) for i in range(ts): for j in range(cons): for k in range(chls): data[i, j, k] = np.average(ele_data[j, :, k, i]) rdms = np.zeros([ts, cons, cons], dtype=np.float64) for i in range(ts): for j in range(cons): for k in range(cons): r = np.corrcoef(data[i, j], data[i, k])[0][1] rdms[i, j, k] = limtozero(1 - abs(r)) return rdms # if opt = "allin" data = np.zeros([cons, chls, ts], dtype=np.float64) for i in range(cons): for j in range(chls): for k in range(ts): data[i, j, k] = np.average(ele_data[i, :, j, k]) data = np.reshape(data, [cons, chls*ts]) rdm = np.zeros([cons, cons], dtype=np.float64) for i in range(cons): for j in range(cons): r = np.corrcoef(data[i], data[j])[0][1] rdm[i, j] = limtozero(1 - abs(r)) return rdm
def fmriRDM(fmri_data, ksize=[3, 3, 3], strides=[1, 1, 1]): # ksize=[kx, ky, kz] represents that the calculation unit contains k1*k2*k3 voxels # strides=[sx, sy, sz] represents the moving steps along the x, y, z # the shape of fmri_rdm : [N_cons, N_subs, nx, ny, nz] # N_cons, N_subs, nx, ny, nz represent the number of conditions, # the number of subjects, the size of the fmri data cons, subs, nx, ny, nz = np.shape(fmri_data) # get the number of conditions, subjects and the size of the data kx = ksize[0] ky = ksize[1] kz = ksize[2] sx = strides[0] sy = strides[1] sz = strides[2] n_subs = [] n_trials = [] for i in range(cons): n_subs.append(fmri_data[i][0]) n_trials.append(fmri_data[i][1]) # calculate the number of the calculation units n_x = int((nx - kx) / sx)+1 n_y = int((ny - ky) / sy)+1 n_z = int((nz - kz) / sz)+1 data = np.zeros([n_x, n_y, n_z, cons, kx*ky*kz, subs], dtype=np.float64) for x in range(n_x): for y in range(n_y): for z in range(n_z): for i in range(cons): for k1 in range(kx): for k2 in range(ky): for k3 in range(kz): for j in range(subs): data[x, y, z, i, k1*kx+k2*ky+k3*ky, j] = fmri_data[i, j, x+k1, y+k2, z+k3] data = np.reshape(data, [n_x, n_y, n_z, cons, kx*ky*kz*subs]) rdms = np.zeros([n_x, n_y, n_z, cons, cons], dtype=np.float64) for x in range(n_x): for y in range(n_y): for z in range(n_z): for i in range(cons): for j in range(cons): r = np.corrcoef(data[x, y, z, i], data[x, y, z, j])[0][1] rdms[x, y, z, i, j] = limtozero(1 - abs(r)) print(rdms[x, y, z, i, j]) return rdms
def bhvRDM(bhv_data, sub_opt=0, data_opt=1): # sub_opt : 0 : return only one rdm # 1 : each subject obtains a rdm # data_opt : 1 : for raw data, each subject's each trial has a value of data # 0 : each subject has had a value of data, ignore the effect of trials cons = len(bhv_data) # get the number of conditions n_subs = [] # save the number of subjects of each condition for i in range(cons): n_subs.append(np.shape(bhv_data[i])[0]) subs = n_subs[0] if data_opt == 0: # shape of bhv_data: [N_cons, N_subs] # N_cons & N_subs represent the number of conditions & the number of subjects if sub_opt == 1: return None if len(set(n_subs)) != 1: return None rdm = np.zeros([cons, cons], dtype=np.float64) for i in range(cons): for j in range(cons): r = np.corrcoef(bhv_data[i], bhv_data[j])[0][1] # calculate the Pearson Coefficient rdm[i, j] = limtozero(1 - abs(r)) # calculate the dissimilarity return rdm # if data_opt=1 # shape of bhv_data: [N_cons, N_subs, N_trials] # N_cons, N_subs, N_trials represent the number of conditions, the number of subjects, # the number of trials, respectively n_trials = [] # save the number of trials of each condition for i in range(cons): n_trials.append(np.shape(bhv_data[i])[1]) if len(set(n_trials)) != 1: # judge whether numbers of trials of different conditions are same return None if sub_opt == 1: rdms = np.zeros([subs, cons, cons], dtype=np.float64) for sub in subs: for i in range(cons): for j in range(cons): r = np.corrcoef(bhv_data[i][sub], bhv_data[j][sub])[0][1] # calculate the Pearson Coefficient rdms[sub, i, j] = limtozero(1 - abs(r)) # calculate the dissimilarity return rdms # if sub_opt=0 rdm = np.zeros([cons, cons], dtype=np.float64) # initialize a con*con matrix as the rdm if len(set(n_subs)) != 1: # judge whether numbers of trials of different conditions are same return None data = np.zeros([cons, subs], dtype=np.float64) for i in range(cons): for j in range(subs): data[i][j] = np.average(bhv_data[i][j]) # save the data for each subject under each condition, average the trials for i in range(cons): for j in range(cons): r = np.corrcoef(data[i], data[j])[0][1] # calculate the Pearson Coefficient rdm[i, j] = limtozero(1 - abs(r)) # calculate the dissimilarity return rdm
def bhvRDM(bhv_data, sub_opt=0): """ Calculate the Representational Dissimilarity Matrix(Matrices) - RDM(s) for behavioral data Parameters ---------- bhv_data : array The behavioral data. The shape of bhv_data must be [n_cons, n_subs, n_trials]. n_cons, n_subs & n_trials represent the number of conidtions, the number of subjects & the number of trials, respectively. sub_opt : int 0 or 1. Default is 0. Calculate the RDM for each subject or not. If sub_opt=0, return only one RDM based on all data. If sub_opt=1, return n_subs RDMs based on each subject's data. Returns ------- RDM(s) : array The behavioral RDM. If sub_opt=0, return only one RDM. The shape is [n_cons, n_cons]. If sub_opt=1, return n_subs RDMs. The shape is [n_subs, n_cons, n_cons]. Notes ----- This function can also be used to calculate the RDM for computational simulation data """ # get the number of conditions & the number of subjects cons = len(bhv_data) # get the number of conditions n_subs = [] for i in range(cons): n_subs.append(np.shape(bhv_data[i])[0]) subs = n_subs[0] # shape of bhv_data: [N_cons, N_subs, N_trials] # save the number of trials of each condition n_trials = [] for i in range(cons): n_trials.append(np.shape(bhv_data[i])[1]) # save the number of trials of each condition if len(set(n_trials)) != 1: return None # sub_opt=1 if sub_opt == 1: # initialize the RDMs rdms = np.zeros([subs, cons, cons], dtype=np.float64) # calculate the values in RDMs for sub in subs: for i in range(cons): for j in range(cons): # calculate the Pearson Coefficient r = pearsonr(bhv_data[i][sub], bhv_data[j][sub])[0] # calculate the dissimilarity rdms[sub, i, j] = limtozero(1 - abs(r)) return rdms # & sub_opt=0 # initialize the RDM rdm = np.zeros([cons, cons], dtype=np.float64) # judge whether numbers of trials of different conditions are same if len(set(n_subs)) != 1: return None # initialize the data for calculating the RDM data = np.zeros([cons, subs], dtype=np.float64) # assignment for i in range(cons): for j in range(subs): # save the data for each subject under each condition, average the trials data[i][j] = np.average(bhv_data[i][j]) # calculate the values in RDM for i in range(cons): for j in range(cons): # calculate the Pearson Coefficient r = pearsonr(data[i], data[j])[0] # calculate the dissimilarity rdm[i, j] = limtozero(1 - abs(r)) return rdm
def ecogRDM(ele_data, time_win=5, opt="all"): # all these calculations belong to only one subject # nchls represent the number of channels of the data # the shape of ele_data : [N_cons, N_trials, N_chls, N_ts] # time_win : the time-window, if time_win=5, that means each calculation process bases on 5 time points # this is also a processing of downsampling # N_cons, N_trials, N_chls, N_ts represent the number of conditions, # the number of trials, the number of channels, the number of time-points cons, trials, chls, ts = np.shape(ele_data) # get the number of conditins, trials, channels and time points n_trials = [] n_chls = [] n_ts = [] for i in range(cons): n_trials.append(np.shape(ele_data[i])[0]) n_chls.append(np.shape(ele_data[i])[1]) n_ts.append(np.shape(ele_data[i])[2]) if len(set(n_chls)) != 1: return None if len(set(n_ts)) != 1: return None if opt == "channel": data = np.zeros([chls, cons, ts], dtype=np.float64) for i in range(chls): for j in range(cons): for k in range(ts): data[i, j, k] = np.average(ele_data[j, :, i, k]) rdms = np.zeros([chls, cons, cons], dtype=np.float64) for i in range(chls): for j in range(cons): for k in range(cons): r = np.corrcoef(data[i, j], data[i, k])[0][1] rdms[i, j, k] = limtozero(1 - abs(r)) return rdms elif opt == "time": ts = int(ts/time_win) data = np.zeros([ts, cons, chls], dtype=np.float64) for i in range(ts): for j in range(cons): for k in range(chls): data[i, j, k] = np.average(ele_data[j, :, k, i*time_win:i*time_win+time_win]) rdms = np.zeros([ts, cons, cons], dtype=np.float64) for i in range(ts): for j in range(cons): for k in range(cons): r = np.corrcoef(data[i, j], data[i, k])[0][1] rdms[i, j, k] = limtozero(1 - abs(r)) return rdms
def bhvRDM(bhv_data, sub_opt=1, method="correlation", abs=False): """ Calculate the Representational Dissimilarity Matrix(Matrices) - RDM(s) for behavioral data Parameters ---------- bhv_data : array The behavioral data. The shape of bhv_data must be [n_cons, n_subs, n_trials]. n_cons, n_subs & n_trials represent the number of conidtions, the number of subjects & the number of trials, respectively. sub_opt: int 0 or 1. Default is 1. Return the results for each subject or after averaging. If sub_opt=1, calculate the results of each subject (using the absolute distance). If sub_opt=0, calculate the results averaging the trials and taking the subjects as the features. method : string 'correlation' or 'euclidean'. Default is 'correlation'. The method to calculate the dissimilarities. If method='correlation', the dissimilarity is calculated by Pearson Correlation. If method='euclidean', the dissimilarity is calculated by Euclidean Distance, the results will be normalized. abs : boolean True or False. Default is True. Calculate the absolute value of Pearson r or not. Only works when method='correlation'. Returns ------- RDM(s) : array The behavioral RDM. If sub_opt=1, return n_subs RDMs. The shape is [n_subs, n_cons, n_cons]. If sub_opt=0, return only one RDM. The shape is [n_cons, n_cons]. Notes ----- This function can also be used to calculate the RDM for computational simulation data. For example, users can extract the activations for a certain layer i which includes Nn nodes in a deep convolutional neural network (DCNN) corresponding to Ni images. Thus, the input could be a [Ni, 1, Nn] matrix M. Using "bhvRDM(M, sub_opt=0)", users can obtain the DCNN RDM for layer i. """ if len(np.shape(bhv_data)) != 3: print( "\nThe shape of input for bhvEEG() function must be [n_cons, n_subs, n_trials].\n" ) return "Invalid input!" # get the number of conditions & the number of subjects cons = len(bhv_data) # get the number of conditions n_subs = [] for i in range(cons): n_subs.append(np.shape(bhv_data[i])[0]) subs = n_subs[0] # shape of bhv_data: [N_cons, N_subs, N_trials] # save the number of trials of each condition n_trials = [] for i in range(cons): n_trials.append(np.shape(bhv_data[i])[1]) # save the number of trials of each condition if len(set(n_trials)) != 1: return None # sub_opt=1 if sub_opt == 1: print("\nComputing RDMs") # initialize the RDMs rdms = np.zeros([subs, cons, cons], dtype=np.float64) # calculate the values in RDMs for sub in range(subs): rdm = np.zeros([cons, cons], dtype=np.float) for i in range(cons): for j in range(cons): # calculate the difference if abs == True: rdm[i, j] = np.abs( np.average(bhv_data[i, sub]) - np.average(bhv_data[j, sub])) else: rdm[i, j] = np.average(bhv_data[i, sub]) - np.average( bhv_data[j, sub]) # flatten the RDM vrdm = np.reshape(rdm, [cons * cons]) # array -> set -> list svrdm = set(vrdm) lvrdm = list(svrdm) lvrdm.sort() # get max & min maxvalue = lvrdm[-1] minvalue = lvrdm[1] # rescale if maxvalue != minvalue: for i in range(cons): for j in range(cons): # not on the diagnal if i != j: rdm[i, j] = (rdm[i, j] - minvalue) / (maxvalue - minvalue) rdms[sub] = rdm print("\nRDMs computing finished!") return rdms # & sub_opt=0 print("\nComputing RDM") # initialize the RDM rdm = np.zeros([cons, cons], dtype=np.float64) # judge whether numbers of trials of different conditions are same if len(set(n_subs)) != 1: return None # assignment # save the data for each subject under each condition, average the trials data = np.average(bhv_data, axis=2) # calculate the values in RDM for i in range(cons): for j in range(cons): if method == 'correlation': # calculate the Pearson Coefficient r = pearsonr(data[i], data[j])[0] # calculate the dissimilarity if abs == True: rdm[i, j] = limtozero(1 - np.abs(r)) else: rdm[i, j] = limtozero(1 - r) elif method == 'euclidean': rdm[i, j] = np.linalg.norm(data[i] - data[j]) if method == 'euclidean': max = np.max(rdm) min = np.min(rdm) rdm = (rdm - min) / (max - min) print("\nRDM computing finished!") return rdm
def fmriRDM_roi(fmri_data, mask_data, sub_opt=1, method="correlation", abs=False): """ Calculate the Representational Dissimilarity Matrix - RDM(s) based on fMRI data (for ROI) Parameters ---------- fmri_data : array The fmri data. The shape of fmri_data must be [n_cons, n_subs, nx, ny, nz]. n_cons, nx, ny, nz represent the number of conditions, the number of subs & the size of fMRI-img, respectively. mask_data : array [nx, ny, nz]. The mask data for region of interest (ROI) The size of the fMRI-img. nx, ny, nz represent the number of voxels along the x, y, z axis. sub_opt: int 0 or 1. Default is 1. Return the subject-result or average-result. If sub_opt=0, return the average result. If sub_opt=1, return the results of each subject. method : string 'correlation' or 'euclidean' or 'mahalanobis'. Default is 'correlation'. The method to calculate the dissimilarities. If method='correlation', the dissimilarity is calculated by Pearson Correlation. If method='euclidean', the dissimilarity is calculated by Euclidean Distance, the results will be normalized. If method='mahalanobis', the dissimilarity is calculated by Mahalanobis Distance, the results will be normalized. abs : boolean True or False. Default is True. Calculate the absolute value of Pearson r or not. Returns ------- RDM : array The fMRI-ROI RDM. If sub_opt=0, the shape of RDM is [n_cons, n_cons]. If sub_opt=1, the shape of RDM is [n_subs, n_cons, n_cons]. """ if len(np.shape(fmri_data)) != 5 or len(np.shape(mask_data)) != 3: return "Invalid input!" # get the number of conditions, subjects, the size of the fMRI-img ncons, nsubs, nx, ny, nz = fmri_data.shape # record the the number of voxels that is not 0 or NaN n = 0 for i in range(nx): for j in range(ny): for k in range(nz): # not 0 or NaN if (mask_data[i, j, k] != 0) and (math.isnan(mask_data[i, j, k]) == False)\ and (np.isnan(fmri_data[:, :, :, j, k]).any() == False): n = n + 1 # initialize the data for calculating the RDM data = np.zeros([ncons, nsubs, n], dtype=np.float) # assignment for p in range(ncons): for q in range(nsubs): n = 0 for i in range(nx): for j in range(ny): for k in range(nz): # not 0 or NaN if (mask_data[i, j, k] != 0) and (math.isnan(mask_data[i, j, k]) == False)\ and (np.isnan(fmri_data[:, :, :, j, k]).any() == False): data[p, q, n] = fmri_data[p, q, i, j, k] n = n + 1 # initialize the RDMs subrdms = np.zeros([nsubs, ncons, ncons], dtype=np.float) # shape of data: [ncons, nsubs, n] -> [nsubs, ncons, n] data = np.transpose(data, (1, 0, 2)) # calculate the values in RDM for sub in range(nsubs): for i in range(ncons): for j in range(ncons): if (np.isnan(data[:, i]).any() == False) and (np.isnan( data[:, j]).any() == False): if method is 'correlation': # calculate the Pearson Coefficient r = pearsonr(data[sub, i], data[sub, j])[0] # calculate the dissimilarity if abs == True: subrdms[sub, i, j] = limtozero(1 - np.abs(r)) else: subrdms[sub, i, j] = limtozero(1 - r) elif method is 'euclidean': subrdms[sub, i, j] = np.linalg.norm(data[sub, i] - data[sub, j]) elif method is 'mahalanobis': X = np.transpose( np.vstack((data[sub, i], data[sub, j])), (1, 0)) X = np.dot(X, np.linalg.inv(np.cov(X, rowvar=False))) subrdms[sub, i, j] = np.linalg.norm(X[:, 0] - X[:, 1]) if method is 'euclidean' or method is 'mahalanobis': max = np.max(subrdms[sub]) min = np.min(subrdms[sub]) subrdms[sub] = (subrdms[sub] - min) / (max - min) # average the RDMs rdm = np.average(subrdms, axis=0) if sub_opt == 0: return rdm if sub_opt == 1: return subrdms
def fmriRDM(fmri_data, ksize=[3, 3, 3], strides=[1, 1, 1], sub_opt=1, method="correlation", abs=False): """ Calculate the Representational Dissimilarity Matrices (RDMs) based on fMRI data (searchlight) Parameters ---------- fmri_data : array The fmri data. The shape of fmri_data must be [n_cons, n_subs, nx, ny, nz]. n_cons, nx, ny, nz represent the number of conditions, the number of subs & the size of fMRI-img, respectively. 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. kx, ky, kz should be odd. strides : array or list [sx, sy, sz]. Default is [1, 1, 1]. The strides for calculating along the x, y, z axis. sub_opt: int 0 or 1. Default is 1. Return the subject-result or average-result. If sub_opt=0, return the average result. If sub_opt=1, return the results of each subject. method : string 'correlation' or 'euclidean'. Default is 'correlation'. The method to calculate the dissimilarities. If method='correlation', the dissimilarity is calculated by Pearson Correlation. If method='euclidean', the dissimilarity is calculated by Euclidean Distance, the results will be normalized. abs : boolean True or False. Default is True. Calculate the absolute value of Pearson r or not. Returns ------- RDM : array The fMRI-Searchlight RDM. If sub_opt=0, the shape of RDMs is [n_x, n_y, n_z, n_cons, n_cons]. If sub_opt=1, the shape of RDMs is [n_subs, n_x, n_y, n_cons, n_cons] n_subs, n_x, n_y, n_z represent the number of subjects & the number of calculation units for searchlight along the x, y, z axis. """ if len(np.shape(fmri_data)) != 5: print( "\nThe shape of input for fmriRDM() function must be [n_cons, n_subs, nx, ny, nz].\n" ) return "Invalid input!" # get the number of conditions, subjects and the size of the fMRI-img cons, subs, nx, ny, nz = np.shape(fmri_data) # 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 = int((nx - kx) / sx) + 1 n_y = int((ny - ky) / sy) + 1 n_z = int((nz - kz) / sz) + 1 # initialize the data for calculating the RDM data = np.full([n_x, n_y, n_z, cons, kx * ky * kz, subs], np.nan) print("\nComputing RDMs") # assignment for x in range(n_x): for y in range(n_y): for z in range(n_z): for i in range(cons): index = 0 for k1 in range(kx): for k2 in range(ky): for k3 in range(kz): for j in range(subs): data[x, y, z, i, index, j] = fmri_data[i, j, x * sx + k1, y * sy + k2, z * sz + k3] index = index + 1 # shape of data: [n_x, n_y, n_z, cons, kx*ky*kz, subs] # ->[subs, n_x, n_y, n_z, cons, kx*ky*kz] data = np.transpose(data, (5, 0, 1, 2, 3, 4)) # flatten the data for different calculating conditions data = np.reshape(data, [subs, n_x, n_y, n_z, cons, kx * ky * kz]) # initialize the RDMs subrdms = np.full([subs, n_x, n_y, n_z, cons, cons], np.nan) total = subs * n_x * n_y * n_z for sub in range(subs): for x in range(n_x): for y in range(n_y): for z in range(n_z): # show the progressbar percent = (sub * n_x * n_y * n_z + x * n_y * n_z + y * n_z + z + 1) / total * 100 show_progressbar("Calculating", percent) for i in range(cons): for j in range(cons): # no NaN if (np.isnan(data[:, x, y, z, i]).any() == False) and \ (np.isnan(data[:, x, y, z, j]).any() == False): if method == 'correlation': # calculate the Pearson Coefficient r = pearsonr(data[sub, x, y, z, i], data[sub, x, y, z, j])[0] # calculate the dissimilarity if abs == True: subrdms[sub, x, y, z, i, j] = limtozero(1 - np.abs(r)) else: subrdms[sub, x, y, z, i, j] = limtozero(1 - r) elif method == 'euclidean': subrdms[sub, x, y, z, i, j] = np.linalg.norm( data[sub, x, y, z, i] - data[sub, x, y, z, j]) """elif method == 'mahalanobis': X = np.transpose(np.vstack((data[sub, x, y, z, i], data[sub, x, y, z, j])), (1, 0)) X = np.dot(X, np.linalg.inv(np.cov(X, rowvar=False))) subrdms[sub, x, y, z, i, j] = np.linalg.norm(X[:, 0] - X[:, 1])""" if method == 'euclidean': max = np.max(subrdms[sub, x, y, z]) min = np.min(subrdms[sub, x, y, z]) subrdms[sub, x, y, z] = (subrdms[sub, x, y, z] - min) / (max - min) # average the RDMs rdms = np.average(subrdms, axis=0) print("\nRDMs computing finished!") if sub_opt == 0: return rdms if sub_opt == 1: return subrdms
def fmriRDM(fmri_data, ksize=[3, 3, 3], strides=[1, 1, 1]): """ Calculate the Representational Dissimilarity Matrices (RDMs) for fMRI data (Searchlight) Parameters ---------- fmri_data : array The fmri data. The shape of fmri_data must be [n_cons, n_subs, n_chls, nx, ny, nz]. n_cons, n_chls, nx, ny, nz represent the number of conidtions, the number of channels & the size of fMRI-img, respectively. 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. Returns ------- RDM : array The fMRI-Searchlight RDM. The shape of RDMs is [n_x, n_y, n_z, n_cons, n_cons]. n_x, n_y, n_z represent the number of calculation units for searchlight along the x, y, z axis """ # get the number of conditions, subjects and the size of the fMRI-img cons, subs, nx, ny, nz = np.shape(fmri_data) # 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 = int((nx - kx) / sx)+1 n_y = int((ny - ky) / sy)+1 n_z = int((nz - kz) / sz)+1 # initialize the data for calculating the RDM data = np.full([n_x, n_y, n_z, cons, kx*ky*kz, subs], np.nan) # assignment for x in range(n_x): for y in range(n_y): for z in range(n_z): for i in range(cons): index = 0 for k1 in range(kx): for k2 in range(ky): for k3 in range(kz): for j in range(subs): data[x, y, z, i, index, j] = fmri_data[i, j, x+k1, y+k2, z+k3] index = index + 1 # flatten the data for different calculating conditions data = np.reshape(data, [n_x, n_y, n_z, cons, kx*ky*kz*subs]) # initialize the RDMs rdms = np.full([n_x, n_y, n_z, cons, cons], np.nan) # calculate the values in RDMs for x in range(n_x): for y in range(n_y): for z in range(n_z): for i in range(cons): for j in range(cons): # no NaN if (np.isnan(data[x, y, z, i]).any() == False) and (np.isnan(data[x, y, z, j]).any() == False): # calculate the Pearson Coefficient r = pearsonr(data[x, y, z, i], data[x, y, z, j])[0] # calculate the dissimilarity rdms[x, y, z, i, j] = limtozero(1 - abs(r)) print(rdms[x, y, z, i, j]) return rdms