Beispiel #1
0
def test_pac_meth():
    """Test all Pac methods."""
    pha = np.random.rand(2, 7, 1024)
    amp = np.random.rand(3, 7, 1024)
    nmeth, nsuro, nnorm = 5, 5, 5
    p = Pac()
    for k in range(nmeth):
        for i in range(nsuro):
            for j in range(nnorm):
                p.idpac = (k + 1, i, j)
                p.fit(pha, amp, axis=2, traxis=1, njobs=1, nperm=2)
Beispiel #2
0
 def test_fit(self):
     """Test all Pac methods."""
     pha = np.random.rand(2, 7, 1024)
     amp = np.random.rand(3, 7, 1024)
     nmeth, nsuro, nnorm = 5, 4, 5
     p = Pac()
     for k in range(nmeth):
         for i in range(nsuro):
             for j in range(nnorm):
                 p.idpac = (k + 1, i, j)
                 p.fit(pha, amp, n_jobs=1, n_perm=10)
Beispiel #3
0
 def test_fit(self):
     """Test all Pac methods."""
     pha = np.random.rand(2, 7, 1024)
     amp = np.random.rand(3, 7, 1024)
     nmeth, nsuro, nnorm = 5, 4, 5
     p = Pac(verbose=False)
     for k in range(nmeth):
         for i in range(nsuro):
             for j in range(nnorm):
                 p.idpac = (k + 1, i, j)
                 p.fit(pha, amp, n_jobs=1, n_perm=10)
                 if (i >= 1) and (k + 1 != 4):
                     for mcp in ['maxstat', 'fdr', 'bonferroni']:
                         p.infer_pvalues(mcp=mcp)
Beispiel #4
0
    def test_functional_pac(self):
        """Test functionnal pac."""
        # generate a 10<->100hz ground truth coupling
        n_epochs, sf, n_times = 1, 512., 4000
        data, time = pac_signals_wavelet(f_pha=10,
                                         f_amp=100,
                                         noise=.8,
                                         n_epochs=n_epochs,
                                         n_times=n_times,
                                         sf=sf)
        # phase / amplitude extraction (single time)
        p = Pac(f_pha='lres', f_amp='lres', dcomplex='wavelet', width=12)
        phases = p.filter(sf, data, ftype='phase', n_jobs=1)
        amplitudes = p.filter(sf, data, ftype='amplitude', n_jobs=1)
        # ground truth array construction
        n_pha, n_amp = len(p.xvec), len(p.yvec)
        n_pix = int(n_pha * n_amp)
        gt = np.zeros((n_amp, n_pha), dtype=bool)
        b_pha = np.abs(p.xvec.reshape(-1, 1) - np.array([[9, 11]])).argmin(0)
        b_amp = np.abs(p.yvec.reshape(-1, 1) - np.array([[95, 105]])).argmin(0)
        gt[b_amp[0]:b_amp[1] + 1, b_pha[0]:b_pha[1] + 1] = True

        plt.figure(figsize=(12, 9))
        plt.subplot(2, 3, 1)
        p.comodulogram(gt, title='Gound truth', cmap='magma', colorbar=False)
        # loop over implemented methods
        for i, k in enumerate([1, 2, 3, 5, 6]):
            # compute only the pac
            p.idpac = (k, 2, 3)
            xpac = p.fit(phases, amplitudes, n_perm=200).squeeze()
            pval = p.pvalues.squeeze()
            is_coupling = pval <= .05
            # count the number of correct pixels. This includes both true
            # positives and true negatives
            acc = 100 * (is_coupling == gt).sum() / n_pix
            assert acc > 95.
            # build title of the figure (for sanity check)
            meth = p.method.replace(' (', '\n(')
            title = f"Method={meth}\nAccuracy={np.around(acc, 2)}%"
            # set to nan everywhere it's not significant
            xpac[~is_coupling] = np.nan
            vmin, vmax = np.nanmin(xpac), np.nanmax(xpac)
            # plot the results
            plt.subplot(2, 3, i + 2)
            p.comodulogram(xpac,
                           colorbar=False,
                           vmin=vmin,
                           vmax=vmax,
                           title=title)
            plt.ylabel(''), plt.xlabel('')
        plt.tight_layout()
        plt.show()  # show on demand
plt.style.use('seaborn-paper')

# First, we generate a delta <-> low-gamma coupling. By default, this dataset
#  is organized as (n_epochs, n_times) where n_times is the number of time
# points.
n_epochs = 20     # number of datasets
sf = 512.  # sampling frequency
data, time = pac_signals_wavelet(sf=sf, f_pha=6, f_amp=70, noise=3.,
                                 n_epochs=n_epochs, n_times=4000)

