OSCR

Alpha frequency shapes perceptual sensitivity by modulating optimal phase likelihood.

Code ↔ Paper

4 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 4 matches · 1 of them tie a paragraph to a whole file, not to given lines: a weak match, whose lines are not tinted
  1. [1] § Methods › Extract instantaneous alpha frequency and phase ↔ SCRIPT/restingIAF_natcomm.m, the whole file · a weak match · score 0.64 · alpha band, spectral, derivative, spectopo, filtered, noise
  2. [2] § Methods › Extract instantaneous alpha frequency and phase ↔ SCRIPT/Script_NC.m, lines 1004–1130 · score 0.64 · single trial IAF, instantaneous frequency, IAF accuracy, EEGLAB, FFT, pre
  3. [3] § Methods › Assessing the specificity of the relationship between IAF and perceptual accuracy relative to alpha power ↔ SCRIPT/Script_NC.m, lines 780–913 · score 0.62 · alpha power, trial fluctuation, perceptual accuracy, amplitude, EEG, incorrect
  4. [4] § Methods › IAF single-trial regression: accuracy ↔ SCRIPT/Script_NC.m, lines 1004–1130 · score 0.54 · single trial IAF, instantaneous frequency, row, FFT, pre, stimulus

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

MATLAB · 1,130 lines · 44 KB · no license · 3 matches

  1. %% ------------------------- EXTRACT PEAK & ELECTRODES ---------------------
  2. clc; clear; close all
  3. eegfolder = ''%path
  4. cd(EEGFOLDER);
  5. dEEG = dir(EEGFOLDER);
  6. EEG_files = struct2cell(dEEG)';
  7. EEG_files = EEG_files(3:end,1);
  8. start_from = 2;
  9. subji = start_from:2:length(EEG_files);
  10. dataEEG = cell(1, numel(subji));
  11. cd(EEGFOLDER);
  12. for p = 1:numel(subji)
  13. idxEEG = subji(p);
  14. filename = char(EEG_files{idxEEG});
  15. EEG = pop_loadset('filename', filename);
  16. EEG = eeg_checkset(EEG);
  17. dataEEG{p} = EEG;
  18. end
  19. electrodes_peak = cell(1, numel(subji));
  20. peak = nan(1, numel(subji));
  21. for soggetto = 1:numel(subji)
  22. EEG = dataEEG{soggetto};
  23. EEG.data = diff(EEG.data, 1, 2);
  24. data = double(EEG.data);
  25. chosedelectrodes = [18,49,50,17,48];
  26. time2anal = [-800 -100];
  27. time2idx = dsearchn(EEG.times', time2anal');
  28. datawin = data(chosedelectrodes, time2idx(1):time2idx(2), :);
  29. [a,b] = spectopo(datawin, 0, EEG.srate, 'nfft', EEG.srate*100, 'plot', 'off', 'verbose', 'off');
  30. alphalim = [7 13];
  31. alphaidx = dsearchn(b, alphalim');
  32. alphapow = mean(a(:, alphaidx(1):alphaidx(2)), 2);
  33. [~, which_elec] = sort(alphapow, 'descend');
  34. electrodes_peak{soggetto} = EEG.chanlocs(chosedelectrodes(which_elec(1))).labels;
  35. data1 = squeeze(EEG.data(chosedelectrodes(which_elec(1)), :, :));
  36. data1 = reshape(data1, 1, size(data1,1), size(data1,2));
  37. cmin=1; fRange=[1 40]; w=[7 13]; Fw=11; k=5; Fs=EEG.srate;
  38. data_colcoran = reshape(data1(:, time2idx(1):time2idx(2), :), 1, []);
  39. [~, colcalpha] = restingIAF(data_colcoran, 1, cmin, fRange, Fs, w, Fw, k);
  40. peak(soggetto) = colcalpha.peaks;
  41. for elec = 2:length(chosedelectrodes)
  42. if isnan(peak(soggetto))
  43. electrodes_peak{soggetto} = EEG.chanlocs(chosedelectrodes(which_elec(elec))).labels;
  44. data_alt = squeeze(EEG.data(chosedelectrodes(which_elec(elec)), time2idx(1):time2idx(2), :));
  45. data_alt = reshape(data_alt, 1, size(data_alt,1), size(data_alt,2));
  46. data_colcoran = reshape(data_alt, 1, []);
  47. [~, colcalpha] = restingIAF(data_colcoran, 1, cmin, fRange, Fs, w, Fw, k);
  48. peak(soggetto) = colcalpha.peaks;
  49. end
  50. end
  51. end
  52. %% --------------------- EXTRACT INST_IAF --------------------
  53. clc; clear; close all
  54. load('AllSubjects.mat')
  55. eegfolder = ''%path
  56. cd(EEGFOLDER);
  57. dEEG = dir(EEGFOLDER);
  58. EEG_files = struct2cell(dEEG)';
  59. EEG_files = EEG_files(3:end,1);
  60. start_from = 2;
  61. subji = start_from:2:length(EEG_files);
  62. dataEEG = cell(1, numel(subji));
  63. cd(EEGFOLDER);
  64. for p = 1:numel(subji)
  65. idxEEG = subji(p);
  66. filename = char(EEG_files{idxEEG});
  67. EEG = pop_loadset('filename', filename);
  68. EEG = eeg_checkset(EEG);
  69. dataEEG{p} = EEG;
  70. end
  71. electrodes_to_analyze_all = readcell('electrodes_to_analyze.xlsx');
  72. peak = readmatrix('peak_to_analyze.xlsx');
  73. for subject = 1:numel(databehx)
  74. EEG = dataEEG{subject};
  75. EEG.data = diff(EEG.data, 1, 2);
  76. electrodes_to_analyze = find(strcmpi({EEG.chanlocs.labels}, electrodes_to_analyze_all{subject}));
  77. alpha_lim = [peak(subject)-2, peak(subject)+2];
  78. [inst_freq, inst_ph] = instantaneous_NatComm(EEG.data(electrodes_to_analyze,:,:), EEG.srate, alpha_lim);
  79. inst_freq = squeeze(inst_freq);
  80. inst_ph = squeeze(inst_ph);
  81. end
  82. %% Pre-stimulus IAF is linked to variations in perceptual sensitivity: BIN analysis
  83. clc,clear
  84. load('IAF_allSubjects.mat');
  85. nS = numel(datax);
  86. d = zeros(nS,2);
  87. c = zeros(nS,2);
  88. accuracy = zeros(nS,2);
  89. iaf_mean_terciles = zeros(nS,2);
  90. for s = 1:nS
  91. data = datax{s};
  92. data(:,4) = mean(data(:,4:end), 2);
  93. data(:,5:end) = [];
  94. [~, h] = sort(data(:,4));
  95. data = data(h,:);
  96. N = size(data,1);
  97. iLow = 1:ceil(N/3);
  98. iHigh = (ceil(2*N/3)+1):N;
  99. % ========== FIRST TERCILE ===============
  100. sub = data(iLow,:);
  101. iaf_mean_terciles(s,1) = mean(sub(:,4));
  102. stim_pres = sub(sub(:,1)==1,:);
  103. stim_abs = sub(sub(:,1)==0,:);
  104. nPres = size(stim_pres,1);
  105. nAbs = size(stim_abs,1);
  106. hit = sum(stim_pres(:,1)==stim_pres(:,2)) / nPres;
  107. fa = sum(stim_abs(:,1)~=stim_abs(:,2)) / nAbs;
  108. if hit == 0, hit = 0.5/nPres; elseif hit == 1, hit = (nPres-0.5)/nPres; end
  109. if fa == 0, fa = 0.5/nAbs; elseif fa == 1, fa = (nAbs-0.5)/nAbs; end
  110. d(s,1) = norminv(hit) - norminv(fa);
  111. c(s,1) = -(norminv(hit) + norminv(fa)) / 2;
  112. accuracy(s,1) = mean(sub(:,1) == sub(:,2));
  113. % ========== THIRD TERCILE ==============
  114. sub = data(iHigh,:);
  115. iaf_mean_terciles(s,2) = mean(sub(:,4));
  116. stim_pres = sub(sub(:,1)==1,:);
  117. stim_abs = sub(sub(:,1)==0,:);
  118. nPres = size(stim_pres,1);
  119. nAbs = size(stim_abs,1);
  120. hit = sum(stim_pres(:,1)==stim_pres(:,2)) / nPres;
  121. fa = sum(stim_abs(:,1)~=stim_abs(:,2)) / nAbs;
  122. if hit == 0, hit = 0.5/nPres; elseif hit == 1, hit = (nPres-0.5)/nPres; end
  123. if fa == 0, fa = 0.5/nAbs; elseif fa == 1, fa = (nAbs-0.5)/nAbs; end
  124. d(s,2) = norminv(hit) - norminv(fa);
  125. c(s,2) = -(norminv(hit) + norminv(fa)) / 2;
  126. accuracy(s,2) = mean(sub(:,1) == sub(:,2));
  127. end
  128. %% Time-resolved binning analysis revealed that the IAF effect on sensitivity
  129. %% is broadly extended over the pre-stimulus period: Bin analysis timeresolved
  130. clc,clear
  131. load('IAF_allSubjects.mat');
  132. nperms = 1000;
  133. rng('Shuffle')
  134. ntpns = size(datax{1},2) - 3;
  135. nS = numel(datax);
  136. iaf_mean_timeresolved = zeros(nS,ntpns,2);
  137. d = zeros(nS,ntpns,2);
  138. c = zeros(nS,ntpns,2);
  139. accuracy = zeros(nS,ntpns,2);
  140. for timepointi = 1:ntpns
  141. for participant = 1:nS
  142. data = datax{participant};
  143. data(:,4) = data(:, 3+timepointi);
  144. data(:,5:end)= [];
  145. [~, h] = sort(data(:,4));
  146. data_real = data(h,:);
  147. N = size(data_real,1);
  148. iL = 1:ceil(N/3);
  149. data_low_alpha = data_real(iL,:);
  150. stim_pres = data_low_alpha(data_low_alpha(:,1)==1,:);
  151. hit = (sum(stim_pres(:,1) == stim_pres(:,2)))/(length(stim_pres));
  152. if hit == 1, hit = (length(stim_pres) - 0.5)/length(stim_pres); end
  153. if hit == 0, hit = 0.5/length(stim_pres); end
  154. stim_abs = data_low_alpha(data_low_alpha(:,1)==0,:);
  155. fa = (sum(stim_abs(:,1) ~= stim_abs(:,2)))/(length(stim_abs));
  156. if fa == 0, fa = 0.5/length(stim_abs); end
  157. d(participant,timepointi,1) = norminv(hit) - norminv(fa);
  158. c(participant,timepointi,1) = -(norminv(hit) + norminv(fa))/2;
  159. accuracy(participant,timepointi,1) = sum(data_low_alpha(:,1)==data_low_alpha(:,2))/length(data_low_alpha);
  160. iH = (ceil(2*N/3)+1):N;
  161. data_hig_alpha = data_real(iH,:);
  162. stim_pres = data_hig_alpha(data_hig_alpha(:,1)==1,:);
  163. hit = (sum(stim_pres(:,1) == stim_pres(:,2)))/(length(stim_pres));
  164. if hit == 1, hit = (length(stim_pres) - 0.5)/length(stim_pres); end
  165. if hit == 0, hit = 0.5/length(stim_pres); end
  166. stim_abs = data_hig_alpha(data_hig_alpha(:,1)==0,:);
  167. fa = (sum(stim_abs(:,1) ~= stim_abs(:,2)))/(length(stim_abs));
  168. if fa == 0, fa = 0.5/length(stim_abs); end
  169. d(participant,timepointi,2) = norminv(hit) - norminv(fa);
  170. c(participant,timepointi,2) = -(norminv(hit) + norminv(fa))/2;
  171. accuracy(participant,timepointi,2) = sum(data_hig_alpha(:,1)==data_hig_alpha(:,2))/length(data_hig_alpha);
  172. end
  173. end
  174. d = d; % d, accuracy, c
  175. d_t_t_lowalpha = mean(d(:,:,1));
  176. d_t_t_highalpha = mean(d(:,:,2));
  177. load('timeperiod_iaf.mat')
  178. x = timeperiod;
  179. sig_real = zeros(ntpns,1);
  180. t_real = zeros(ntpns,1);
  181. for timi = 1:ntpns
  182. lowalpha = d(:,timi,1);
  183. highalpha = d(:,timi,2);
  184. [sig_real(timi),~,~,e] = ttest(lowalpha,highalpha);
  185. t_real(timi) = e.tstat;
  186. end
  187. t_real(~sig_real) = 0;
  188. islands = bwconncomp(t_real);
  189. clustsizes = islands.PixelIdxList;
  190. sum_t = zeros(length(clustsizes),1);
  191. for clusti = 1:length(clustsizes)
  192. ii = clustsizes{clusti};
  193. sum_t(clusti) = sum(abs(t_real(ii(1):ii(end))));
  194. end
  195. sig_fake = zeros(ntpns,nperms);
  196. t_fake = zeros(ntpns,nperms);
  197. max_cluster_sizes = zeros(nperms,1);
  198. for perm = 1:nperms
  199. lowalpha = d(:,:,1);
  200. highalpha = d(:,:,2);
  201. randorder = randperm(nS);
  202. randorder_1 = rem(randorder,2);
  203. lowalpha_fake = zeros(size(lowalpha));
  204. highalpha_fake = zeros(size(highalpha));
  205. for part = 1:nS
  206. if randorder_1(part)==1
  207. lowalpha_fake(part,:) = lowalpha(part,:);
  208. highalpha_fake(part,:) = highalpha(part,:);
  209. else
  210. lowalpha_fake(part,:) = highalpha(part,:);
  211. highalpha_fake(part,:) = lowalpha(part,:);
  212. end
  213. end
  214. for timi = 1:ntpns
  215. [sig_fake(timi,perm),~,~,e] = ttest(lowalpha_fake(:,timi),highalpha_fake(:,timi));
  216. t_fake(timi,perm) = e.tstat;
  217. end
  218. t_fake(~sig_fake(:,perm),perm) = 0;
  219. islands = bwconncomp(t_fake(:,perm));
  220. tempclustsizes = islands.PixelIdxList;
  221. sum_t_fake = zeros(max([length(tempclustsizes),1]),1);
  222. if ~isempty(tempclustsizes)
  223. for clusti = 1:length(tempclustsizes)
  224. ii = tempclustsizes{clusti};
  225. sum_t_fake(clusti) = sum(abs(t_fake(ii(1):ii(end),perm)));
  226. end
  227. end
  228. max_cluster_sizes(perm) = max(sum_t_fake);
  229. end
  230. p_value_cluster = zeros(length(clustsizes),1);
  231. S = sort(max_cluster_sizes);
  232. for clusti = 1:length(clustsizes)
  233. p_value_cluster(clusti) = (nperms - dsearchn(S,sum_t(clusti)')) / nperms;
  234. end
  235. %% IAF is higher in correct vs. incorrect trials.
  236. clc,clear
  237. load('IAF_allSubjects.mat');
  238. nS = length(datax);
  239. iaf = zeros(nS,2);
  240. for participant = 1:nS
  241. data = datax{participant};
  242. data(:,4) = mean(data(:,4:end),2);
  243. data(:,5:end) = [];
  244. accuracy = (data(:,1) == data(:,2));
  245. iaf_acc = data(accuracy ,4);
  246. iaf_inc = data(~accuracy,4);
  247. iaf(participant,1) = mean(iaf_acc);
  248. iaf(participant,2) = mean(iaf_inc);
  249. end
  250. %% Trial-by-trial fluctuations in IAF predict the accuracy of perceptual report.
  251. clc,clear
  252. load('IAF_allSubjects.mat');
  253. rng shuffle
  254. nperms = 2000;
  255. nS = length(datax);
  256. b_perms = zeros(nperms,1);
  257. b_z = zeros(nS,1);
  258. b = zeros(nS,1);
  259. for participant = 1:nS
  260. participant
  261. data = datax{participant};
  262. data(:,4) = mean(data(:,4:end),2);
  263. data(:,5:end) = [];
  264. data(:,4) = zscore(data(:,4));
  265. accuracy = (data(:,1) == data(:,2));
  266. X = [ones(length(data),1), data(:,4)];
  267. t = (X'*X)\(X'*accuracy);
  268. b(participant) = t(2);
  269. datat = data;
  270. for permi = 1:nperms
  271. datat(:,4) = Shuffle(data(:,4));
  272. Xp = [ones(length(data),1), datat(:,4)];
  273. tp = (Xp'*Xp)\(Xp'*accuracy);
  274. b_perms(permi) = tp(2);
  275. end
  276. b_z(participant) = (b(participant) - mean(b_perms)) / std(b_perms);
  277. end
  278. %% Alpha phase effects on perceptual sensitivity are moderated by IAF.
  279. clc,clear
  280. rng('Shuffle')
  281. load('timeperiod_phase.mat');
  282. NT = numel(timeperiod);
  283. which_group = 'below'; % 'below' | 'above'
  284. switch which_group
  285. case 'below'
  286. load('PHASE_below.mat');
  287. datax = data_phase_below;
  288. group = 1:numel(datax);
  289. case 'above'
  290. load('PHASE_above.mat');
  291. datax = data_phase_above;
  292. group = 1:numel(datax);
  293. end
  294. acc_phase = zeros(length(group), NT, 2);
  295. for participant = 1:length(group)
  296. X = datax{group(participant) };
  297. acc = (X(:,1) == X(:,2));
  298. for t = 1:NT
  299. phase_degree = rad2deg( X(:, t+3) );
  300. numBins = 2;
  301. binEdges = linspace(-180, 180, numBins+1);
  302. binIndices = zeros(size(phase_degree));
  303. for i = 1:numBins
  304. binIndices( phase_degree >= binEdges(i) & phase_degree <= binEdges(i+1) ) = i;
  305. end
  306. peak = (binIndices==2);
  307. trough = (binIndices==1);
  308. acc_phase(participant,t,1) = sum(acc(peak)) / sum(peak);
  309. acc_phase(participant,t,2) = sum(acc(trough)) / sum(trough);
  310. end
  311. end
  312. sign = zeros(NT,1);
  313. tval = zeros(NT,1);
  314. for t = 1:NT
  315. [sign(t),~,~,st] = ttest(acc_phase(:,t,1), acc_phase(:,t,2));
  316. tval(t) = st.tstat;
  317. end
  318. tval(sign<1) = 0;
  319. CC = bwconncomp(tval);
  320. clustsizes = CC.PixelIdxList;
  321. sum_t = zeros(numel(clustsizes),1);
  322. for c = 1:numel(clustsizes)
  323. idx = clustsizes{c};
  324. sum_t(c) = sum(abs(tval(idx(1):idx(end))));
  325. end
  326. nperms = 1000;
  327. sig_fake = zeros(NT,nperms);
  328. t_fake = zeros(NT,nperms);
  329. max_cluster_sizes = zeros(nperms,1);
  330. for perm = 1:nperms
  331. lowalpha = acc_phase(:,:,1);
  332. highalpha = acc_phase(:,:,2);
  333. randorder = randperm(size(acc_phase,1));
  334. randorder_1 = rem(randorder,2);
  335. lowalpha_fake = zeros(size(lowalpha));
  336. highalpha_fake = zeros(size(highalpha));
  337. for s = 1:size(acc_phase,1)
  338. if randorder_1(s)==1
  339. lowalpha_fake(s,:) = lowalpha(s,:);
  340. highalpha_fake(s,:) = highalpha(s,:);
  341. else
  342. lowalpha_fake(s,:) = highalpha(s,:);
  343. highalpha_fake(s,:) = lowalpha(s,:);
  344. end
  345. end
  346. for t = 1:NT
  347. [sig_fake(t,perm),~,~,e] = ttest(lowalpha_fake(:,t), highalpha_fake(:,t));
  348. t_fake(t,perm) = e.tstat;
  349. end
  350. t_fake(~sig_fake(:,perm),perm) = 0;
  351. CCp = bwconncomp(t_fake(:,perm));
  352. tmpMass = zeros(max([CCp.NumObjects,1]),1);
  353. if CCp.NumObjects>0
  354. for c = 1:CCp.NumObjects
  355. idx = CCp.PixelIdxList{c};
  356. tmpMass(c) = sum(abs(t_fake(idx(1):idx(end),perm)));
  357. end
  358. else
  359. tmpMass(1) = 0;
  360. end
  361. max_cluster_sizes(perm) = max(tmpMass);
  362. end
  363. p_value_cluster = zeros(numel(clustsizes),1);
  364. mx = sort(max_cluster_sizes);
  365. for c = 1:numel(clustsizes)
  366. p_value_cluster(c) = (nperms - dsearchn(mx, sum_t(c))) / nperms;
  367. end
  368. %% Trial-by-trial fluctuations in alpha phase predict perceptual sensitivity only in lower IAF trials.
  369. clc,clear
  370. rng shuffle
  371. load('PHASE_all.mat');
  372. load('IAF_allSubjects.mat')
  373. load('timeperiod_phase.mat')
  374. phase2analyse = 5;
  375. phaseidx = dsearchn(timeperiod', phase2analyse');
  376. phaseidx = unique(phaseidx);
  377. nS = numel(datax);
  378. iaf_coeff = zeros(nS,1);
  379. pha_coeff = zeros(nS,1);
  380. iaf_pha_c = zeros(nS,1);
  381. for participant = 1:nS
  382. X_iaf = datax{participant};
  383. accuracy = (X_iaf(:,1) == X_iaf(:,2)); % 0/1
  384. iaf = zscore( mean(X_iaf(:,4:end),2) );
  385. X_phase = data_phase_all{participant};
  386. phase = X_phase(:, phaseidx(1)+3);
  387. phase_degree = rad2deg(phase);
  388. numBins = 2;
  389. binEdges = linspace(-180, 180, numBins + 1);
  390. binIndices = zeros(size(phase_degree));
  391. for i = 1:numBins
  392. binIndices( phase_degree >= binEdges(i) & phase_degree <= binEdges(i+1) ) = i;
  393. end
  394. peak = (binIndices == 2);
  395. X = [ones(size(X_phase,1),1), iaf, double(peak), iaf .* double(peak)];
  396. t = (X'*X)\(X'*accuracy);
  397. iaf_coeff(participant) = t(2);
  398. pha_coeff(participant) = t(3);
  399. iaf_pha_c(participant) = t(4);
  400. iaf_coeff_p = zeros(1000,1);
  401. pha_coeff_p = zeros(1000,1);
  402. iaf_pha_p = zeros(1000,1);
  403. for permi = 1:1000
  404. acc_perm = Shuffle(accuracy);
  405. tperm = (X'*X)\(X'*acc_perm);
  406. iaf_coeff_p(permi) = tperm(2);
  407. pha_coeff_p(permi) = tperm(3);
  408. iaf_pha_p(permi) = tperm(4);
  409. end
  410. iaf_coeff(participant) = (iaf_coeff(participant) - mean(iaf_coeff_p)) ./ std(iaf_coeff_p);
  411. pha_coeff(participant) = (pha_coeff(participant) - mean(pha_coeff_p)) ./ std(pha_coeff_p);
  412. iaf_pha_c(participant) = (iaf_pha_c(participant) - mean(iaf_pha_p)) ./ std(iaf_pha_p);
  413. end
  414. %% Correct vs. incorrect decisions are associated with a different phase angle only in the low IAF group
  415. clc,clear
  416. rng Shuffle
  417. load('timeperiod_phase.mat')
  418. T = numel(timeperiod);
  419. which_group = 'below'; % 'below' | 'above'
  420. switch which_group
  421. case 'below'
  422. load('PHASE_below.mat');
  423. datax = data_phase_below;
  424. group = 1:numel(datax);
  425. case 'above'
  426. load('PHASE_above.mat');
  427. datax = data_phase_above;
  428. group = 1:numel(datax);
  429. end
  430. circolar_mean = zeros(numel(datax), T, 2);
  431. for p = 1:numel(datax)
  432. data = datax{p};
  433. accuracy = (data(:,1) == data(:,2));
  434. for t = 1:T
  435. circolar_mean(p,t,1) = circ_mean(data( accuracy==1, t+3)); % Correct
  436. circolar_mean(p,t,2) = circ_mean(data( accuracy==0, t+3)); % Incorrect
  437. end
  438. end
  439. p_obs = zeros(T,1);
  440. F_obs = zeros(T,1);
  441. for t = 1:T
  442. [p_obs(t), tbl] = circ_wwtest(circolar_mean(:,t,1), circolar_mean(:,t,2));
  443. F_obs(t) = tbl{2,5};
  444. end
  445. is_sig = (p_obs < 0.05);
  446. CC = bwconncomp(is_sig);
  447. clusters_obs = CC.PixelIdxList;
  448. mass_obs = zeros(numel(clusters_obs),1);
  449. for c = 1:numel(clusters_obs)
  450. idx = clusters_obs{c};
  451. mass_obs(c) = sum(F_obs(idx));
  452. end
  453. nperms = 1000;
  454. T = size(circolar_mean,2);
  455. nSubj = size(circolar_mean,1);
  456. max_mass = zeros(nperms,1);
  457. for perm = 1:nperms
  458. cm_tmp = circolar_mean;
  459. swap_mask = false(nSubj,1);
  460. swap_mask(randperm(nSubj, floor(nSubj/2))) = true;
  461. tmpMass = cm_tmp(swap_mask,:,1);
  462. cm_tmp(swap_mask,:,1) = cm_tmp(swap_mask,:,2);
  463. cm_tmp(swap_mask,:,2) = tmpMass;
  464. pvec = zeros(T,1); Fvec = zeros(T,1);
  465. for t = 1:T
  466. [pvec(t), tbl] = circ_wwtest(cm_tmp(:,t,1), cm_tmp(:,t,2));
  467. Fvec(t) = tbl{2,5};
  468. end
  469. is_sig_p = (pvec < 0.05);
  470. CCp = bwconncomp(is_sig_p);
  471. if CCp.NumObjects==0
  472. max_mass(perm) = 0;
  473. else
  474. masses = zeros(CCp.NumObjects,1);
  475. for c = 1:CCp.NumObjects
  476. ii = CCp.PixelIdxList{c};
  477. masses(c) = sum(Fvec(ii));
  478. end
  479. max_mass(perm) = max(masses);
  480. end
  481. end
  482. p_value_cluster = nan(numel(mass_obs),1);
  483. sort_max = sort(max_mass);
  484. for c = 1:numel(mass_obs)
  485. p_value_cluster(c) = (nperms - dsearchn(sort_max, mass_obs(c))) / nperms;
  486. end
  487. %% Alpha-phase clustering increases for correct responses only in low IAF individuals (Time-resolved)
  488. clc, clear
  489. rng('Shuffle')
  490. load('timeperiod_phase.mat')
  491. NT = numel(timeperiod);
  492. which_group = 'below'; % 'below' | 'above'
  493. switch which_group
  494. case 'below'
  495. load('PHASE_below.mat');
  496. datax = data_phase_below;
  497. group = 1:numel(datax);
  498. case 'above'
  499. load('PHASE_above.mat');
  500. datax = data_phase_above;
  501. group = 1:numel(datax);
  502. end
  503. no_perm = 500;
  504. itpc = zeros(length(datax), NT, 2);
  505. for participant = 1:length(datax)
  506. participant
  507. data = datax{participant};
  508. accuracy = (data(:,1) == data(:,2));
  509. nCorr = sum(accuracy==1);
  510. nErr = sum(accuracy==0);
  511. nMin = min(nCorr,nErr);
  512. for t = 1:NT
  513. itpc_s = zeros(no_perm,1);
  514. for r = 1:no_perm
  515. temp = Shuffle(find(accuracy==1));
  516. temp = temp(1:nMin);
  517. itpc_s(r,1) = abs(mean(exp(1i*data(temp , t+3))));
  518. end
  519. itpc(participant,t,1) = mean(itpc_s);
  520. itpc(participant,t,2) = abs(mean(exp(1i*data(accuracy==0, t+3))));
  521. end
  522. end
  523. signP = zeros(NT,1);
  524. tstat = zeros(NT,1);
  525. for t = 1:NT
  526. [~,signP(t),~,st] = ttest(itpc(:,t,1), itpc(:,t,2));
  527. tstat(t) = st.tstat;
  528. end
  529. tmask = tstat; tmask(signP>0.05) = 0;
  530. CC = bwconncomp(tmask);
  531. clists = CC.PixelIdxList;
  532. sum_t = zeros(numel(clists),1);
  533. for c = 1:numel(clists)
  534. idx = clists{c};
  535. sum_t(c) = sum(abs(tmask(idx(1):idx(end))));
  536. end
  537. nperms = 1000;
  538. sig_fake = zeros(NT,nperms);
  539. t_fake = zeros(NT,nperms);
  540. max_cluster_sizes = zeros(nperms,1);
  541. for perm = 1:nperms
  542. lowalpha = itpc(:,:,1); % Correct(bal)
  543. highalpha = itpc(:,:,2); % Incorrect
  544. randorder = randperm(size(itpc,1));
  545. randorder_1 = rem(randorder,2);
  546. lowalpha_fake = zeros(size(lowalpha));
  547. highalpha_fake = zeros(size(highalpha));
  548. for s = 1:size(itpc,1)
  549. if randorder_1(s)==1
  550. lowalpha_fake(s,:) = lowalpha(s,:);
  551. highalpha_fake(s,:) = highalpha(s,:);
  552. else
  553. lowalpha_fake(s,:) = highalpha(s,:);
  554. highalpha_fake(s,:) = lowalpha(s,:);
  555. end
  556. end
  557. for t = 1:NT
  558. [sig_fake(t,perm),~,~,e] = ttest(lowalpha_fake(:,t), highalpha_fake(:,t));
  559. t_fake(t,perm) = e.tstat;
  560. end
  561. t_fake(~sig_fake(:,perm),perm) = 0;
  562. CCp = bwconncomp(t_fake(:,perm));
  563. tmpMass = zeros(max([CCp.NumObjects,1]),1);
  564. if CCp.NumObjects>0
  565. for c = 1:CCp.NumObjects
  566. idx = CCp.PixelIdxList{c};
  567. tmpMass(c) = sum(abs(t_fake(idx(1):idx(end),perm)));
  568. end
  569. else
  570. tmpMass(1) = 0;
  571. end
  572. max_cluster_sizes(perm) = max(tmpMass);
  573. end
  574. p_value_cluster = zeros(numel(clists),1);
  575. mx = sort(max_cluster_sizes);
  576. for c = 1:numel(clists)
  577. p_value_cluster(c) = (nperms - dsearchn(mx, sum_t(c))) / nperms;
  578. end
  579. %% Alpha-phase clustering increases for correct responses only in low IAF individuals (Time-Frequency)
  580. clc, clearvars
  581. rng('shuffle');
  582. load('timeperiod_phase.mat')
  583. load('idx_group.mat')
  584. load('PHASE_all.mat');
  585. below_median_indices = idx_group(:,1);
  586. above_median_indices = idx_group(:,2);
  587. eegfolder = ''%path
  588. group_mode = 'below';
  589. switch group_mode
  590. case 'below'
  591. subj_idx = below_median_indices;
  592. case 'above'
  593. subj_idx = above_median_indices;
  594. end
  595. EEG_struct = dir(fullfile(eegfolder, '*.set'));
  596. EEG_files = {EEG_struct.name}';
  597. EEG_files_sel = EEG_files(subj_idx);
  598. PHASE_files_sel = data_phase_all(subj_idx);
  599. elec_list_all = readcell('electrodes_to_analyze.xlsx');
  600. elec_list = elec_list_all(subj_idx);
  601. EEG = pop_loadset('filename', EEG_files_sel{1}, 'filepath', eegfolder);
  602. EEG = eeg_checkset(EEG);
  603. freqs2use = linspace(2,50,50);
  604. tvec = -1.5:1/EEG.srate:1.5;
  605. half_wavelet = (length(tvec)-1)/2;
  606. range_cycles = [3 11];
  607. s = logspace(log10(range_cycles(1)),log10(range_cycles(end)),numel(freqs2use)) ./ (2*pi*freqs2use);
  608. n_wavelet = numel(tvec);
  609. cmwX_template = cell(numel(freqs2use),1);
  610. for fi = 1:numel(freqs2use)
  611. wavelet = exp(1i*2*pi*freqs2use(fi).*tvec) .* exp(-tvec.^2./(2*s(fi)^2));
  612. cmwX_template{fi} = wavelet;
  613. end
  614. nSubj = numel(EEG_files_sel);
  615. NT = numel(timeperiod);
  616. itpc = zeros(nSubj, numel(freqs2use), NT, 2);
  617. for s = 1:nSubj
  618. s
  619. data = PHASE_files_sel{s};
  620. accuracy = (data(:,1) == data(:,2));
  621. eeg_file = fullfile(eegfolder, EEG_files_sel{s});
  622. EEG = pop_loadset('filename', EEG_files_sel{s}, 'filepath', eegfolder);
  623. EEG = eeg_checkset(EEG);
  624. elec_name = elec_list{s};
  625. chan_idx = find(strcmp({EEG.chanlocs.labels}, elec_name));
  626. n_data = size(EEG.data,2)*size(EEG.data,3);
  627. n_conv = n_wavelet + n_data - 1;
  628. TF_phase = zeros(numel(freqs2use), size(EEG.data,2), size(EEG.data,3));
  629. chandat = reshape(EEG.data(chan_idx,:,:), 1, []);
  630. dataX = fft(chandat, n_conv);
  631. for fi = 1:numel(freqs2use)
  632. wavelet = cmwX_template{fi};
  633. cmw = fft(wavelet, n_conv);
  634. cmw = cmw ./ max(cmw);
  635. as = ifft(cmw .* dataX);
  636. as = as(half_wavelet+1:end-half_wavelet);
  637. as = reshape(as, size(EEG.data,2), size(EEG.data,3));
  638. TF_phase(fi,:,:) = angle(as);
  639. end
  640. nCorr = sum(accuracy==1);
  641. nErr = sum(accuracy==0);
  642. nMin = min(nCorr,nErr);
  643. time2saveidx = dsearchn(EEG.times', [-800 200]');
  644. itpc_s = zeros(numel(freqs2use), size(TF_phase,2), 500);
  645. corr_idx = find(accuracy==1);
  646. for subs = 1:500
  647. temp = Shuffle(corr_idx);
  648. temp = temp(1:nMin);
  649. for fi = 1:numel(freqs2use)
  650. itpc_s(fi,:,subs) = abs(mean(exp(1i*TF_phase(fi,:,temp)),3));
  651. end
  652. end
  653. itpc(s,:,:,1) = mean(itpc_s(:, time2saveidx(1):time2saveidx(2), :), 3);
  654. err_idx = (accuracy==0);
  655. for fi = 1:numel(freqs2use)
  656. itpc(s,fi,:,2) = abs(mean(exp(1i*TF_phase(fi, time2saveidx(1):time2saveidx(2), err_idx)), 3));
  657. end
  658. end
  659. itpc_corr = itpc(:,:,:,1);
  660. itpc_incorr = itpc(:,:,:,2);
  661. itpc_diff = itpc_corr - itpc_incorr;
  662. npart = size(itpc_diff,1);
  663. pval = 0.05/2;
  664. zval = abs(norminv(pval));
  665. n_permutes = 1000;
  666. permmaps = zeros(n_permutes, numel(freqs2use), numel(timeperiod));
  667. tf3d = {itpc_corr, itpc_incorr};
  668. for permi = 1:n_permutes
  669. group_temp = zeros(numel(freqs2use), numel(timeperiod));
  670. randorder = randperm(npart);
  671. randorder_1 = rem(randorder,2)+1;
  672. randorder_2 = rem(randorder_1,2)+1;
  673. for subj = 1:length(randorder_1)
  674. A = tf3d{randorder_1(subj)}(subj,:,:);
  675. B = tf3d{randorder_2(subj)}(subj,:,:);
  676. group_temp = group_temp + squeeze(B(1,:,:)-A(1,:,:));
  677. end
  678. permmaps(permi,:,:) = group_temp./subj;
  679. end
  680. mean_h0 = squeeze(mean(permmaps,1));
  681. std_h0 = squeeze(std(permmaps,0,1));
  682. zmap = (squeeze(nanmean(itpc_diff,1)) - mean_h0) ./ std_h0;
  683. zmap(abs(zmap)<zval) = 0;
  684. max_cluster_sizes = zeros(1,n_permutes);
  685. for permi = 1:n_permutes
  686. threshimg = squeeze(permmaps(permi,:,:));
  687. threshimg = (threshimg-mean_h0) ./ std_h0;
  688. threshimg(abs(threshimg)<zval) = 0;
  689. islands = bwconncomp(threshimg);
  690. if numel(islands.PixelIdxList)>0
  691. tempclustsizes = cellfun(@length, islands.PixelIdxList);
  692. max_cluster_sizes(permi) = max(tempclustsizes);
  693. end
  694. end
  695. mx = sort(max_cluster_sizes);
  696. islands = bwconncomp(zmap);
  697. nClust = islands.NumObjects;
  698. p_cluster = zeros(nClust,1);
  699. for c = 1:nClust
  700. this_size = numel(islands.PixelIdxList{c});
  701. rank_idx = dsearchn(mx', this_size);
  702. p_cluster(c) = 1-(rank_idx/n_permutes);
  703. if p_cluster(c) >= 0.05
  704. zmap(islands.PixelIdxList{c}) = 0;
  705. end
  706. end
  707. %% SI: No significant differences observed in behavioural performance between first and third power terciles
  708. clc; clearvars;
  709. rng('shuffle');
  710. eegfolder = ''%path
  711. load('AllSubjects.mat')
  712. cd(eegfolder);
  713. EEG_struct = dir(fullfile(eegfolder, '*.set'));
  714. EEG_files = {EEG_struct.name}';
  715. elec_to_select = readcell('electrodes_to_analyze.xlsx');
  716. iaf_to_select = readcell('peak_to_analyze.xlsx');
  717. freqs2use = linspace(2,50,50);
  718. nSubj = numel(EEG_files);
  719. d = zeros(nSubj,2);
  720. c = zeros(nSubj,2);
  721. for s = 1:nSubj
  722. filename = EEG_files{s};
  723. EEG = pop_loadset('filename', filename, 'filepath', eegfolder);
  724. EEG = eeg_checkset(EEG);
  725. EEG.data = diff(EEG.data,1,2);
  726. elec2anal = elec_to_select{s};
  727. chan_idx = find(strcmpi({EEG.chanlocs.labels}, elec2anal));
  728. TF_abs = TF_IAF(EEG.data, EEG.srate, chan_idx); % [F x T x trials]
  729. mean_pow = mean(TF_abs,3);
  730. basewin = [-3200 -2800];
  731. baseidx = round(dsearchn(EEG.times', basewin'));
  732. bslpow = mean(mean_pow(:, baseidx(1):baseidx(2)), 2);
  733. BSLpow = repmat(bslpow, [1, size(TF_abs,2), size(TF_abs,3)]);
  734. ampl_all = 10*log10(TF_abs ./ BSLpow);
  735. iaf2select = iaf_to_select{s};
  736. iafrange2select = dsearchn(freqs2use', iaf2select');
  737. time2select = [-800 -100];
  738. timerange2select = dsearchn(EEG.times', [time2select(1) time2select(2)]');
  739. subpow = ampl_all(iafrange2select, timerange2select(1):timerange2select(2), :);
  740. meanampl = squeeze(mean(subpow, 2));
  741. meanampl = meanampl(:);
  742. [~, sorted_alpha_ampl] = sort(meanampl);
  743. nTrials = numel(sorted_alpha_ampl);
  744. n1 = ceil(nTrials/3);
  745. n3start = ceil(2*nTrials/3);
  746. first_tercile = sorted_alpha_ampl(1:n1);
  747. third_tercile = sorted_alpha_ampl(n3start:end);
  748. data = databehx{s};
  749. data = data(:,1:2);
  750. data_low_alpha = data(first_tercile,:);
  751. stim_pres = data_low_alpha(data_low_alpha(:,1)==1,:);
  752. hit = sum(stim_pres(:,1)==stim_pres(:,2)) / size(stim_pres,1);
  753. if hit==1, hit = (size(stim_pres,1)-0.5)/size(stim_pres,1); end
  754. if hit==0, hit = 0.5/size(stim_pres,1); end
  755. stim_abs = data_low_alpha(data_low_alpha(:,1)==0,:);
  756. fa = sum(stim_abs(:,1)~=stim_abs(:,2)) / size(stim_abs,1);
  757. if fa==0, fa = 0.5/size(stim_abs,1); end
  758. d(s,1) = norminv(hit) - norminv(fa);
  759. c(s,1) = -(norminv(hit) + norminv(fa))/2;
  760. data_high_alpha = data(third_tercile,:);
  761. stim_pres = data_high_alpha(data_high_alpha(:,1)==1,:);
  762. hit = sum(stim_pres(:,1)==stim_pres(:,2)) / size(stim_pres,1);
  763. if hit==1, hit = (size(stim_pres,1)-0.5)/size(stim_pres,1); end
  764. if hit==0, hit = 0.5/size(stim_pres,1); end
  765. stim_abs = data_high_alpha(data_high_alpha(:,1)==0,:);
  766. fa = sum(stim_abs(:,1)~=stim_abs(:,2)) / size(stim_abs,1);
  767. if fa==0, fa = 0.5/size(stim_abs,1); end
  768. d(s,2) = norminv(hit) - norminv(fa);
  769. c(s,2) = -(norminv(hit)+norminv(fa))/2;
  770. end
  771. [~,p_d,~,st_d] = ttest(d(:,1), d(:,2));
  772. bf_d = bf.ttest(d(:,1), d(:,2));
  773. [~,p_c,~,st_c] = ttest(c(:,1), c(:,2));
  774. bf_c = bf.ttest(c(:,1), c(:,2));
  775. %% SI: Correct and Incorrect trials are not characterized by difference in oscillatory amplitude.
  776. %% SI: Trial-by-trial fluctuations in alpha power do not account for perceptual accuracy.
  777. clc; clearvars;
  778. rng('shuffle');
  779. eegfolder = ''%path
  780. D = dir(eegfolder);
  781. folder_direeg = struct2cell(D)';
  782. folder_direeg = folder_direeg(3:end,1);
  783. folder_direeg = folder_direeg(2:2:end);
  784. all_idx = 1:116;
  785. group = all_idx;
  786. freqs2use = linspace(2,50,50);
  787. iaf_to_select = readmatrix('peak_to_analyze.xlsx');
  788. elec_to_select= readcell('electrodes_to_analyze.xlsx');
  789. load('IAF_allSubjects.mat');
  790. nSubj = numel(group);
  791. ampl = cell(nSubj,2);
  792. b_z_pow = zeros(nSubj,1);
  793. iaf_z_pow = zeros(nSubj,1);
  794. for pi = 1:nSubj
  795. subj_id = group(pi);
  796. data = datax{subj_id};
  797. accuracy = (data(:,1) == data(:,2));
  798. iaf_p = zscore(mean(data(:,4:end), 2));
  799. cd(eegfolder);
  800. filename = folder_direeg{subj_id};
  801. EEG = pop_loadset('filename', filename);
  802. EEG = eeg_checkset(EEG);
  803. EEG.data = diff(EEG.data, 1, 2);
  804. iaf_part = iaf_to_select(subj_id);
  805. elec_name = elec_to_select{subj_id};
  806. chan_idx = find(strcmpi({EEG.chanlocs.labels}, elec_name));
  807. iafidx = dsearchn(freqs2use', iaf_part);
  808. TF_amp = TF_IAF(EEG.data, EEG.srate, chan_idx);
  809. time2save = [-800 -100];
  810. time2saveidx = dsearchn(EEG.times', time2save');
  811. basewin = [-3200 -2800];
  812. baseidx = round(dsearchn(EEG.times', basewin'));
  813. mean_pow_corr = mean(TF_amp(:,:,accuracy), 3);
  814. bslpow_CORR = mean(mean_pow_corr(:, baseidx(1):baseidx(2)), 2);
  815. mean_pow_incorr = mean(TF_amp(:,:,accuracy==0), 3);
  816. bslpow_INCORR = mean(mean_pow_incorr(:, baseidx(1):baseidx(2)), 2);
  817. ampl{pi,1} = 10*log10( mean(TF_amp(:, time2saveidx(1):time2saveidx(2), accuracy), 3) ./ bslpow_CORR );
  818. ampl{pi,2} = 10*log10( mean(TF_amp(:, time2saveidx(1):time2saveidx(2), accuracy==0),3) ./ bslpow_INCORR );
  819. mean_pow_all = mean(TF_amp, 3);
  820. bslpow_all = mean(mean_pow_all(:, baseidx(1):baseidx(2)), 2);
  821. BSLpow = repmat(bslpow_all, [1, size(TF_amp,2), size(TF_amp,3)]);
  822. powtrialbytrial = TF_amp ./ BSLpow;
  823. ampl2use = squeeze( zscore( mean(powtrialbytrial(iafidx, time2saveidx(1):time2saveidx(2), :), 2) ) );
  824. ampl2use = ampl2use(:);
  825. X = [ones(length(ampl2use),1), ampl2use, iaf_p];
  826. beta = (X' * X) \ (X' * accuracy);
  827. b_pow = beta(2);
  828. b_iaf = beta(3);
  829. nPermReg = 2000;
  830. b_perms_ampl = zeros(nPermReg,1);
  831. b_perms_iaf = zeros(nPermReg,1);
  832. for permi = 1:nPermReg
  833. rp = randperm(length(ampl2use));
  834. pow_r = ampl2use(rp);
  835. iaf_r = iaf_p(rp);
  836. Xp = [ones(length(pow_r),1), pow_r, iaf_r];
  837. beta_p = (Xp' * Xp) \ (Xp' * accuracy);
  838. b_perms_ampl(permi) = beta_p(2);
  839. b_perms_iaf(permi) = beta_p(3);
  840. end
  841. b_z_pow(pi) = (b_pow - mean(b_perms_ampl)) ./ std(b_perms_ampl);
  842. iaf_z_pow(pi) = (b_iaf - mean(b_perms_iaf)) ./ std(b_perms_iaf);
  843. end
  844. [~,p_b,~,st_b] = ttest(b_z_pow);
  845. bf_b = bf.ttest(b_z_pow);
  846. [~,p_i,~,st_i] = ttest(iaf_z_pow);
  847. bf_i = bf.ttest(iaf_z_pow);
  848. [F,T] = size(ampl{1,1});
  849. correct_value = zeros(nSubj,F,T);
  850. incorrect_value = zeros(nSubj,F,T);
  851. for i = 1:nSubj
  852. correct_value(i,:,:) = ampl{i,1};
  853. incorrect_value(i,:,:) = ampl{i,2};
  854. end
  855. correct_responses = squeeze(mean(correct_value,1)); % [F x T]
  856. incorrect_responses = squeeze(mean(incorrect_value,1)); % [F x T]
  857. difference_matrix = correct_responses - incorrect_responses;
  858. pval = 0.05/2;
  859. zval = abs(norminv(pval));
  860. time2save = [-800 -100];
  861. time2saveidx = dsearchn(EEG.times', time2save');
  862. timeperiod = EEG.times(time2saveidx(1):time2saveidx(2));
  863. num_zeros = nSubj/2;
  864. num_ones = nSubj/2;
  865. vector = [zeros(1,num_zeros), ones(1,num_ones)] + 1;
  866. meanamplcorr = {correct_value, incorrect_value};
  867. nPermTF = 1000;
  868. difference_matrix_perm = zeros(nPermTF,F,T);
  869. for permi = 1:nPermTF
  870. v = vector(randperm(nSubj));
  871. sv = 3 - v;
  872. corrtemp = zeros(F,T);
  873. incorrtemp = zeros(F,T);
  874. for part = 1:nSubj
  875. corrtemp = corrtemp + squeeze(meanamplcorr{v(part)} (part,:,:));
  876. incorrtemp = incorrtemp + squeeze(meanamplcorr{sv(part)}(part,:,:));
  877. end
  878. difference_matrix_perm(permi,:,:) = (corrtemp - incorrtemp) ./ nSubj;
  879. end
  880. mean_h0 = squeeze(mean(difference_matrix_perm,1));
  881. std_h0 = squeeze(std(difference_matrix_perm,[],1));
  882. zmap = (difference_matrix - mean_h0) ./ std_h0;
  883. zmap(abs(zmap) < zval) = 0;
  884. max_cluster_sizes = zeros(1, nPermTF);
  885. for permi = 1:nPermTF
  886. thr = squeeze(difference_matrix_perm(permi,:,:));
  887. thr = (thr - mean_h0) ./ std_h0;
  888. thr(abs(thr) < zval) = 0;
  889. islands = bwconncomp(thr);
  890. if numel(islands.PixelIdxList) > 0
  891. tempclustsizes = cellfun(@length, islands.PixelIdxList);
  892. max_cluster_sizes(permi) = max(tempclustsizes);
  893. else
  894. max_cluster_sizes(permi) = 0;
  895. end
  896. end
  897. mx = sort(max_cluster_sizes);
  898. islands = bwconncomp(zmap);
  899. nClust = islands.NumObjects;
  900. p_cluster = zeros(nClust,1);
  901. for c = 1:nClust
  902. this_size = numel(islands.PixelIdxList{c});
  903. rank_idx = dsearchn(mx', this_size);
  904. p_cluster(c) = 1 - (rank_idx / nPermTF);
  905. if p_cluster(c) >= 0.05
  906. zmap(islands.PixelIdxList{c}) = 0;
  907. end
  908. end
  909. %% SI: Low and Fast IAF groups do not exhibit significant differences in oscillatory amplitude.
  910. clc; clearvars;
  911. rng('shuffle');
  912. load('idx_group.mat');
  913. group_low = idx_group(:,1);
  914. group_high = idx_group(:,2);
  915. nLow = numel(group_low);
  916. nHigh = numel(group_high);
  917. iaf_to_select = readmatrix('peak_to_analyze.xlsx');
  918. elec_to_select = readcell('electrodes_to_analyze.xlsx');
  919. eegfolder = '';%path
  920. cd(eegfolder);
  921. D = dir(eegfolder);
  922. folder_direeg = struct2cell(D)';
  923. folder_direeg = folder_direeg(3:end,1);
  924. folder_direeg = folder_direeg(2:2:end);
  925. nSubj = numel(folder_direeg);
  926. freqs2use = linspace(2,50,50);
  927. EEG = pop_loadset('filename', folder_direeg{1}, 'filepath', eegfolder);
  928. EEG = eeg_checkset(EEG);
  929. time_window = [-800 -100];
  930. time2idx = dsearchn(EEG.times', time_window');
  931. timeperiod = EEG.times(time2idx(1):time2idx(2));
  932. basewin = [-3200 -2800];
  933. baseidx = round(dsearchn(EEG.times', basewin'));
  934. nFreq = numel(freqs2use);
  935. nTimeWin = numel(timeperiod);
  936. tf_ampl_all = NaN(nSubj, nFreq, nTimeWin);
  937. for s = 1:nSubj
  938. part_elec = elec_to_select{s};
  939. filename = folder_direeg{s};
  940. EEG = pop_loadset('filename', filename, 'filepath', eegfolder);
  941. EEG = eeg_checkset(EEG);
  942. EEG.data = diff(EEG.data,1,2);
  943. elec_idx = find(strcmpi({EEG.chanlocs.labels}, part_elec));
  944. TF_abs = TF_IAF(EEG.data, EEG.srate, elec_idx);
  945. bslpow = mean(mean(TF_abs(:, baseidx(1):baseidx(2), :), 2), 3);
  946. meanampl = mean(TF_abs, 3);
  947. BSLpow = repmat(bslpow, [1, size(meanampl,2)]);
  948. ampl_all = 10*log10(meanampl ./ BSLpow);
  949. tf_ampl_all(s,:,:) = ampl_all(:, time2idx(1):time2idx(2));
  950. end
  951. low_tf = squeeze(mean(tf_ampl_all(group_low,:,:), 1));
  952. high_tf = squeeze(mean(tf_ampl_all(group_high,:,:), 1));
  953. diff_tf = low_tf - high_tf;
  954. pval = 0.05/2;
  955. zval = abs(norminv(pval));
  956. nPermTF = 1000;
  957. all_idx = [group_low(:); group_high(:)];
  958. nTot = numel(all_idx);
  959. perm_maps = zeros(nPermTF, nFreq, nTimeWin);
  960. for permi = 1:nPermTF
  961. rp = randperm(nTot);
  962. fake_low_idx = all_idx(rp(1:nLow));
  963. fake_high_idx = all_idx(rp(nLow+1:end));
  964. fake_low_tf = squeeze(mean(tf_ampl_all(fake_low_idx,:,:), 1));
  965. fake_high_tf = squeeze(mean(tf_ampl_all(fake_high_idx,:,:), 1));
  966. perm_maps(permi,:,:) = fake_low_tf - fake_high_tf;
  967. end
  968. mean_h0 = squeeze(mean(perm_maps,1));
  969. std_h0 = squeeze(std(perm_maps,0,1));
  970. zmap = (diff_tf - mean_h0) ./ std_h0;
  971. zmap(abs(zmap) < zval) = 0;
  972. max_cluster_sizes = zeros(1, nPermTF);
  973. for permi = 1:nPermTF
  974. thr = squeeze(perm_maps(permi,:,:));
  975. thr = (thr - mean_h0) ./ std_h0;
  976. thr(abs(thr) < zval) = 0;
  977. islands = bwconncomp(thr);
  978. if numel(islands.PixelIdxList) > 0
  979. temp_sizes = cellfun(@length, islands.PixelIdxList);
  980. max_cluster_sizes(permi) = max(temp_sizes);
  981. else
  982. max_cluster_sizes(permi) = 0;
  983. end
  984. end
  985. mx = sort(max_cluster_sizes(:));
  986. islands = bwconncomp(zmap);
  987. nClust = islands.NumObjects;
  988. p_cluster = zeros(nClust,1);
  989. for c = 1:nClust
  990. this_size = numel(islands.PixelIdxList{c});
  991. rank_idx = dsearchn(mx, this_size);
  992. p_cluster(c) = 1 - (rank_idx / nPermTF);
  993. if p_cluster(c) >= 0.05
  994. zmap(islands.PixelIdxList{c}) = 0;
  995. end
  996. end
  997. %% SI : FFT-based method for estimating single-trial IAF confirmed the pattern
  998. %% of results observed with the instantaneous frequency approach.
  999. %% SI : The FFT-based and instantaneous frequency approaches result in comparable single-trial IAF values.
  1000. clc; clear; close all;
  1001. EEGFOLDER = '';%path
  1002. cd(EEGFOLDER);
  1003. dEEG = dir(EEGFOLDER);
  1004. EEG_files = struct2cell(dEEG)';
  1005. EEG_files = EEG_files(3:end,1);
  1006. start_from = 2;
  1007. subji = start_from:2:length(EEG_files);
  1008. dataEEG = cell(1, numel(subji));
  1009. cd(EEGFOLDER);
  1010. for p = 1:numel(subji)
  1011. idxEEG = subji(p);
  1012. filename = char(EEG_files{idxEEG});
  1013. EEG = pop_loadset('filename', filename);
  1014. EEG = eeg_checkset(EEG);
  1015. dataEEG{p} = EEG;
  1016. end
  1017. electrodes_to_analyze = readcell('electrodes_to_analyze.xlsx');
  1018. cmin = 1;
  1019. fRange = [1 40];
  1020. Fw = 11;
  1021. k = 5;
  1022. iaf_all = cell(1, size(subji,2));
  1023. god_all = cell(1, size(subji,2));
  1024. for soggetto = 1:size(subji,2)
  1025. EEG = dataEEG{soggetto};
  1026. EEG.data = diff(EEG.data,1,2);
  1027. time2anal = [-800 -100];
  1028. time2idx = dsearchn(EEG.times',time2anal');
  1029. Fs = EEG.srate;
  1030. idxElectrode = find(strcmpi({EEG.chanlocs.labels}, ...
  1031. electrodes_to_analyze{soggetto}));
  1032. w = [7 14];
  1033. ntrials = size(EEG.data,3);
  1034. iaf_p = zeros(ntrials,1);
  1035. god_p = zeros(ntrials,1);
  1036. for triali = 1:ntrials
  1037. data_colcoran = EEG.data(idxElectrode,time2idx(1):time2idx(2),triali);
  1038. [~,colcalpha] = restingIAF_natcomm(data_colcoran, 1, cmin, fRange, Fs, w, Fw, k,'nfft', EEG.srate*4);
  1039. iaf_p(triali) = colcalpha.peaks;
  1040. god_p(triali) = ~isnan(iaf_p(triali));
  1041. end
  1042. iaf_all{soggetto} = iaf_p;
  1043. god_all{soggetto} = god_p;
  1044. end
  1045. load('IAF_allSubjects.mat')
  1046. iaf = zeros(length(datax),2);
  1047. gof = zeros(length(datax),2);
  1048. nperms = 2000;
  1049. [d,c,accuracies] = deal(zeros(length(datax),2));
  1050. b = zeros(1,length(iaf_all));
  1051. b_z = zeros(1,length(iaf_all));
  1052. rho = NaN(numel(iaf_all),1);
  1053. for participant = 1:length(iaf_all)
  1054. databeh = datax{participant};
  1055. iaf_inst = mean(databeh(:,4:end),2);
  1056. databeh = databeh(:,1:3);
  1057. accuracy = databeh(:,1) == databeh(:,2);
  1058. data_iaf = iaf_all{participant};
  1059. rho(participant) = corr(data_iaf, iaf_inst,'Type','Spearman','Rows','complete');
  1060. iaf_acc = data_iaf(accuracy);
  1061. iaf_inc = data_iaf(~accuracy);
  1062. iaf(participant,1) = nanmean(iaf_acc);
  1063. iaf(participant,2) = nanmean(iaf_inc);
  1064. data_gof = god_all{participant};
  1065. gof_acc = data_gof(accuracy);
  1066. gof_inc = data_gof(~accuracy);
  1067. gof(participant,1) = mean(gof_acc);
  1068. gof(participant,2) = mean(gof_inc);
  1069. X = [ones(length(data_iaf),1), data_iaf];
  1070. todel = isnan(X(:,2));
  1071. X(todel,:) = [];
  1072. accuracy(todel) = [];
  1073. X(:,2) = zscore(X(:,2));
  1074. t = (X'*X)\(X'*accuracy);
  1075. b(participant) = t(2);
  1076. datat = X;
  1077. X_o = X;
  1078. b_perms = zeros(nperms,1);
  1079. for permi = 1:nperms
  1080. datat(:,2) = Shuffle(X_o(:,2));
  1081. Xt = [ones(length(datat),1), datat(:,2)];
  1082. tt = (Xt'*Xt)\(Xt'*accuracy);
  1083. b_perms(permi) = tt(2);
  1084. end
  1085. b_z(participant) = (b(participant)-mean(b_perms))./std(b_perms);
  1086. todel = isnan(data_iaf);
  1087. data_iaf(todel) = [];
  1088. databeh(todel,:) = [];
  1089. [~, h] = sort(data_iaf);
  1090. databeh = databeh(h,:);
  1091. data_low_alpha = databeh(1:ceil(length(data_iaf)/3),:);
  1092. data_hig_alpha = databeh(ceil(length(data_iaf)/3*2)+1:end,:);
  1093. stim_pres = data_low_alpha( data_low_alpha(:,1)==1 ,:);
  1094. hit = (sum(stim_pres(:,1) == stim_pres(:,2)))/(length(stim_pres));
  1095. stim_abs = data_low_alpha( data_low_alpha(:,1)==0 ,:);
  1096. fa = (sum(stim_abs(:,1) ~= stim_abs(:,2)))/(length(stim_abs));
  1097. if hit==0, hit=0.5/length(stim_pres); elseif hit==1, hit=(length(stim_pres)-0.5)/length(stim_pres); end
  1098. if fa==0, fa=0.5/length(stim_abs); elseif fa==1, fa=(nN-0.5)/length(stim_abs); end
  1099. d(participant,1) = norminv(hit) - norminv(fa);
  1100. c(participant,1) = -(norminv(hit) + norminv(fa))/2;
  1101. accuracies(participant,1) = sum(data_low_alpha(:,1) == data_low_alpha(:,2)) ...
  1102. / length(data_low_alpha(:,1));
  1103. stim_pres = data_hig_alpha( data_hig_alpha(:,1)==1 ,:);
  1104. hit = (sum(stim_pres(:,1) == stim_pres(:,2)))/(length(stim_pres));
  1105. stim_abs = data_hig_alpha( data_hig_alpha(:,1)==0 ,:);
  1106. fa = (sum(stim_abs(:,1) ~= stim_abs(:,2)))/(length(stim_abs));
  1107. if hit==0, hit=0.5/length(stim_pres); elseif hit==1, hit=(length(stim_pres)-0.5)/length(stim_pres); end
  1108. if fa==0, fa=0.5/length(stim_abs); elseif fa==1, fa=(nN-0.5)/length(stim_abs); end
  1109. d(participant,2) = norminv(hit) - norminv(fa);
  1110. c(participant,2) = -(norminv(hit) + norminv(fa))/2;
  1111. accuracies(participant,2) = sum(data_hig_alpha(:,1) == data_hig_alpha(:,2)) ...
  1112. / length(data_hig_alpha(:,1));
  1113. end
  1114. [a,b,cc,dd] = ttest(iaf(:,1),iaf(:,2))
  1115. [bf10a] = bf.ttest(iaf(:,1),iaf(:,2))
  1116. [a,b,cc,dd] = ttest(gof(:,1),gof(:,2))
  1117. [bf1] = bf.ttest(gof(:,1),gof(:,2))
  1118. [aa,bb,cc,ddd] = ttest(b_z)
  1119. [bf10b] = bf.ttest(b_z)
  1120. [a,b,cc,dd] = ttest(d(:,1),d(:,2))
  1121. [bf10c] = bf.ttest(d(:,1),d(:,2))
  1122. [a,b,cc,dd] = ttest(c(:,1),c(:,2))
  1123. [bf10] = bf.ttest(c(:,1),c(:,2))
  1124. [a,b,cc,dd] = ttest(accuracies(:,1),accuracies(:,2))
  1125. [bf10d] = bf.ttest(accuracies(:,1),accuracies(:,2))

Script_NC.m, no license · at the source

Overview

  1. Dipartimento di Psicologia, Università di Bologna and Centro studi e ricerche in Neuroscienze Cognitive, Università di Bologna, Cesena, Italy
  2. Universidad Antonio de Nebrija, Madrid, Spain
Institutions: Universidad Nebrija (Spain); University of Bologna (Italy)
Journal: Nature communications, volume 17, issue 1, article 3384
Dates: received 8 March 2024; accepted 13 February 2026; published online 3 March 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s41467-026-70124-9 · PMID 41776179 · PMCID PMC13065768 · OpenAlex W7133300256
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: EEG (modality), human (organism), cognitive (subfield)
Methods: Spectral & time-frequency, Preprocessing, Connectivity, Statistics, Smoothing, state filtering, decompositions, Physiology & signal measures
Keywords: Human behaviour, Perception
MeSH: Alpha Rhythm*, Perception*, Visual Perception*, Bayes Theorem, Decision Making, Electroencephalography, Female, Humans, Male, Photic Stimulation (* major topic)
Topic: Visual perception and processing mechanisms (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Citations: cited by 6 papers (Europe PMC); 84 references in the paper

Abstract

The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.

Repository

Its files are read in the Code ↔ Paper reader above, with 4 matches between paragraphs and lines of code.

OSF 6298n

License: none: the authors keep all their rights
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Languages: MATLAB (4)
Size: 20 files, 4 scripts
Software Heritage: not checked
Found in: “Code availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
  • 30 September 2026: the link answers (HTTP 200)
4 files
At the source:

Code availability statement

The paper has a code availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

  • it points to the authors' code: OSF 6298n

Read it in the paper: doi.org/10.1038/s41467-026-70124-9.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 4 scripts, each with its path and the digest of its content;
  • 4 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data availability statement

The paper has a data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

  • no repository, dataset or request procedure was recognized in it

Read it in the paper: doi.org/10.1038/s41467-026-70124-9.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 30 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 2 authors, 2 keywords, 10 MeSH terms, 82 references.

Cite

This paper

Romei, V., & Tarasi, L. (2026). Alpha frequency shapes perceptual sensitivity by modulating optimal phase likelihood. Nature communications, 17(1), 3384. https://doi.org/10.1038/s41467-026-70124-9

BibTeX

@article{romei2026alpha,
author = {Romei, Vincenzo and Tarasi, Luca},
title = {{Alpha frequency shapes perceptual sensitivity by modulating optimal phase likelihood}},
journal = {Nature communications},
year = {2026},
month = mar,
volume = {17},
number = {1},
pages = {3384},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-70124-9},
url = {https://doi.org/10.1038/s41467-026-70124-9},
pmid = {41776179},
pmcid = {PMC13065768}
}

RIS

TY - JOUR
AU - Romei, Vincenzo
AU - Tarasi, Luca
TI - Alpha frequency shapes perceptual sensitivity by modulating optimal phase likelihood
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/03/03
VL - 17
IS - 1
SP - 3384
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-70124-9
UR - https://doi.org/10.1038/s41467-026-70124-9
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-70124-9",
"type": "article-journal",
"title": "Alpha frequency shapes perceptual sensitivity by modulating optimal phase likelihood",
"container-title": "Nature communications",
"author": [
{
"family": "Romei",
"given": "Vincenzo"
},
{
"family": "Tarasi",
"given": "Luca"
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "3384",
"DOI": "10.1038/s41467-026-70124-9",
"PMID": "41776179",
"PMCID": "PMC13065768",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-70124-9",
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
3
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1162/imag.a.1263
Individual alpha frequency predicts the sensitivity of time perception.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: cognitive, 13 references
[2] doi:10.7554/elife.110000 [code]
Alpha-band phase modulates perceptual sensitivity by changing internal noise and sensory tuning.
Journal: eLife
In common: CircStat, Image Processing Toolbox, Statistics and Machine Learning Toolbox, EEG, 10 references
[3] doi:10.1093/cercor/bhag117 [code]
Spontaneous changes in the prestimulus alpha power predict both objective and subjective aspects of perception-evidence from 4 paradigms and 471 experimental sessions.
Journal: Cerebral cortex (New York, N.Y. : 1991)
In common: EEG, cognitive, 8 references
[4] doi:10.7554/elife.108408 [code]
Frequency and laminar profile of feature-specific visual activity revealed by interleaved EEG-fMRI.
Journal: eLife
In common: Image Processing Toolbox, Signal Processing Toolbox, Statistics and Machine Learning Toolbox, EEG, 5 references
[5] doi:10.1523/jneurosci.0154-26.2026 [code]
Faster but less precise: expectation enhances response speed while reducing sensory fidelity.
Journal: The Journal of neuroscience : the official journal of the Society for Neuroscience
In common: CircStat, EEGLAB, Image Processing Toolbox, 2 other tools, EEG, cognitive, 2 references
[6] doi:10.1111/psyp.70271 [code]
Disentangling Respiratory Phase-Dependent and Phase-Independent Components of Anticipatory Cardiac Deceleration.
Journal: Psychophysiology
In common: CircStat, EEGLAB, Image Processing Toolbox, 2 other tools, EEG, cognitive, 1 reference
[7] doi:10.1016/j.isci.2025.113806 [code]
Beta-band frequency shifts signal decisions in human prefrontal cortex
Journal: n/a
In common: Statistics and Machine Learning Toolbox, 6 references
[8] doi:10.1162/imag.a.1229 [code]
40 Hz audiovisual stimulation improves sustained attention and related brain oscillations.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: CircStat, EEGLAB, Image Processing Toolbox, 2 other tools, EEG, 1 reference
[9] doi:10.1162/imag.a.1199 [code]
Sustained alpha oscillations serve attentional prioritization in working memory, not maintenance.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: CircStat, EEGLAB, Image Processing Toolbox, 2 other tools, EEG, cognitive, 1 reference
[10] doi:10.1371/journal.pbio.3003818 [code]
Human neuronal firing varies with the frequency of local field potential oscillations.
Journal: PLoS biology
In common: CircStat, EEGLAB, Image Processing Toolbox, 2 other tools, 1 reference

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.