def test_functional_erpac(self): """Test function test_functional_pac.""" # erpac simultation n_epochs, n_times, sf, edges = 400, 1000, 512., 50 x, times = pac_signals_wavelet(f_pha=10, f_amp=100, n_epochs=n_epochs, noise=.1, n_times=n_times, sf=sf) times = times[edges:-edges] # phase / amplitude extraction (single time) p = EventRelatedPac(f_pha=[8, 12], f_amp=(30, 200, 5, 5), dcomplex='wavelet', width=12) kw = dict(n_jobs=1, edges=edges) phases = p.filter(sf, x, ftype='phase', **kw) amplitudes = p.filter(sf, x, ftype='amplitude', **kw) n_amp = len(p.yvec) # generate a normal distribution gt = np.zeros((n_amp, n_times - 2 * edges)) b_amp = np.abs(p.yvec.reshape(-1, 1) - np.array([[80, 120]])).argmin(0) gt[b_amp[0]:b_amp[1] + 1, :] = True plt.figure(figsize=(16, 5)) plt.subplot(131) p.pacplot(gt, times, p.yvec, title='Ground truth', cmap='magma') for n_meth, meth in enumerate(['circular', 'gc']): # compute erpac + p-values erpac = p.fit(phases, amplitudes, method=meth, mcp='bonferroni', n_perm=30).squeeze() pvalues = p.pvalues.squeeze() # find everywhere erpac is significant + compare to ground truth is_signi = pvalues < .05 erpac[~is_signi] = np.nan # computes accuracy acc = 100 * (is_signi == gt).sum() / (n_amp * n_times) assert acc > 80. # plot the result title = f"Method={p.method}\nAccuracy={np.around(acc, 2)}%" plt.subplot(1, 3, n_meth + 2) p.pacplot(erpac, times, p.yvec, title=title) plt.tight_layout() plt.show()
# amplitudes # define an ERPAC object p = EventRelatedPac(f_pha=[9, 11], f_amp=(60, 140, 5, 1)) # method for correcting p-values for multiple comparisons mcp = 'bonferroni' # extract phases and amplitudes erpac = p.filterfit(sf, x, method='circular', mcp=mcp).squeeze() # get the p-values and squeeze unused dimensions pvalues = p.pvalues.squeeze() # set to nan everywhere it's not significant erpac[pvalues > .05] = np.nan vmin, vmax = np.nanmin(erpac), np.nanmax(erpac) p.pacplot(erpac, time, p.yvec, xlabel='Time (second)', cmap='Spectral_r', ylabel='Amplitude frequency', title=p.method, cblabel='ERPAC', rmaxis=True, vmin=vmin, vmax=vmax) plt.axvline(1., linestyle='--', color='k', linewidth=2) p.show()
# isolate the gamma range that is coupled with the alpha phase such as when, in # time, this coupling occurs. Here, we compute the ERPAC using the # Gaussian-Copula mutual information (Ince et al. 2017 # :cite:`ince2017statistical`), between the alpha [8, 12]Hz and several gamma # amplitudes, at each time point. rp_obj = EventRelatedPac(f_pha=[8, 12], f_amp=(30, 160, 30, 2)) erpac = rp_obj.filterfit(sf, data, method='gc', smooth=100) ############################################################################### plt.figure(figsize=(8, 6)) rp_obj.pacplot(erpac.squeeze(), times, rp_obj.yvec, xlabel='Time', ylabel='Amplitude frequency (Hz)', title='Event-Related PAC occurring for alpha phase', fz_labels=15, fz_title=18) add_motor_condition(135, color='white') plt.show() ############################################################################### # As you can see from the image above, there is an increase of alpha <-> gamma # (~90Hz) coupling that is occurring especially during the planning phase (i.e # between [0, 1500]ms) ############################################################################### # Align time-frequency map based on alpha phase peak ############################################################################### # to confirm the previous result showing a potential alpha <-> gamma coupling
x1, tvec = pac_signals_wavelet(f_pha=10, f_amp=100, n_epochs=n_epochs, noise=2, n_times=n_times, sf=sf) x2 = np.random.rand(n_epochs, 1000) x = np.concatenate((x1, x2), axis=1) time = np.arange(x.shape[1]) / sf p = EventRelatedPac(f_pha=[9, 11], f_amp='hres') pha = p.filter(sf, x, ftype='phase', n_jobs=-1) amp = p.filter(sf, x, ftype='amplitude', n_jobs=-1) plt.figure(figsize=(14, 6)) for n_m, (method, nb) in enumerate(zip(['circular', 'gc'], ['A', 'B'])): # to be fair with the comparison between ERPAC and gcERPAC, the smoothing # parameter of the gcERPAC is turned off but results could look way better # if for example with add a `smooth=20` erpac = p.fit(pha, amp, method=method, n_jobs=-1).squeeze() plt.subplot(1, 2, n_m + 1) p.pacplot(erpac, time, p.yvec, xlabel='Time (second)', cmap=cfg["cmap"], ylabel='Frequency for amplitude (Hz)', title=p.method, vmin=0., rmaxis=True, fz_labels=20, fz_title=22, fz_cblabel=20) plt.axvline(1., linestyle='--', color='w', linewidth=2) if n_m == 1: plt.ylabel('') ax = plt.gca() ax.text(*tuple(cfg["nb_pos"]), nb, transform=ax.transAxes, **cfg["nb_cfg"]) plt.tight_layout() plt.savefig(f"../figures/Fig5.png", dpi=300, bbox_inches='tight') plt.show()
f_amp=100, n_epochs=n_epochs, noise=2, n_times=n_times, sf=sf) x2 = np.random.rand(n_epochs, 1000) x = np.concatenate((x1, x2), axis=1) time = np.arange(x.shape[1]) / sf p = EventRelatedPac(f_pha=[9, 11], f_amp=(60, 140, 5, 1)) pha = p.filter(sf, x, ftype='phase', n_jobs=1) amp = p.filter(sf, x, ftype='amplitude', n_jobs=1) plt.figure(figsize=(8, 6)) erpac = p.fit(pha, amp, method='circular', n_jobs=-1).squeeze() p.pacplot(erpac, time, p.yvec, xlabel='Time (second)', cmap=cfg["cmap"], ylabel='Frequency for amplitude (Hz)', title='Event Related PAC', vmin=0., rmaxis=True) plt.axvline(1., linestyle='--', color='w', linewidth=2) plt.tight_layout() plt.savefig(f"{cfg['path']}/Fig5.png", dpi=300, bbox_inches='tight') plt.show()
times = times[edges:-edges] # phase / amplitude extraction (single time) p = EventRelatedPac(f_pha=[8, 12], f_amp=(30, 200, 5, 5), dcomplex='wavelet', width=12) kw = dict(n_jobs=1, edges=edges) phases = p.filter(sf, x, ftype='phase', **kw) amplitudes = p.filter(sf, x, ftype='amplitude', **kw) n_amp = len(p.yvec) # generate a normal distribution gt = np.zeros((n_amp, n_times - 2 * edges)) b_amp = np.abs(p.yvec.reshape(-1, 1) - np.array([[80, 120]])).argmin(0) gt[b_amp[0]:b_amp[1] + 1, :] = True plt.figure(figsize=(16, 5)) plt.subplot(131) p.pacplot(gt, times, p.yvec, title='Ground truth', cmap='magma') for n_meth, meth in enumerate(['circular', 'gc']): # compute erpac + p-values erpac = p.fit(phases, amplitudes, method=meth, mcp='bonferroni', n_perm=30).squeeze() pvalues = p.pvalues.squeeze() # find everywhere erpac is significant + compare to ground truth is_signi = pvalues < .05 erpac[~is_signi] = np.nan # computes accuracy acc = 100 * (is_signi == gt).sum() / (n_amp * n_times) assert acc > 80. # plot the result title = f"Method={p.method}\nAccuracy={np.around(acc, 2)}%" plt.subplot(1, 3, n_meth + 2)