# First, let's use the MVL, without any further correction by surrogates :
p = Pac(f_pha=(3, 10, 1, .2), f_amp=(50, 90, 5, 1), dcomplex='wavelet',
        width=12)

# Now, we want to compare PAC methods, hence it's useless to systematically
# filter the data. So we extract the phase and the amplitude only once :
phases = p.filter(sf, data, ftype='phase')
amplitudes = p.filter(sf, data, ftype='amplitude')

plt.figure(figsize=(16, 12))
for i, k in enumerate(range(4)):
    # Change the pac method :
    p.idpac = (5, k, 1)
    # Compute only the PAC without filtering :
    xpac = p.fit(phases, amplitudes, n_perm=10)
    # Plot :
    plt.subplot(2, 2, k + 1)
    p.comodulogram(xpac.mean(-1), title=p.str_surro, cmap='Reds', vmin=0)

plt.show()
# to extract all of the phases and amplitudes only once

# define a pac object and extract high-resolution phases and amplitudes using
# Morlet's wavelets
p = Pac(f_pha='hres', f_amp='hres', dcomplex='wavelet')
# etract all of the phases and amplitudes
phases = p.filter(sf, data, ftype='phase', n_jobs=1)
amplitudes = p.filter(sf, data, ftype='amplitude', n_jobs=1)

###############################################################################
# Compute, plot and compare PAC
###############################################################################
# Once all of the phases and amplitudes extracted we can compute PAC by
# ietrating over the implemented methods.

plt.figure(figsize=(14, 8))
for i, k in enumerate([1, 2, 3, 4, 5, 6]):
    # switch method of PAC
    p.idpac = (k, 0, 0)
    # compute only the pac without filtering
    xpac = p.fit(phases, amplitudes)
    # plot
    plt.subplot(2, 3, k)
    title = p.method.replace(' (', f' ({k})\n(')
    p.comodulogram(xpac.mean(-1), title=title, cmap='viridis')
    if k <= 3:
        plt.xlabel('')

plt.tight_layout()
plt.show()
# periods

p_obj = Pac(idpac=(6, 0, 0), f_pha=(6, 14, 4, .2), f_amp=(60, 120, 20, 2))
# extract all of the phases and amplitudes
pha_p = p_obj.filter(sf, data, ftype='phase')
amp_p = p_obj.filter(sf, data, ftype='amplitude')
# define time indices where rest, planning and execution are defined
time_rest = slice(0, 1000)
time_prep = slice(1000, 2500)
time_exec = slice(2500, 4000)
# define phase / amplitude during rest / planning / execution
pha_rest, amp_rest = pha_p[..., time_rest], amp_p[..., time_rest]
pha_prep, amp_prep = pha_p[..., time_prep], amp_p[..., time_prep]
pha_exec, amp_exec = pha_p[..., time_exec], amp_p[..., time_exec]
# compute PAC inside rest, planning, and execution
pac_rest = p_obj.fit(pha_rest, amp_rest).mean(-1)
pac_prep = p_obj.fit(pha_prep, amp_prep).mean(-1)
pac_exec = p_obj.fit(pha_exec, amp_exec).mean(-1)

##############################################################################
# plot the comodulograms inside the rest, planning and execution period

vmax = np.max([pac_rest.max(), pac_prep.max(), pac_exec.max()])
kw = dict(vmax=vmax, vmin=.04, cmap='viridis')
plt.figure(figsize=(14, 4))
plt.subplot(131)
p_obj.comodulogram(pac_rest, title="PAC Rest [-1, 0]s", **kw)
plt.subplot(132)
p_obj.comodulogram(pac_prep, title="PAC Planning [0, 1.5]s", **kw)
plt.ylabel('')
plt.subplot(133)
# ground truth array construction
n_pha, n_amp = len(p.xvec), len(p.yvec)
n_pix = int(n_pha * n_amp)
gt = np.zeros((n_amp, n_pha), dtype=bool)
b_pha = np.abs(p.xvec.reshape(-1, 1) - np.array([[9, 11]])).argmin(0)
b_amp = np.abs(p.yvec.reshape(-1, 1) - np.array([[95, 105]])).argmin(0)
gt[b_amp[0]:b_amp[1] + 1, b_pha[0]:b_pha[1] + 1] = True

