예제 #1
0
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
예제 #2
0
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
예제 #3
0
 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
예제 #4
0
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
예제 #5
0
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