OSCR

Universal rhythmic architecture uncovers two modes of neural dynamics.

Code ↔ Paper

9 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 9 matches · 4 of them tie a paragraph to a whole file, not to given lines: weak matches, whose lines are not tinted
  1. [1] § Methods › Lagged angle vector index (LAVI) ↔ matlab/iaaft_loop_1d.m, the whole file · a weak match · score 0.84 · Fourier coefficients, standard deviation, amplitude distribution, power spectrum, IAAFT, surrogates
  2. [2] § Methods › Lagged angle vector index (LAVI) ↔ matlab/tfrLight.m, lines 104–171 · score 0.71 · upgoing flank, produce angles, convolving, sine, centre, wavelets
  3. [3] § Methods › Lagged angle vector index (LAVI) ↔ matlab/waveletLight.m, the whole file · a weak match · score 0.70 · upgoing flank, produce angles, sine, centre, wavelets, copy
  4. [4] § Methods › EEG acquisition and preprocessing ↔ matlab/Bursts_detection_WTPL_v1_0_0.m, lines 1–81 · score 0.63 · bandpass filtered, standard deviations, FieldTrip, SD, threshold, bursts
  5. [5] § Methods › Lagged angle vector index (LAVI) ↔ matlab/waveletLight.m, the whole file · a weak match · score 0.62 · GNU General Public, FieldTrip, License, angle, channels, Matlab
  6. [6] § Methods › Lagged angle vector index (LAVI) ↔ matlab/tfrLight.m, lines 1–53 · score 0.62 · GNU General Public, FieldTrip, License, Matlab
  7. [7] § Methods › Bursts analysis ↔ matlab/Bursts_detection_WTPL_v1_0_0.m, lines 83–171 · score 0.60 · Morlet wavelets, Burst peak, muscle, raw, width, power
  8. [8] § Methods › Bursts analysis ↔ matlab/Bursts_detection_WTPL_v1_0_0.m, lines 1–81 · score 0.53 · nearest trough, individual bursts, filtered, raw
  9. [9] § Results › Rhythmicity-resolved spectral architecture ↔ matlab/pwelchNaN.m, the whole file · a weak match · score 0.50 · Power spectral density, power spectrum, vector, signal

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 · 386 lines · 20 KB · MIT · 3 matches

  1. function [Output,pmtr] = Bursts_detection_WTPL_v1_0_0 (raw,pmtr)
  2. % [Output,pmtr] = Bursts_detection_WTPL_v1_0_0 (raw,pmtr)
  3. % Detects bursts and their statistics, as used in:
  4. % Karvat, G., Crespo-García, M., Vishne, G., Anderson, M. C., and
  5. % Landau, A. N. (2026). Universal rhythmic architecture uncovers two modes
  6. % of neural dynamics. Nature Communications. https://doi.org/10.1038/s41467-026-73553-8
  7. %
  8. % Dependencies:
  9. % ------------
  10. % Fieldtrip toolbox: Available at https://www.fieldtriptoolbox.org/.
  11. % Please cite the original Fieldtrip paper when using
  12. % this function (doi: 10.1155/2011/156869)
  13. % WTPL toolbox: Available at https://zenodo.org/records/10664624.
  14. % If using WTPL for reporting burst duration, please cite the
  15. % original publication: https://doi.org/10.1162/jocn_a_02088
  16. %
  17. % Input:
  18. % -----
  19. % raw: a raw Fieldtrip structure, with one channel and one trial (of the whole session).
  20. % pmtr: a structure with parameters. If empty, assigns default values.
  21. % .foi: frequencies of interest, in Hz.
  22. % Default: 10.^(0.5:0.025:1.65);
  23. % .wave_width: width of the wavelet, in periods. Default: 5.
  24. % .ptl_high: threshold percentile for bursts. Default: 90.
  25. % .ptl_dur: percentile to use for determining duration. Default:75.
  26. % .SD_dur: value (in Standard Deviation) to add to the median for
  27. % duration calculation. Little et al 2019 used 1.75. Default:0.
  28. % .downsmpFact: downsampling parameter of the tfr. Default: 1 (no downsampling).
  29. % .minQuietFs: minimal of frequencies in foi below the thresold to be
  30. % considered "quiet". Default: 0.25.
  31. % .output_power: boolean, Keep the normalized power in output? Default: 0.
  32. % .art_thresh: optional- threshold for artifact removal in uV
  33. % (replacing 0.5 sec around artifacts with NaN). Skipped
  34. % if NaN. Default: NaN.
  35. % .lastSample: last sample to take into account. Default: end of session.
  36. % .min_f_gap: the minimum gap betwween overlapping bursts, in Hz.
  37. % Default: a quarter of each frequency, with a minimum of 4.
  38. % .max_span: the maximum allowed frequency span. Default: the whole spectrum
  39. % .wtpl_thr: Threshold of WTPL to calculate duration. Default: 0.5.
  40. % .ctrl_bursts: 'yes' or 'no', whether or not to plot individual bursts
  41. % for control. Default: 'no'.
  42. % .fs: sampling frequencies (in Hz). If not provided, tries
  43. % raw.fsample, and if not available, computes from raw.time{1}; % if fs (sapmling rate) not given, compute it
  44. % .min_dur the minimum duration of a burst, in periods. Use 0.5 if
  45. % the duration is calculated according to the high percentile.
  46. % Default: 1; %
  47. %
  48. % Output:
  49. % ------
  50. % .pmtr: structure with the updated parameter values (including defaults).
  51. % .burstDists: N_burst x 21 matrix with columns:
  52. % 1: maxima freq(Hz), 2: maxima timing(sample), 3: begin (sample),
  53. % 4: end (sample), 5: nearest trough, 6: duration (periods),
  54. % 7: duration (ms), 8: power (rel pctl), 9: power (absolute),
  55. % 10: number of troughs, 11: number of peaks,
  56. % 12: begin high percentile (sample), 13: end high percentile (sample)
  57. % 14: freq index (ignore), 15: lowest SPAN frequency (Hz),
  58. % 16: highest SPAN frequency (Hz), 17: lower PEAK freq (Hz),
  59. % 18: highest PEAK freq (Hz), 19: begin (sample, wtpl),
  60. % 20: end(sample, wtpl), 21: duration WTPL (periods)
  61. % .TroughPeak: N_burst x 2 cell array, with the samples of all troughs (:,1)
  62. % and all peaks (:.2) within the burst.
  63. % .PeakSpan: N_burst x 1 cell array, with the dominant (highest power)
  64. % frequency in each sample of the burst.
  65. % .arts: N_time x 1 (logical). Samples with detected artifacts
  66. % (relevant when pmtr.arts is provided)
  67. % .col_names: 21 x 1 cell array, names of the columns of the burstDists
  68. % matrix.
  69. % .pwr: N_foi x N_time double, the normalized time-frequency-represntation
  70. % (given if pmtr.output_power is true).
  71. % .filtd: N_foi x N_time double, the bandpass-filtered data (given if
  72. % pmtr.output_power is true).
  73. %
  74. % Version 1.0.0, 19/06/2026 (Golan Karvat)
  75. %
  76. % To do: define the duration of the burst based on lagged-coherence,
  77. % as suggested by Schmidt et al 2023, https://www.sciencedirect.com/science/article/pii/S0959438823001216
  78. t_func = tic;
  79. % get the parameters
  80. if nargin<2; pmtr=[]; end
  81. % Define parameters
  82. if ~isfield(pmtr,'foi'); pmtr.foi = 10.^(0.5:0.025:1.65); end % frequencies of interest, in Hz
  83. if ~isfield(pmtr,'wave_width'); pmtr.wave_width = 5; end % the width of the wavelet, in periods
  84. if ~isfield(pmtr,'ptl_high'); pmtr.ptl_high = 90; end % the threshold percentile for bursts
  85. if ~isfield(pmtr,'ptl_dur'); pmtr.ptl_dur = 75; end % the percentile to use for determining duration
  86. if ~isfield(pmtr,'SD_dur'); pmtr.SD_dur = 0; end % value (in SD) to add to the median for duration calculation. Little et al 2019 used 1.75
  87. if ~isfield(pmtr,'downsmpFact'); pmtr.downsmpFact = 1; end % the downsampling parameter of the tfr
  88. if ~isfield(pmtr,'minQuietFs'); pmtr.minQuietFs = 0.25; end % minimal of frequencies in foi below the thresold to be considered "quiet"
  89. if ~isfield(pmtr,'output_power');pmtr.output_power = 0; end % Keep the normalized power in output?
  90. if ~isfield(pmtr,'art_thresh'); pmtr.art_thresh = NaN; end % optional- threshold for artifact removal in uV (replacing 0.5 sec around artifacts with NaN). Skipped if NaN
  91. if ~isfield(pmtr,'lastSample'); pmtr.lastSample = raw.sampleinfo(end); end %last sample to take into account. Default: end of session
  92. if ~isfield(pmtr,'min_f_gap'); pmtr.min_f_gap = ceil(pmtr.foi./4); pmtr.min_f_gap(pmtr.min_f_gap<4) = 4; end % the minimum gap betwween overlapping bursts, in Hz. Default: a quarter of each frequency, with a minimum of 4
  93. if ~isfield(pmtr,'max_span'); pmtr.max_span = pmtr.foi(end)-pmtr.foi(1); end % the maximum allowed frequency span. Default: the whole spectrum
  94. if ~isfield(pmtr,'wtpl_thr'); pmtr.wtpl_thr = 0.5; end % Threshold of WTPL to calculate duration
  95. if ~isfield(pmtr,'min_dur'); pmtr.min_dur = 1; end % the minimum duration of a burst, in periods. Use 0.5 if the duration is calculated according to the high percentile
  96. if ~isfield(pmtr,'ctrl_bursts'); pmtr.ctrl_bursts = 'no'; end % whether or not to plot individual bursts for control
  97. if ~isfield(pmtr,'fs'); try pmtr.fs = raw.fsample; % if fs (sapmling rate) not given, compute it
  98. catch pmtr.fs = round(1/nanmean(diff(raw.time{1}))); end; end
  99. disp('Calculating bursts');
  100. % make the TFR
  101. f_res = mode(diff(pmtr.foi)); % get the frequency resolution
  102. foi = pmtr.foi;
  103. nF = length(foi);
  104. f1 = max([1, foi(1) - diff(foi([1,2]))]);
  105. f2 = foi(end) + diff(foi([nF-1,nF]));
  106. foi2 = [f1 pmtr.foi f2];
  107. pmtr.min_f_gap = [pmtr.min_f_gap(1) pmtr.min_f_gap pmtr.min_f_gap(end)]; % add values to min_f_gap because we add a freq below and a freq above
  108. disp(['Started calculating power at ' showCurrnetTime])
  109. cfg = [];
  110. cfg.method = 'wavelet'; %time-frequency analysis using the 'wavelet method' based on Morlet wavelets
  111. cfg.output = 'fourier'; %'pow'; % keep the full Fourier to support WTPL
  112. cfg.foi = foi2;
  113. cfg.toi = 'all';
  114. cfg.width = pmtr.wave_width;
  115. cfg.pad = 'nextpow2';
  116. try TFR = ft_freqanalysis(cfg, raw);
  117. catch
  118. warning('Having to remove next power of 2');
  119. cfg = rmfield(cfg,'pad');
  120. TFR = ft_freqanalysis(cfg, raw);
  121. end
  122. offline_pwr = squeeze(abs(TFR.fourierspctrm).^2);
  123. % calculate WTPL
  124. wfg = [];
  125. wfg.verbose = 1;
  126. wfg.fs = pmtr.fs;
  127. wfg.nlag_post = 1;
  128. wfg.nlag_pre = 1;
  129. max_leg = max([wfg.nlag_post, wfg.nlag_pre]);
  130. min_start = ceil(pmtr.fs/f1*max_leg)+1; % the minimum margin to keep from the ends
  131. wfg.toi = min_start:length(raw.time{1})-min_start;
  132. WTPL = freqToWTPLwholeSession(wfg, TFR);
  133. %
  134. if ~isnan(pmtr.art_thresh)
  135. cfg = [];
  136. cfg.in_channel = 1;
  137. cfg.fs = pmtr.fs / pmtr.downsmpFact;
  138. % cfg.muscle = pmtr.muscle;
  139. cfg.art_thresh = pmtr.art_thresh;
  140. cfg.art_removal = round(cfg.fs*0.5);
  141. pwr_clean = gross_artifact_removal(cfg, raw, offline_pwr);
  142. arts = isnan(gross_artifact_removal(cfg, raw, raw.trial{1}));
  143. else
  144. pwr_clean = offline_pwr;
  145. arts = [];
  146. end
  147. disp(['Started calculating burst peaks at ' showCurrnetTime])
  148. t_BW = tic;
  149. pwr_pctl_high = prctile (pwr_clean, pmtr.ptl_high, 2);
  150. pwr_pctl_dur = prctile (pwr_clean, pmtr.ptl_dur, 2) + pmtr.SD_dur*std(pwr_clean,0,2,'omitnan');
  151. pwr_masked = pwr_clean ./ pwr_pctl_high;
  152. pwr_masked(pwr_masked < 1)=0;
  153. pwr_masked(isnan(pwr_masked))=0;
  154. pwr_for_dur = pwr_clean ./ pwr_pctl_dur;
  155. pwr_for_dur(pwr_for_dur < 1)=0;
  156. pwr_for_dur(isnan(pwr_for_dur))=0;
  157. BW = imregionalmax(pwr_masked);
  158. [i,j] = find(BW);
  159. added = i==1 | i==length(foi2);
  160. i(added) = [];
  161. j(added) = [];
  162. i(j>pmtr.lastSample)=[]; % remove bursts that happened after the task has ended
  163. j(j>pmtr.lastSample)=[];
  164. % translate to the original frequency frame
  165. i = i-1;
  166. BW ([1,end],:) = []; %one f above and one below were added just for peak reasons
  167. pwr_clean([1,end],:) = [];
  168. pwr_masked([1,end],:) = [];
  169. pwr_for_dur([1,end],:) = [];
  170. offline_pwr([1,end],:) = [];
  171. pwr_pctl_dur([1,end],:) = [];
  172. pwr_pctl_high([1,end],:) = [];
  173. WTPL([1,end],:) = [];
  174. thr = prctile(WTPL(:),75);
  175. wtpl = WTPL;
  176. wtpl(wtpl<thr)=0;
  177. ii = i;% translate i into the coordinates of filtd
  178. disp (['Calculating burst peaks took ' num2str(toc(t_BW)) ' seconds']);
  179. % create array of filtered data, to detect the troughs and peaks
  180. disp(['Started filtering at ' showCurrnetTime])
  181. t_filter = tic;
  182. raw_non_ft = raw.trial{1};
  183. filtd = zeros(length(pmtr.foi),length(raw_non_ft));
  184. for f = 1:length(pmtr.foi)
  185. try filtd(f,:) = ft_preproc_bandpassfilter(raw_non_ft, raw.fsample, pmtr.foi(f)+[-2 2]);
  186. catch bandpass(raw_non_ft,pmtr.foi(f)+[-1 1],raw.fsample); end
  187. end
  188. disp (['Filtering took ' num2str(toc(t_filter)) ' seconds']);
  189. %%
  190. disp(['Started burstDists structure at ' showCurrnetTime])
  191. burstDists = zeros(length(j),21);
  192. PeakSpan = cell(length(j),1);
  193. PeakSamp = cell(length(j),1);
  194. outTick = cell(length(j),2);% 1- timestapms of all troughs. 2= Peaks
  195. % 1= maxima freq(Hz), 2= maxima timing(sample), 3= begin (sample), 4= end (sample), 5 = nearest trough
  196. % 6 = duration (periods), 7 = duration (ms), 8 = power (rel pctl), 9 = power (absolute),
  197. % 10 = number of troughs, 11 = number of peaks, 12= begin high percentile (sample), 13= end high percentile (sample)
  198. % 14 = freq index (ignore), 15 = lowest SPAN frequency (Hz), 16 = highest SPAN frequency (Hz),
  199. % 17 = lower PEAK freq (Hz), 18 = highest PEAK freq (Hz),
  200. % 19 = begin (sample, wtpl), 20 = end(sample, wtpl), 21 = duration WTPL (periods)
  201. too_short = false(length(j),1); % flag of keeping the burst
  202. n = size(pwr_masked,2);
  203. disp(['Total bursts: ' num2str(length(j))]);
  204. t_trials = tic;
  205. prev = fprintf(' ');
  206. %
  207. for x = 1:length(j)
  208. if ~mod(x,100); prev = dispRMVprev (['Finished ' num2str(x) ' bursts in ' num2str(toc(t_trials)) ' sec'],prev); end
  209. burstDists(x,1) = foi(i(x));% pmtr.foi(i(x)-1); %i(x)+pmtr.foi(1)-2; % freq
  210. burstDists(x,14) = i(x);%i(x)+pmtr.foi(1)-2; % freq index. to be removed
  211. burstDists(x,2) = j(x)*pmtr.downsmpFact; % timeStamp
  212. % get the beginning and end of the burst, according to the percentile used to detect the peak
  213. [t_before_high_pctl, t_after_high_pctl, ~, ~] = get_burst_durations(i,j,x,pmtr,ii,filtd,n,pwr_masked);
  214. % get the beginning and end of the burst, according to the percentile used to calculate duration
  215. [t_before, t_after, pks, trgh] = get_burst_durations(i,j,x,pmtr,ii,filtd,n,pwr_for_dur);
  216. burstDists(x,3) = t_before * pmtr.downsmpFact;
  217. burstDists(x,4) = t_after * pmtr.downsmpFact;
  218. burstDists(x,6) = (t_after - t_before) ./ (ceil(pmtr.fs./burstDists(x,1)));
  219. too_short(x) = burstDists(x,6)<pmtr.min_dur;
  220. if ~too_short(x)
  221. burstDists(x,7) = (t_after - t_before) / pmtr.fs*1000;
  222. burstDists(x,8) = pwr_masked(i(x), j(x));
  223. burstDists(x,9) = pwr_clean(i(x), j(x));
  224. tmp = filtd(ii(x), t_before-1:t_after+1);
  225. outTick{x,1} = trgh;
  226. outTick{x,2} = pks;
  227. burstDists(x,10) = length(trgh);
  228. burstDists(x,11) = length(pks);
  229. % finding the nearest trough
  230. wished_inds = ceil(pmtr.fs/burstDists(x,1)*1.5); % samples to look around the maxima, to make sure there is at least one trough
  231. pre_ind = max([1,j(x)-wished_inds]);
  232. post_ind = min([length(raw_non_ft),j(x)+wished_inds]);
  233. inds = pre_ind:post_ind;
  234. locs = [];
  235. val = [];
  236. for si = 2:(length(inds)-1) % this for loop is much faster than findpeaks
  237. if(filtd(ii(x), inds(si)) < filtd(ii(x), inds(si)-1) &&...
  238. filtd(ii(x), inds(si)) < filtd(ii(x), inds(si)+1))
  239. locs = [locs, inds(si)]; val = [val, abs(filtd(ii(x), inds(si)))]; end
  240. end
  241. locs2 = abs(locs-burstDists(x,2));
  242. nearest_trough = locs(locs2==min(locs2));
  243. if length(nearest_trough)>1
  244. cand = val(locs2==min(locs2));
  245. [~,tmpi]=max(cand);
  246. nearest_trough = nearest_trough(tmpi);
  247. end
  248. if isempty(nearest_trough) % in the (very) rare condition that there is no trough, take the point of power maxima
  249. % figure; plot(filtd(ii(x), inds));
  250. nearest_trough = burstDists(x,2);
  251. % disp('Found a burst without troughs');
  252. end
  253. burstDists(x,5) = nearest_trough;
  254. end
  255. col = pwr_masked(:,burstDists(x,2));
  256. [freq_span,ind_above,ind_below] = getFreqSpan(col, i(x));
  257. burstDists(x,15) = foi(burstDists(x,14) - ind_below);
  258. burstDists(x,16) = foi(burstDists(x,14) + ind_above);
  259. % Peak frequency span
  260. B = burstDists(x,:);
  261. f_ind = B(14)-ind_below : B(14)+ind_above;
  262. if numel(f_ind)>1
  263. curr = pwr_masked(f_ind, B(3):B(4));
  264. [M,I] = max(curr); I(M==0) = [];
  265. burstDists(x,17) = foi(f_ind(min(I)));
  266. burstDists(x,18) = foi(f_ind(max(I)));
  267. peak_f_ind = f_ind(I);
  268. PeakSpan{x} = foi(peak_f_ind);
  269. PeakSamp{x} = B(3):B(4); PeakSamp{x}(M==0)=[];
  270. else
  271. burstDists(x,[17,18]) = foi(B(14)); % if there was only one frequency in the burst, the whole span is this frequency
  272. peak_f_ind = B(14);
  273. PeakSpan{x} = foi(peak_f_ind);
  274. PeakSamp{x} = B(1);
  275. end
  276. % Define the beginning and end of the burst according to all
  277. % frequencies that had a peak
  278. % in_pwr = zeros(size(pwr_for_dur));
  279. % in_pwr (B(14),:) = sum(pwr_for_dur(unique(peak_f_ind),:),1);
  280. % get_burst_durations(i,j,x,pmtr,ii,filtd,n,in_pwr);
  281. % in_pwr = sum(pwr_for_dur(unique(peak_f_ind),:),1);
  282. [t_before, t_after] = WTPL_burst_durations_v2(peak_f_ind, B, pwr_for_dur);
  283. burstDists(x,12) = t_before * pmtr.downsmpFact;
  284. burstDists(x,13) = t_after * pmtr.downsmpFact;
  285. burstDists(x,6) = (t_after - t_before) ./ (ceil(pmtr.fs./burstDists(x,1)));
  286. % WTPL-based duration
  287. % first aarguement is what freq indices to look at. Can be B(14) or unique(peak_f_ind)
  288. % B is the bursts distribution of this burst. wtpl should be normalized to threshold.
  289. % in_wt = sum(wtpl(unique(peak_f_ind),:),1);
  290. [t_before, t_after] = WTPL_burst_durations_v2(peak_f_ind,B, wtpl);
  291. burstDists(x,19) = t_before;
  292. burstDists(x,20) = t_after;
  293. burstDists(x,21) = (t_after - t_before) ./ (ceil(pmtr.fs./burstDists(x,1)));
  294. end
  295. %%
  296. bst = burstDists;
  297. span = bst(:,16)- bst(:,15);
  298. too_wide = span > pmtr.max_span;
  299. span(too_wide)=[];
  300. bst(too_short|too_wide,:)=[]; % remove bursts that were too short (time) or too wide (freq)
  301. outTick(too_short|too_wide,:) = [];
  302. PeakSpan(too_short|too_wide)=[];
  303. %% Burst pruning
  304. pwr = pwr_clean./pwr_pctl_high;
  305. disp('.');
  306. prev = fprintf(' ');
  307. t_.bst=tic;
  308. for bi = 1:length(bst)
  309. if ~mod(bi,2500); prev = dispRMVprev (['Finished pruning ' num2str(bi) ' bursts in ' num2str(toc(t_.bst)) ' sec'],prev); end
  310. % if ~mod(bi,1e4); disp(['finished pruning ' num2str(bi) ' bursts in ' num2str(toc(t_.bst)) ' seconds']); end
  311. if bst(bi,1) > 0 % skip bursts that were already rejected
  312. cond1 = bst(:,3)>=bst(bi,3) & bst(:,3)<=bst(bi,4); % all bursts that begin after the beginning but before the end of the current
  313. cond2 = bst(:,4)<=bst(bi,4) & bst(:,4)>=bst(bi,3); % all bursts that finsh before the end but after the beginning of the current
  314. cond3 = bst(:,3)<=bst(bi,3) & bst(:,4)>=bst(bi,4); % all bursts that begin after and finish before the current
  315. cooc = cond1 | cond2 | cond3;
  316. cooc(bi)=0;
  317. cooc = find(cooc);
  318. for ci = 1:length(cooc)
  319. f1 = bst(bi,1);
  320. ind1 = bst(bi,14);
  321. f2 = bst(cooc(ci),1);
  322. ind2 = bst(cooc(ci),14);
  323. if abs(f1-f2) <= pmtr.min_f_gap(bst(bi,14)) % if the difference b/w the burst peakss is smaller than the defined minimum
  324. % pwr1 = pwr(ind1-pmtr.foi(1)+2, bst(bi,2)); % remove the burst with the lower energy.
  325. % pwr2 = pwr(ind2-pmtr.foi(1)+2, bst(cooc(ci),2)); % if they are equal, keep the first (which has the earlier peak).
  326. % % note that the power in the matrix is with 1 Hz below and
  327. % % 1 Hz above pmtr.foi.
  328. pwr1 = pwr(ind1, bst(bi,2)); % remove the burst with the lower energy.
  329. pwr2 = pwr(ind2, bst(cooc(ci),2)); % if they are equal, keep the first (which has the earlier peak).
  330. e1 = pwr1*(bst(bi,4)-bst(bi,3)); % estimation of energy as power x duration
  331. e2 = pwr2*(bst(cooc(ci),4)+bst(cooc(ci),3));
  332. if e2>e1
  333. bst(cooc(ci),3) = min([bst(cooc(ci),3), bst(bi,3)]);
  334. bst(cooc(ci),4) = max([bst(cooc(ci),4), bst(bi,4)]);
  335. bst(bi,:) = 0; % reject the "bi" burst
  336. break; % if the "original" was rejected no need to compare to the rest
  337. else
  338. bst(bi,3) = min([bst(cooc(ci),3), bst(bi,3)]);
  339. bst(bi,4) = max([bst(cooc(ci),4), bst(bi,4)]);
  340. bst(cooc(ci),:) = 0; end
  341. end
  342. end
  343. end
  344. end
  345. outTick(~bst(:,1),:) = [];
  346. PeakSpan(~bst(:,1),:) = [];
  347. bst(~bst(:,1),:)=[];
  348. disp('.');
  349. disp (['Total bursts rejected: ' num2str(length(burstDists)- length(bst))]);
  350. %%
  351. Output.pmtr = pmtr;
  352. Output.burstDists = bst;
  353. Output.TroughPeak = outTick;
  354. Output.PeakSpan = PeakSpan;
  355. Output.arts = arts;
  356. Output.col_names = {'maxima freq (Hz)','maxima timing (sample)',...
  357. 'begin (sample)','end (sample)','nearest trough','duration (period)', ...
  358. 'duration (ms)', 'power (rel pctl)', 'power (absolute)', 'number of troughs', 'number of peaks'...
  359. 'begin high percentile (sample)', 'end high percentile (sample)', ...
  360. 'ignore', 'low Span freq (Hz)', 'high Span freq (Hz)', 'low Peak freq (Hz)', 'high Peak freq (Hz)',...
  361. 'begin (sample, wtpl)', 'end (sample, wtpl)', 'duration WTPL (periods)'}';
  362. if pmtr.output_power
  363. Output.pwr = pwr_clean./pwr_pctl_high;
  364. Output.filtd = filtd;
  365. end
  366. disp('.');
  367. disp (['The call to Bursts_detection_WTPL took ' num2str(toc(t_func)) ,' seconds']);

