def gauss_cop_pac(pha, amp): """Tensor-based Gaussian Copula PAC (gcPac). This function assumes that phases and amplitudes have already been prepared i.e. phases should be represented in a unit circle (np.c_[np.sin(pha), np.cos(pha)]) and both inputs should also have been copnormed. Parameters ---------- pha, amp : array_like Respectively the arrays of phases of shape (n_pha, ..., n_times) and the array of amplitudes of shape (n_amp, ..., n_times). Returns ------- pac : array_like Array of phase amplitude coupling of shape (n_amp, n_pha, ...) References ---------- Ince et al 2017. :cite:`ince2017statistical` """ # prepare the shape of gcpac n_pha, n_amp = pha.shape[0], amp.shape[0] pha_sh = list(pha.shape[:-2]) gc = np.zeros([n_amp] + pha_sh, dtype=float) # compute mutual information for p in range(n_pha): for a in range(n_amp): gc[a, p, ...] = nd_mi_gg(pha[p, ...], amp[a, ...]) return gc
def gcpac(pha, amp): """Gaussian Copula Phase-amplitude coupling. This function assumes that phases and amplitudes have already been prepared i.e. phases should be represented in a unit circle (np.c_[np.sin(pha), np.cos(pha)]) and both inputs should also have been copnormed. Parameters ---------- pha, amp : array_like Respectively the arrays of phases of shape (n_pha, ..., n_times) and the array of amplitudes of shape (n_amp, ..., n_times). Returns ------- pac : array_like Array of phase amplitude coupling of shape (n_amp, n_pha, ...) References ---------- Ince RAA, Giordano BL, Kayser C, Rousselet GA, Gross J, Schyns PG (2017) A statistical framework for neuroimaging data analysis based on mutual information estimated via a gaussian copula: Gaussian Copula Mutual Information. Human Brain Mapping 38:1541–1573. """ # prepare the shape of gcpac n_pha, n_amp = pha.shape[0], amp.shape[0] pha_sh = list(pha.shape[:-2]) gc = np.zeros([n_amp] + pha_sh, dtype=float) # compute mutual information for p in range(n_pha): for a in range(n_amp): gc[a, p, ...] = nd_mi_gg(pha[p, ...], amp[a, ...]) return gc
def _fcn(xp, xa): # noqa _erpac = np.zeros((n_amp, n_pha), dtype=float) for a in range(n_amp): _xa = xa.reshape(n_amp, 1, -1) for p in range(n_pha): _xp = xp.reshape(n_pha, 2, -1) _erpac[a, p] = nd_mi_gg(_xp[p, ...], _xa[a, ...]) return _erpac
def ergcpac(pha, amp, smooth=None, n_jobs=-1): """Event Related PAC using the Gaussian Copula Mutual Information. This function assumes that phases and amplitudes have already been prepared i.e. phases should be represented in a unit circle (np.c_[np.sin(pha), np.cos(pha)]) and both inputs should also have been copnormed. Parameters ---------- pha, amp : array_like Respectively arrays of phases of shape (n_pha, n_times, 2, n_epochs) and the array of amplitudes of shape (n_amp, n_times, 1, n_epochs). Returns ------- erpac : array_like Array of correlation coefficients of shape (n_amp, n_pha, n_times) References ---------- Ince et al. 2017 :cite:`ince2017statistical` """ # get shapes (n_pha, n_times, _, n_epochs), n_amp = pha.shape, amp.shape[0] # noqa # compute mutual information across trials ergcpac = np.zeros((n_amp, n_pha, n_times)) if isinstance(smooth, int): # define the temporal smoothing vector vec = np.arange(smooth, n_times - smooth, 1) times = [slice(k - smooth, k + smooth + 1) for k in vec] # move time axis to avoid to do it inside parallel pha, amp = np.moveaxis(pha, 1, -2), np.moveaxis(amp, 1, -2) # function to run in parallel across times def _fcn(t): # noqa _erpac = np.zeros((n_amp, n_pha), dtype=float) xp, xa = pha[..., t, :], amp[..., t, :] for a in range(n_amp): _xa = xa.reshape(n_amp, 1, -1) for p in range(n_pha): _xp = xp.reshape(n_pha, 2, -1) _erpac[a, p] = nd_mi_gg(_xp[p, ...], _xa[a, ...]) return _erpac # run the function across time points _ergcpac = Parallel(n_jobs=n_jobs, **CONFIG['JOBLIB_CFG'])(delayed(_fcn)(t) for t in times) # reconstruct the smoothed array for a in range(n_amp): for p in range(n_pha): mean_vec = np.zeros((n_times, ), dtype=float) for t, _gc in zip(times, _ergcpac): ergcpac[a, p, t] += _gc[a, p] mean_vec[t] += 1 ergcpac[a, p, :] /= mean_vec else: for a in range(n_amp): for p in range(n_pha): ergcpac[a, p, ...] = nd_mi_gg(pha[p, ...], amp[a, ...]) return ergcpac
def ergcpac(pha, amp, smooth=None, n_jobs=-1): """Event Related PAC computed using the Gaussian Copula Mutual Information. Parameters ---------- pha, amp : array_like Respectively the arrays of phases of shape (n_pha, n_times, n_epochs) and the array of amplitudes of shape (n_amp, n_times, n_epochs). Returns ------- rho : array_like Array of correlation coefficients of shape (n_amp, n_pha, n_times) References ---------- Ince RAA, Giordano BL, Kayser C, Rousselet GA, Gross J, Schyns PG (2017) A statistical framework for neuroimaging data analysis based on mutual information estimated via a gaussian copula: Gaussian Copula Mutual Information. Human Brain Mapping 38:1541–1573. """ # Move the trial axis to the end : pha = np.moveaxis(pha, 1, -1) amp = np.moveaxis(amp, 1, -1) # get shapes n_pha, n_times, n_epochs = pha.shape n_amp = amp.shape[0] # conversion for computing mi sco = copnorm(np.stack([np.sin(pha), np.cos(pha)], axis=-2)) amp = copnorm(amp)[..., np.newaxis, :] # compute mutual information across trials ergcpac = np.zeros((n_amp, n_pha, n_times)) if isinstance(smooth, int): # define the temporal smoothing vector vec = np.arange(smooth, n_times - smooth, 1) times = [slice(k - smooth, k + smooth + 1) for k in vec] # move time axis to avoid to do it inside parallel sco = np.moveaxis(sco, 1, -2) amp = np.moveaxis(amp, 1, -2) # function to run in parallel across times def _fcn(xp, xa): # noqa _erpac = np.zeros((n_amp, n_pha), dtype=float) for a in range(n_amp): _xa = xa.reshape(n_amp, 1, -1) for p in range(n_pha): _xp = xp.reshape(n_pha, 2, -1) _erpac[a, p] = nd_mi_gg(_xp[p, ...], _xa[a, ...]) return _erpac # run the function across time points _ergcpac = Parallel(n_jobs=n_jobs, **JOBLIB_CFG)(delayed(_fcn)(sco[..., t, :], amp[..., t, :]) for t in times) # reconstruct the smoothed ERGCPAC array for a in range(n_amp): for p in range(n_pha): mean_vec = np.zeros((n_times, ), dtype=float) for t, _gc in zip(times, _ergcpac): ergcpac[a, p, t] += _gc[a, p] mean_vec[t] += 1 ergcpac[a, p, :] /= mean_vec else: for a in range(n_amp): for p in range(n_pha): ergcpac[a, p, ...] = nd_mi_gg(sco[p, ...], amp[a, ...]) return ergcpac