plt.figure(figsize=(12, 9))
plt.subplot(2, 3, 1)
p.comodulogram(gt, title='Gound truth', cmap='magma', colorbar=False)
# loop over implemented methods
for i, k in enumerate([1, 2, 3, 5, 6]):
    # compute only the pac
    p.idpac = (k, 2, 3)
    xpac = p.fit(phases, amplitudes, n_perm=200).squeeze()
    pval = p.pvalues.squeeze()
    is_coupling = pval <= .05
    # count the number of correct pixels. This includes both true
    # positives and true negatives
    trpr = (is_coupling == gt).sum() / n_pix
    assert trpr > .95
    # build title of the figure (for sanity check)
    meth = p.method.replace(' (', '\n(')
    title = f"Method={meth}\nAccuracy={np.around(trpr * 100, 2)}%"
    # set to nan everywhere it's not significant
    xpac[~is_coupling] = np.nan
    vmin, vmax = np.nanmin(xpac), np.nanmax(xpac)
    # plot the results
    plt.subplot(2, 3, i + 2)
    p.comodulogram(xpac, colorbar=False, vmin=vmin, vmax=vmax, title=title)
                                 n_epochs=n_epochs,
                                 n_times=n_times)
alphabet = string.ascii_uppercase

p = Pac(idpac=(1, 2, 3), f_pha='hres', f_amp='hres')
pha = p.filter(sf, data, ftype='phase', n_jobs=1)
amp = p.filter(sf, data, ftype='amplitude', n_jobs=1)

plt.figure(figsize=(18, 10))
gs = GridSpec(2, 7)

for k in range(6):
    p.idpac = (k + 1, 2, 3)
    xpac = p.fit(pha.copy(),
                 amp.copy(),
                 n_perm=n_perm,
                 p=.05,
                 n_jobs=-1,
                 random_state=k).mean(-1)

    sq = methods[titles[k]]
    plt.subplot(gs[sq[0], sq[1]])
    p.comodulogram(xpac,
                   cblabel="",
                   title=p.method.replace(' (', '\n('),
                   cmap=cfg["cmap"],
                   vmin=0,
                   colorbar=True,
                   fz_labels=15,
                   fz_title=16)
    # clean up x-y labels
    if k % 3 != 0: plt.ylabel("")  # noqa
plt.plot(time, np.squeeze(x100hz), color='lightgray', linewidth=1)
plt.plot(time, np.squeeze(amplitude), color=color_amp, linewidth=3)
plt.xticks([]), plt.yticks([])
plt.title("100hz amplitude")
rmaxis(plt.gca())
savefig('100hz_amp')

###############################################################################
# surrogates
###############################################################################
data, time = pac_signals_tort(n_epochs=10,
                              f_pha=10,
                              f_amp=100,
                              sf=1024,
                              n_times=1000,
                              rnd_state=1)
p = Pac(idpac=(1, 2, 3), f_pha=[9, 11], f_amp=[90, 110])
pha = p.filter(1024, data, ftype='phase')
amp = p.filter(1024, data, ftype='amplitude')
pac = p.fit(pha, amp, n_perm=n_perm).squeeze()
surro = p.surrogates.squeeze().max(-1)

plt.figure(figsize=(6, 4.5))
plt.hist(surro, bins=10, color=color_perm)
plt.title("Distribution of surrogates")
rmaxis(plt.gca())
plt.autoscale(axis='both', tight=True)
plt.xticks([]), plt.yticks([])
plt.tight_layout()
savefig('perm')
Beispiel #11
0
data, time = pac_signals_wavelet(sf=sf, f_pha=10, f_amp=100, noise=2.,
                                 n_epochs=n_epochs, n_times=n_times)


p = Pac(idpac=(1, 2, 3), f_pha=cfg["phres"], f_amp=cfg["ahres"])
# p = Pac(idpac=(1, 2, 3), f_pha=(1, 30, 1, 1), f_amp=(60, 160, 5, 5))
# p = Pac(idpac=(1, 2, 3), f_pha='mres', f_amp='mres')
pha = p.filter(sf, data, ftype='phase', n_jobs=1)
amp = p.filter(sf, data, ftype='amplitude', n_jobs=1)

plt.figure(figsize=(18, 10))
gs = GridSpec(2, 7)

for k in range(5):
    p.idpac = (k + 1, 2, 3)
    xpac = p.fit(pha.copy(), amp.copy(), n_perm=n_perm, p=.05,
                 n_jobs=-1).mean(-1)

    sq = methods[titles[k]]
    plt.subplot(gs[sq[0], sq[1]])
    p.comodulogram(xpac, cblabel="", title=titles[k], cmap=cfg["cmap"],
                   vmin=0, colorbar=True)
    if k > 0:
        plt.ylabel("")
        # plt.tick_params(axis='y', which='both', labelleft=False)

plt.tight_layout()
plt.savefig(f"{cfg['path']}/Fig3.png", dpi=300,
            bbox_inches='tight')