Bursts_detection_WTPL_v1_0_0.m at commit 7838687, under MIT · at the source

Overview

Authors: Golan Karvat1, Maité Crespo-García1, Gal Vishne2,3, Michael C. Anderson1, Ayelet N. Landau4,5,6
  1. MRC Cognition and Brain Sciences Unit, University of Cambridge,Cambridge, CB2 7EF UK
  2. Edmond and Lily Safra Center for brain sciences, The Hebrew University of Jerusalem,Jerusalem, 9190401 Israel
  3. Present Address: Data Science Institute, Columbia University,New York, 10027 NY USA
  4. Department of Psychology, The Hebrew University of Jerusalem,Jerusalem, 9190401 Israel
  5. Department of Cognitive and Brain Sciences, The Hebrew University of Jerusalem,Jerusalem, 9190401 Israel
  6. Department of Experimental Psychology, University College London (UCL),London, WC1H 0AP UK
Institutions: University of Cambridge (United Kingdom); Hebrew University of Jerusalem (Israel); Columbia University (United States); University College London (United Kingdom)
Journal: Nature communications, volume 17, issue 1, article 7024
Dates: received 5 February 2025; accepted 7 May 2026; published online 30 May 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41467-026-73553-8 · PMID 42218120 · PMCID PMC13392403 · OpenAlex W7162852488
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: EEG (modality), human (organism)
Methods: Spectral & time-frequency, Preprocessing, Statistics, Smoothing, state filtering, decompositions, Connectivity, fMRI & imaging, Physiology & signal measures
Keywords: Psychology, Neuroscience, Cognitive neuroscience, Neuronal physiology
MeSH: Brain*, Periodicity*, Adolescent, Adult, Aged, Aged, 80 and over, Animals, Electroencephalography, Female, Humans, Male, Middle Aged, Young Adult (* major topic)
Topic: Neural dynamics and brain function (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: German Research Foundation Walter-Benjamin post-doctoral fellowship KA 5804/1-1; Azrieli Foundation graduate fellowship Edmond and Lily Safra Center fellowship for Brain Sciences graduates; Medical Research Council grant MC-A060-5PR00; James McDonnell Scholar Award in Understanding Human Cognition ISF grant 958/16 European Research Council (ERC) under the European Union’s Horizon 2020 research and innovation programme 852387 FLAG-ERA collaborative grant (MONAD) and the Israel Innovation Authority
Citations: cited by 4 papers (Europe PMC); 99 references in the paper

Abstract

Understanding the organizing principles of brain activity can advance neurotechnology and medical diagnosis. Traditionally, neural activity is viewed as consisting oscillations in distinct frequency bands. However, emerging evidence suggests these oscillations often manifest as transient bursts rather than sustained rhythms. We examine the hypothesis that rhythmicity (sustained vs bursty) adds a further dimension to brain organization. Using a rhythmicity measure, we segment neurophysiological spectra from 859 participants across datasets, species, recording techniques, ages 18–88, sexes, brain regions, and cognitive states in health and disease. Our results reveal a universal rhythmicity-resolved spectral architecture with two categories: high-rhythmicity bands exhibiting sustained oscillations and new low-rhythmicity bands dominated by brief bursts. This architecture reflects two modes of operation: sustained bands suitable for maintaining ongoing activity, and transient bands which can signal responses to change. The rhythmicity-resolved architecture provides a unifying framework that bridges human and non-human findings, enables individualized spectral definitions, and offers a principled basis for understanding brain activity.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repositories

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

laaanchic/LAVI

License: MIT
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: 78386879eeb8cf9be06a1edfa6917c91b2d0d2ba, 22 July 2026
Languages: MATLAB (26), Python (13), Jupyter (2)
Size: 67 files, 41 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, license file, environment (python/pyproject.toml, python/requirements.txt), tests, 3 notebooks
Not found: CITATION.cff, continuous integration, documentation
Tools: NumPy (14 files), SciPy (8 files), Signal Processing Toolbox (3 files), Statistics and Machine Learning Toolbox (3 files), Matplotlib (3 files), pandas (2 files), FieldTrip (1 file), MNE-Python (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
43 files

laaanchic/WTPL

License: MIT
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: 6da57b71f1084c62cfa1a4deaebee227d38f2584, 21 July 2026
Languages: MATLAB (5)
Size: 8 files, 5 scripts
Software Heritage: not archived
Found in: the text, “Time-resolved rhythmicity”
Holds: README, license file
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
7 files

Zenodo 19581527

License: MIT
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
  • 28 September 2026: the link answers (HTTP 200)
21 files
At the source:

Code availability

A Matlab implementation for LAVI and ABBA (including pink surrogate and look-up table generation) is available at https://github.com/laaanchic/LAVI79.

Reproduced under the paper's license (CC BY), from the paper cited above.

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:

  • 3 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 65 scripts, each with its path and the digest of its content;
  • 9 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

Datasets cited

Data availability

Dataset I used in this study is available in the Figshare database under accession code 10.6084/m9.figshare.29519285.v1 (https://figshare.com/articles/dataset/EEG_during_the_two-flash_task/29519285)91. Dataset II used in this study is available in the Figshare database under accession code 10.6084/m9.figshare.29519639.v1 (https://figshare.com/articles/dataset/EEG_at_wakeful_rest/29519639/1)92. Dataset III used in this study is available in the Figshare database under accession code 10.6084/m9.figshare.29519756.v1 (https://figshare.com/articles/dataset/EEG_during_tactile_timing_task/29519756/1)93. Dataset IV used in this study is available in the Harvard Dataverse database under accession code 10.7910/DVN/YD7PPU (https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/YD7PPU)94. Dataset V used in this study is available under restricted access, as it is controlled by the original data providers; access can be obtained by contacting the corresponding authors of ref. 68, Mikael Johansson and Robin Hellerstedt. Dataset VI used in this study is available under restricted access, as it is controlled by the original data providers; access can be obtained by contacting the lead author of ref. 69, Pierre Gagnepain. Dataset VII generated in this study is available in the Figshare database under accession code 10.6084/m9.figshare.27934962.v2 (https://figshare.com/articles/dataset/EEG_at_rest_and_with_TMS/27934962/2)95. Dataset VIII used in this study is available under restricted access; access can be obtained via the Cambridge Centre for Ageing and Neuroscience (Cam-CAN) data portal (https://camcan-archive.mrc-cbu.cam.ac.uk/dataaccess/) upon application and approval by the Cam-CAN data access committee. Dataset IX used in this study is available in the Open Science Framework database under accession code 10.17605/OSF.IO/4HXPW (https://osf.io/4hxpw/)96. Dataset X used in this study can be found in an online repository. The URL of the repository is: http://epi.fizica.unibuc.ro/scalesoldnew/. Dataset XI used in this study is available in the University of Oxford database under accession code 10.5287/BODLEIAN:MZJ7YWXVO (https://data.mrc.ox.ac.uk/stn-lfp-on-off-and-dbs)97. Dataset XII used in this study is available in the Collaborative Research in Computational. Neuroscience (CRCNS) database under accession code 10.6080/K09G5JRZ (https://portal.nersc.gov/project/crcns/download/hc-3)98. A small dataset generated in the study to demonstrate the LAVI algorithm is available at https://github.com/laaanchic/LAVI/blob/main/data.mat. Source data are provided with this paper.

Reproduced under the paper's license (CC BY), from the paper cited above.

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, 28 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 5 authors, 4 keywords, 13 MeSH terms, 4 funders, 96 references.

Cite

This paper

Karvat, G., Crespo-García, M., Vishne, G., Anderson, M. C., & Landau, A. N. (2026). Universal rhythmic architecture uncovers two modes of neural dynamics. Nature communications, 17(1), 7024. https://doi.org/10.1038/s41467-026-73553-8

BibTeX

@article{karvat2026universal,
author = {Karvat, Golan and Crespo-García, Maité and Vishne, Gal and Anderson, Michael C. and Landau, Ayelet N.},
title = {{Universal rhythmic architecture uncovers two modes of neural dynamics}},
journal = {Nature communications},
year = {2026},
month = may,
volume = {17},
number = {1},
pages = {7024},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-73553-8},
url = {https://doi.org/10.1038/s41467-026-73553-8},
pmid = {42218120},
pmcid = {PMC13392403}
}

RIS

TY - JOUR
AU - Karvat, Golan
AU - Crespo-García, Maité
AU - Vishne, Gal
AU - Anderson, Michael C.
AU - Landau, Ayelet N.
TI - Universal rhythmic architecture uncovers two modes of neural dynamics
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/05/30
VL - 17
IS - 1
SP - 7024
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-73553-8
UR - https://doi.org/10.1038/s41467-026-73553-8
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-73553-8",
"type": "article-journal",
"title": "Universal rhythmic architecture uncovers two modes of neural dynamics",
"container-title": "Nature communications",
"author": [
{
"family": "Karvat",
"given": "Golan"
},
{
"family": "Crespo-García",
"given": "Maité"
},
{
"family": "Vishne",
"given": "Gal"
},
{
"family": "Anderson",
"given": "Michael C."
},
{
"family": "Landau",
"given": "Ayelet N."
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "7024",
"DOI": "10.1038/s41467-026-73553-8",
"PMID": "42218120",
"PMCID": "PMC13392403",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-73553-8",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
30
]
]
}
}

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.1226 [code]
A neuroscientist's guide to neural burst detection.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: FieldTrip, MNE-Python, Statistics and Machine Learning Toolbox, 4 other tools, 8 references
[2] doi:10.1016/j.isci.2026.115375 [code]
Bursts of regional cortical inhibition during smartphone use.
Journal: iScience
In common: Signal Processing Toolbox, Statistics and Machine Learning Toolbox, pandas, 2 other tools, 7 references
[3] doi:10.1093/cercor/bhag077 [code]
The longitudinal development of intrinsic timescales in infancy and their relation to alpha brain rhythm.
Journal: Cerebral cortex (New York, N.Y. : 1991)
In common: FieldTrip, MNE-Python, pandas, 3 other tools, EEG, 5 references
[4] doi:10.1162/imag.a.1040 [code]
Novel 4 He-OPMs support waveform-specific beta burst analysis comparable to SQUID-MEG
Journal: n/a
In common: FieldTrip, MNE-Python, Signal Processing Toolbox, 5 other tools, 4 references
[5] doi:10.1162/imag.a.1255
Beta bursts spatiotemporal profiles and their links to hemodynamic responses during movement and rest.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: EEG, 9 references
[6] doi:10.1002/hbm.70484 [code]
Frequency-Resolved Cortical Functional Connectivity Across the Adult Lifespan.
Journal: Human brain mapping
In common: 9 references
[7] doi:10.7554/elife.107088 [code]
Development of auditory and spontaneous movement responses to music over the first postnatal year.
Journal: eLife
In common: FieldTrip, MNE-Python, Signal Processing Toolbox, 5 other tools, EEG, 3 references
[8] doi:10.1038/s41597-025-06397-4 [code]
MEG-SCANS - A comprehensive magnetoencephalography speech dataset with Stories, Chirps and Noisy Sentences
Journal: n/a
In common: FieldTrip, MNE-Python, Signal Processing Toolbox, 5 other tools, 3 references
[9] doi:10.7554/elife.108408 [code]
Frequency and laminar profile of feature-specific visual activity revealed by interleaved EEG-fMRI.
Journal: eLife
In common: FieldTrip, Signal Processing Toolbox, Statistics and Machine Learning Toolbox, 4 other tools, EEG, 4 references
[10] doi:10.1038/s41598-025-08037-8 [code]
OPM-MEG reveals dynamics of beta bursts underlying attentional processes in sensory cortex
Journal: n/a
In common: NumPy, EEG, 7 references

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.