p.show()
#  is organized as (ntrials, npts) where npts is the number of time points.
n = 30  # number of datasets
sf = 512.  # sampling frequency
data, time = pac_signals_wavelet(sf=sf,
                                 fpha=6,
                                 famp=70,
                                 noise=2.,
                                 ntrials=n,
                                 npts=4000)

# First, let's use the MVL, without any further correction by surrogates :
p = Pac(fpha=(3, 10, 1, .2), famp=(50, 90, 5, 1), dcomplex='wavelet', width=12)

# Now, we want to compare PAC methods, hence it's useless to systematically
# filter the data. So we extract the phase and the amplitude only once :
phases = p.filter(sf, data, axis=1, ftype='phase')
amplitudes = p.filter(sf, data, axis=1, ftype='amplitude')

plt.figure(figsize=(18, 9))
for i, k in enumerate(range(5)):
    # Change the pac method :
    p.idpac = (5, k, 1)
    print('-> Surrogates using ' + p.surro)
    # Compute only the PAC without filtering :
    xpac = p.fit(phases, amplitudes, axis=2, nperm=5)
    # Plot :
    plt.subplot(2, 3, k + 1)
    p.comodulogram(xpac.mean(-1), title=p.surro, cmap='Spectral_r')

plt.show()
Beispiel #13
0
phases = p.filter(sf, data, ftype='phase')
amplitudes = p.filter(sf, data, ftype='amplitude')

###############################################################################
# Compute PAC and surrogates
###############################################################################
# now the phases and amplitudes are extracted, we can compute the true PAC such
# as the surrogates. Then the true value of PAC is going to be normalized using
# a z-score normalization and using the distribution of surrogates

plt.figure(figsize=(16, 12))
for i, k in enumerate(range(4)):
    # change the pac method
    p.idpac = (5, k, 1)
    # compute only the pac without filtering
    xpac = p.fit(phases, amplitudes, n_perm=20, random_state=0)
    # plot
    title = p.str_surro.replace(' (', '\n(')
    plt.subplot(2, 2, k + 1)
    p.comodulogram(xpac.mean(-1),
                   title=title,
                   cmap='Reds',
                   vmin=0,
                   fz_labels=18,
                   fz_title=20,
                   fz_cblabel=18)

plt.tight_layout()

plt.show()
Beispiel #14
0
###############################################################################
data, time = pac_signals_wavelet(f_pha=6,
                                 f_amp=70,
                                 n_epochs=n_epochs,
                                 noise=1,
                                 n_times=n_times,
                                 sf=sf)

psd = PSD(data, sf)

trif, tridx = pac_trivec(f_start=40, f_end=100, f_width=3)

p = Pac(idpac=(6, 0, 0), f_pha=[5, 7], f_amp=trif)
pha = p.filter(sf, data, ftype='phase')
amp = p.filter(sf, data, ftype='amplitude')
pac = p.fit(pha, amp, n_jobs=-1).mean(-1).squeeze()

best_f = trif[pac.argmax()]

plt.figure(figsize=(16, 7))
plt.subplot(121)
ax = psd.plot(confidence=None, f_min=2, f_max=30, log=False, grid=True)
plt.ylim(0, .15)
plt.title("Power Spectrum Density (PSD)")
# plt.autoscale(enable=True, axis='y', tight=True)
ax = plt.gca()
ax.text(*tuple(cfg["nb_pos"]), 'A', transform=ax.transAxes, **cfg["nb_cfg"])

plt.subplot(122)
p.triplot(pac,
          trif,
Beispiel #15
0
npts = 3000  # Number of time points
data, time = pac_signals_tort(sf=sf,
                              fpha=[4, 6],
                              famp=[90, 110],
                              noise=3,
                              ntrials=n,
                              dpha=10,
                              damp=10,
                              npts=npts)

# First, let's use the MVL, without any further correction by surrogates :
p = Pac(fpha=(1, 10, 1, .1), famp=(60, 140, 1, 1), dcomplex='wavelet', width=6)

# Now, we want to compare PAC methods, hence it's useless to systematically
# filter the data. So we extract the phase and the amplitude only once :
phases = p.filter(sf, data, axis=1, ftype='phase')
amplitudes = p.filter(sf, data, axis=1, ftype='amplitude')

plt.figure(figsize=(18, 9))
for i, k in enumerate([1, 2, 3, 4, 5]):
    # Change the pac method :
    p.idpac = (k, 0, 0)
    print('-> PAC using ' + str(p))
    # Compute only the PAC without filtering :
    xpac = p.fit(phases, amplitudes, axis=2)
    # Plot :
    plt.subplot(2, 3, k)
    p.comodulogram(xpac.mean(-1), title=p.method, cmap='Spectral_r')

plt.show()