Universal rhythmic architecture uncovers two modes of neural dynamics.
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] § 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] § Methods › Lagged angle vector index (LAVI) ↔ matlab/tfrLight.m, lines 104–171 · score 0.71 · upgoing flank, produce angles, convolving, sine, centre, wavelets
- [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] § 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] § 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] § Methods › Lagged angle vector index (LAVI) ↔ matlab/tfrLight.m, lines 1–53 · score 0.62 · GNU General Public, FieldTrip, License, Matlab
- [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] § Methods › Bursts analysis ↔ matlab/Bursts_detection_WTPL_v1_0_0.m, lines 1–81 · score 0.53 · nearest trough, individual bursts, filtered, raw
- [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
- function [Output,pmtr] = Bursts_detection_WTPL_v1_0_0 (raw,pmtr)
- % [Output,pmtr] = Bursts_detection_WTPL_v1_0_0 (raw,pmtr)
- % Detects bursts and their statistics, as used in:
- % Karvat, G., Crespo-García, M., Vishne, G., Anderson, M. C., and
- % Landau, A. N. (2026). Universal rhythmic architecture uncovers two modes
- % of neural dynamics. Nature Communications. https://doi.org/10.1038/s41467-026-73553-8
- %
- % Dependencies:
- % ------------
- % Fieldtrip toolbox: Available at https://www.fieldtriptoolbox.org/.
- % Please cite the original Fieldtrip paper when using
- % this function (doi: 10.1155/2011/156869)
- % WTPL toolbox: Available at https://zenodo.org/records/10664624.
- % If using WTPL for reporting burst duration, please cite the
- % original publication: https://doi.org/10.1162/jocn_a_02088
- %
- % Input:
- % -----
- % raw: a raw Fieldtrip structure, with one channel and one trial (of the whole session).
- % pmtr: a structure with parameters. If empty, assigns default values.
- % .foi: frequencies of interest, in Hz.
- % Default: 10.^(0.5:0.025:1.65);
- % .wave_width: width of the wavelet, in periods. Default: 5.
- % .ptl_high: threshold percentile for bursts. Default: 90.
- % .ptl_dur: percentile to use for determining duration. Default:75.
- % .SD_dur: value (in Standard Deviation) to add to the median for
- % duration calculation. Little et al 2019 used 1.75. Default:0.
- % .downsmpFact: downsampling parameter of the tfr. Default: 1 (no downsampling).
- % .minQuietFs: minimal of frequencies in foi below the thresold to be
- % considered "quiet". Default: 0.25.
- % .output_power: boolean, Keep the normalized power in output? Default: 0.
- % .art_thresh: optional- threshold for artifact removal in uV
- % (replacing 0.5 sec around artifacts with NaN). Skipped
- % if NaN. Default: NaN.
- % .lastSample: last sample to take into account. Default: end of session.
- % .min_f_gap: the minimum gap betwween overlapping bursts, in Hz.
- % Default: a quarter of each frequency, with a minimum of 4.
- % .max_span: the maximum allowed frequency span. Default: the whole spectrum
- % .wtpl_thr: Threshold of WTPL to calculate duration. Default: 0.5.
- % .ctrl_bursts: 'yes' or 'no', whether or not to plot individual bursts
- % for control. Default: 'no'.
- % .fs: sampling frequencies (in Hz). If not provided, tries
- % raw.fsample, and if not available, computes from raw.time{1}; % if fs (sapmling rate) not given, compute it
- % .min_dur the minimum duration of a burst, in periods. Use 0.5 if
- % the duration is calculated according to the high percentile.
- % Default: 1; %
- %
- % Output:
- % ------
- % .pmtr: structure with the updated parameter values (including defaults).
- % .burstDists: N_burst x 21 matrix with columns:
- % 1: maxima freq(Hz), 2: maxima timing(sample), 3: begin (sample),
- % 4: end (sample), 5: nearest trough, 6: duration (periods),
- % 7: duration (ms), 8: power (rel pctl), 9: power (absolute),
- % 10: number of troughs, 11: number of peaks,
- % 12: begin high percentile (sample), 13: end high percentile (sample)
- % 14: freq index (ignore), 15: lowest SPAN frequency (Hz),
- % 16: highest SPAN frequency (Hz), 17: lower PEAK freq (Hz),
- % 18: highest PEAK freq (Hz), 19: begin (sample, wtpl),
- % 20: end(sample, wtpl), 21: duration WTPL (periods)
- % .TroughPeak: N_burst x 2 cell array, with the samples of all troughs (:,1)
- % and all peaks (:.2) within the burst.
- % .PeakSpan: N_burst x 1 cell array, with the dominant (highest power)
- % frequency in each sample of the burst.
- % .arts: N_time x 1 (logical). Samples with detected artifacts
- % (relevant when pmtr.arts is provided)
- % .col_names: 21 x 1 cell array, names of the columns of the burstDists
- % matrix.
- % .pwr: N_foi x N_time double, the normalized time-frequency-represntation
- % (given if pmtr.output_power is true).
- % .filtd: N_foi x N_time double, the bandpass-filtered data (given if
- % pmtr.output_power is true).
- %
- % Version 1.0.0, 19/06/2026 (Golan Karvat)
- %
- % To do: define the duration of the burst based on lagged-coherence,
- % as suggested by Schmidt et al 2023, https://www.sciencedirect.com/science/article/pii/S0959438823001216
- t_func = tic;
- % get the parameters
- if nargin<2; pmtr=[]; end
- % Define parameters
- if ~isfield(pmtr,'foi'); pmtr.foi = 10.^(0.5:0.025:1.65); end % frequencies of interest, in Hz
- if ~isfield(pmtr,'wave_width'); pmtr.wave_width = 5; end % the width of the wavelet, in periods
- if ~isfield(pmtr,'ptl_high'); pmtr.ptl_high = 90; end % the threshold percentile for bursts
- if ~isfield(pmtr,'ptl_dur'); pmtr.ptl_dur = 75; end % the percentile to use for determining duration
- 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
- if ~isfield(pmtr,'downsmpFact'); pmtr.downsmpFact = 1; end % the downsampling parameter of the tfr
- if ~isfield(pmtr,'minQuietFs'); pmtr.minQuietFs = 0.25; end % minimal of frequencies in foi below the thresold to be considered "quiet"
- if ~isfield(pmtr,'output_power');pmtr.output_power = 0; end % Keep the normalized power in output?
- 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
- if ~isfield(pmtr,'lastSample'); pmtr.lastSample = raw.sampleinfo(end); end %last sample to take into account. Default: end of session
- 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
- if ~isfield(pmtr,'max_span'); pmtr.max_span = pmtr.foi(end)-pmtr.foi(1); end % the maximum allowed frequency span. Default: the whole spectrum
- if ~isfield(pmtr,'wtpl_thr'); pmtr.wtpl_thr = 0.5; end % Threshold of WTPL to calculate duration
- 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
- if ~isfield(pmtr,'ctrl_bursts'); pmtr.ctrl_bursts = 'no'; end % whether or not to plot individual bursts for control
- if ~isfield(pmtr,'fs'); try pmtr.fs = raw.fsample; % if fs (sapmling rate) not given, compute it
- catch pmtr.fs = round(1/nanmean(diff(raw.time{1}))); end; end
- disp('Calculating bursts');
- % make the TFR
- f_res = mode(diff(pmtr.foi)); % get the frequency resolution
- foi = pmtr.foi;
- nF = length(foi);
- f1 = max([1, foi(1) - diff(foi([1,2]))]);
- f2 = foi(end) + diff(foi([nF-1,nF]));
- foi2 = [f1 pmtr.foi f2];
- 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
- disp(['Started calculating power at ' showCurrnetTime])
- cfg = [];
- cfg.method = 'wavelet'; %time-frequency analysis using the 'wavelet method' based on Morlet wavelets
- cfg.output = 'fourier'; %'pow'; % keep the full Fourier to support WTPL
- cfg.foi = foi2;
- cfg.toi = 'all';
- cfg.width = pmtr.wave_width;
- cfg.pad = 'nextpow2';
- try TFR = ft_freqanalysis(cfg, raw);
- catch
- warning('Having to remove next power of 2');
- cfg = rmfield(cfg,'pad');
- TFR = ft_freqanalysis(cfg, raw);
- end
- offline_pwr = squeeze(abs(TFR.fourierspctrm).^2);
- % calculate WTPL
- wfg = [];
- wfg.verbose = 1;
- wfg.fs = pmtr.fs;
- wfg.nlag_post = 1;
- wfg.nlag_pre = 1;
- max_leg = max([wfg.nlag_post, wfg.nlag_pre]);
- min_start = ceil(pmtr.fs/f1*max_leg)+1; % the minimum margin to keep from the ends
- wfg.toi = min_start:length(raw.time{1})-min_start;
- WTPL = freqToWTPLwholeSession(wfg, TFR);
- %
- if ~isnan(pmtr.art_thresh)
- cfg = [];
- cfg.in_channel = 1;
- cfg.fs = pmtr.fs / pmtr.downsmpFact;
- % cfg.muscle = pmtr.muscle;
- cfg.art_thresh = pmtr.art_thresh;
- cfg.art_removal = round(cfg.fs*0.5);
- pwr_clean = gross_artifact_removal(cfg, raw, offline_pwr);
- arts = isnan(gross_artifact_removal(cfg, raw, raw.trial{1}));
- else
- pwr_clean = offline_pwr;
- arts = [];
- end
- disp(['Started calculating burst peaks at ' showCurrnetTime])
- t_BW = tic;
- pwr_pctl_high = prctile (pwr_clean, pmtr.ptl_high, 2);
- pwr_pctl_dur = prctile (pwr_clean, pmtr.ptl_dur, 2) + pmtr.SD_dur*std(pwr_clean,0,2,'omitnan');
- pwr_masked = pwr_clean ./ pwr_pctl_high;
- pwr_masked(pwr_masked < 1)=0;
- pwr_masked(isnan(pwr_masked))=0;
- pwr_for_dur = pwr_clean ./ pwr_pctl_dur;
- pwr_for_dur(pwr_for_dur < 1)=0;
- pwr_for_dur(isnan(pwr_for_dur))=0;
- BW = imregionalmax(pwr_masked);
- [i,j] = find(BW);
- added = i==1 | i==length(foi2);
- i(added) = [];
- j(added) = [];
- i(j>pmtr.lastSample)=[]; % remove bursts that happened after the task has ended
- j(j>pmtr.lastSample)=[];
- % translate to the original frequency frame
- i = i-1;
- BW ([1,end],:) = []; %one f above and one below were added just for peak reasons
- pwr_clean([1,end],:) = [];
- pwr_masked([1,end],:) = [];
- pwr_for_dur([1,end],:) = [];
- offline_pwr([1,end],:) = [];
- pwr_pctl_dur([1,end],:) = [];
- pwr_pctl_high([1,end],:) = [];
- WTPL([1,end],:) = [];
- thr = prctile(WTPL(:),75);
- wtpl = WTPL;
- wtpl(wtpl<thr)=0;
- ii = i;% translate i into the coordinates of filtd
- disp (['Calculating burst peaks took ' num2str(toc(t_BW)) ' seconds']);
- % create array of filtered data, to detect the troughs and peaks
- disp(['Started filtering at ' showCurrnetTime])
- t_filter = tic;
- raw_non_ft = raw.trial{1};
- filtd = zeros(length(pmtr.foi),length(raw_non_ft));
- for f = 1:length(pmtr.foi)
- try filtd(f,:) = ft_preproc_bandpassfilter(raw_non_ft, raw.fsample, pmtr.foi(f)+[-2 2]);
- catch bandpass(raw_non_ft,pmtr.foi(f)+[-1 1],raw.fsample); end
- end
- disp (['Filtering took ' num2str(toc(t_filter)) ' seconds']);
- %%
- disp(['Started burstDists structure at ' showCurrnetTime])
- burstDists = zeros(length(j),21);
- PeakSpan = cell(length(j),1);
- PeakSamp = cell(length(j),1);
- outTick = cell(length(j),2);% 1- timestapms of all troughs. 2= Peaks
- % 1= maxima freq(Hz), 2= maxima timing(sample), 3= begin (sample), 4= end (sample), 5 = nearest trough
- % 6 = duration (periods), 7 = duration (ms), 8 = power (rel pctl), 9 = power (absolute),
- % 10 = number of troughs, 11 = number of peaks, 12= begin high percentile (sample), 13= end high percentile (sample)
- % 14 = freq index (ignore), 15 = lowest SPAN frequency (Hz), 16 = highest SPAN frequency (Hz),
- % 17 = lower PEAK freq (Hz), 18 = highest PEAK freq (Hz),
- % 19 = begin (sample, wtpl), 20 = end(sample, wtpl), 21 = duration WTPL (periods)
- too_short = false(length(j),1); % flag of keeping the burst
- n = size(pwr_masked,2);
- disp(['Total bursts: ' num2str(length(j))]);
- t_trials = tic;
- prev = fprintf(' ');
- %
- for x = 1:length(j)
- if ~mod(x,100); prev = dispRMVprev (['Finished ' num2str(x) ' bursts in ' num2str(toc(t_trials)) ' sec'],prev); end
- burstDists(x,1) = foi(i(x));% pmtr.foi(i(x)-1); %i(x)+pmtr.foi(1)-2; % freq
- burstDists(x,14) = i(x);%i(x)+pmtr.foi(1)-2; % freq index. to be removed
- burstDists(x,2) = j(x)*pmtr.downsmpFact; % timeStamp
- % get the beginning and end of the burst, according to the percentile used to detect the peak
- [t_before_high_pctl, t_after_high_pctl, ~, ~] = get_burst_durations(i,j,x,pmtr,ii,filtd,n,pwr_masked);
- % get the beginning and end of the burst, according to the percentile used to calculate duration
- [t_before, t_after, pks, trgh] = get_burst_durations(i,j,x,pmtr,ii,filtd,n,pwr_for_dur);
- burstDists(x,3) = t_before * pmtr.downsmpFact;
- burstDists(x,4) = t_after * pmtr.downsmpFact;
- burstDists(x,6) = (t_after - t_before) ./ (ceil(pmtr.fs./burstDists(x,1)));
- too_short(x) = burstDists(x,6)<pmtr.min_dur;
- if ~too_short(x)
- burstDists(x,7) = (t_after - t_before) / pmtr.fs*1000;
- burstDists(x,8) = pwr_masked(i(x), j(x));
- burstDists(x,9) = pwr_clean(i(x), j(x));
- tmp = filtd(ii(x), t_before-1:t_after+1);
- outTick{x,1} = trgh;
- outTick{x,2} = pks;
- burstDists(x,10) = length(trgh);
- burstDists(x,11) = length(pks);
- % finding the nearest trough
- 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
- pre_ind = max([1,j(x)-wished_inds]);
- post_ind = min([length(raw_non_ft),j(x)+wished_inds]);
- inds = pre_ind:post_ind;
- locs = [];
- val = [];
- for si = 2:(length(inds)-1) % this for loop is much faster than findpeaks
- if(filtd(ii(x), inds(si)) < filtd(ii(x), inds(si)-1) &&...
- filtd(ii(x), inds(si)) < filtd(ii(x), inds(si)+1))
- locs = [locs, inds(si)]; val = [val, abs(filtd(ii(x), inds(si)))]; end
- end
- locs2 = abs(locs-burstDists(x,2));
- nearest_trough = locs(locs2==min(locs2));
- if length(nearest_trough)>1
- cand = val(locs2==min(locs2));
- [~,tmpi]=max(cand);
- nearest_trough = nearest_trough(tmpi);
- end
- if isempty(nearest_trough) % in the (very) rare condition that there is no trough, take the point of power maxima
- % figure; plot(filtd(ii(x), inds));
- nearest_trough = burstDists(x,2);
- % disp('Found a burst without troughs');
- end
- burstDists(x,5) = nearest_trough;
- end
- col = pwr_masked(:,burstDists(x,2));
- [freq_span,ind_above,ind_below] = getFreqSpan(col, i(x));
- burstDists(x,15) = foi(burstDists(x,14) - ind_below);
- burstDists(x,16) = foi(burstDists(x,14) + ind_above);
- % Peak frequency span
- B = burstDists(x,:);
- f_ind = B(14)-ind_below : B(14)+ind_above;
- if numel(f_ind)>1
- curr = pwr_masked(f_ind, B(3):B(4));
- [M,I] = max(curr); I(M==0) = [];
- burstDists(x,17) = foi(f_ind(min(I)));
- burstDists(x,18) = foi(f_ind(max(I)));
- peak_f_ind = f_ind(I);
- PeakSpan{x} = foi(peak_f_ind);
- PeakSamp{x} = B(3):B(4); PeakSamp{x}(M==0)=[];
- else
- burstDists(x,[17,18]) = foi(B(14)); % if there was only one frequency in the burst, the whole span is this frequency
- peak_f_ind = B(14);
- PeakSpan{x} = foi(peak_f_ind);
- PeakSamp{x} = B(1);
- end
- % Define the beginning and end of the burst according to all
- % frequencies that had a peak
- % in_pwr = zeros(size(pwr_for_dur));
- % in_pwr (B(14),:) = sum(pwr_for_dur(unique(peak_f_ind),:),1);
- % get_burst_durations(i,j,x,pmtr,ii,filtd,n,in_pwr);
- % in_pwr = sum(pwr_for_dur(unique(peak_f_ind),:),1);
- [t_before, t_after] = WTPL_burst_durations_v2(peak_f_ind, B, pwr_for_dur);
- burstDists(x,12) = t_before * pmtr.downsmpFact;
- burstDists(x,13) = t_after * pmtr.downsmpFact;
- burstDists(x,6) = (t_after - t_before) ./ (ceil(pmtr.fs./burstDists(x,1)));
- % WTPL-based duration
- % first aarguement is what freq indices to look at. Can be B(14) or unique(peak_f_ind)
- % B is the bursts distribution of this burst. wtpl should be normalized to threshold.
- % in_wt = sum(wtpl(unique(peak_f_ind),:),1);
- [t_before, t_after] = WTPL_burst_durations_v2(peak_f_ind,B, wtpl);
- burstDists(x,19) = t_before;
- burstDists(x,20) = t_after;
- burstDists(x,21) = (t_after - t_before) ./ (ceil(pmtr.fs./burstDists(x,1)));
- end
- %%
- bst = burstDists;
- span = bst(:,16)- bst(:,15);
- too_wide = span > pmtr.max_span;
- span(too_wide)=[];
- bst(too_short|too_wide,:)=[]; % remove bursts that were too short (time) or too wide (freq)
- outTick(too_short|too_wide,:) = [];
- PeakSpan(too_short|too_wide)=[];
- %% Burst pruning
- pwr = pwr_clean./pwr_pctl_high;
- disp('.');
- prev = fprintf(' ');
- t_.bst=tic;
- for bi = 1:length(bst)
- if ~mod(bi,2500); prev = dispRMVprev (['Finished pruning ' num2str(bi) ' bursts in ' num2str(toc(t_.bst)) ' sec'],prev); end
- % if ~mod(bi,1e4); disp(['finished pruning ' num2str(bi) ' bursts in ' num2str(toc(t_.bst)) ' seconds']); end
- if bst(bi,1) > 0 % skip bursts that were already rejected
- 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
- 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
- cond3 = bst(:,3)<=bst(bi,3) & bst(:,4)>=bst(bi,4); % all bursts that begin after and finish before the current
- cooc = cond1 | cond2 | cond3;
- cooc(bi)=0;
- cooc = find(cooc);
- for ci = 1:length(cooc)
- f1 = bst(bi,1);
- ind1 = bst(bi,14);
- f2 = bst(cooc(ci),1);
- ind2 = bst(cooc(ci),14);
- 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
- % pwr1 = pwr(ind1-pmtr.foi(1)+2, bst(bi,2)); % remove the burst with the lower energy.
- % pwr2 = pwr(ind2-pmtr.foi(1)+2, bst(cooc(ci),2)); % if they are equal, keep the first (which has the earlier peak).
- % % note that the power in the matrix is with 1 Hz below and
- % % 1 Hz above pmtr.foi.
- pwr1 = pwr(ind1, bst(bi,2)); % remove the burst with the lower energy.
- pwr2 = pwr(ind2, bst(cooc(ci),2)); % if they are equal, keep the first (which has the earlier peak).
- e1 = pwr1*(bst(bi,4)-bst(bi,3)); % estimation of energy as power x duration
- e2 = pwr2*(bst(cooc(ci),4)+bst(cooc(ci),3));
- if e2>e1
- bst(cooc(ci),3) = min([bst(cooc(ci),3), bst(bi,3)]);
- bst(cooc(ci),4) = max([bst(cooc(ci),4), bst(bi,4)]);
- bst(bi,:) = 0; % reject the "bi" burst
- break; % if the "original" was rejected no need to compare to the rest
- else
- bst(bi,3) = min([bst(cooc(ci),3), bst(bi,3)]);
- bst(bi,4) = max([bst(cooc(ci),4), bst(bi,4)]);
- bst(cooc(ci),:) = 0; end
- end
- end
- end
- end
- outTick(~bst(:,1),:) = [];
- PeakSpan(~bst(:,1),:) = [];
- bst(~bst(:,1),:)=[];
- disp('.');
- disp (['Total bursts rejected: ' num2str(length(burstDists)- length(bst))]);
- %%
- Output.pmtr = pmtr;
- Output.burstDists = bst;
- Output.TroughPeak = outTick;
- Output.PeakSpan = PeakSpan;
- Output.arts = arts;
- Output.col_names = {'maxima freq (Hz)','maxima timing (sample)',...
- 'begin (sample)','end (sample)','nearest trough','duration (period)', ...
- 'duration (ms)', 'power (rel pctl)', 'power (absolute)', 'number of troughs', 'number of peaks'...
- 'begin high percentile (sample)', 'end high percentile (sample)', ...
- 'ignore', 'low Span freq (Hz)', 'high Span freq (Hz)', 'low Peak freq (Hz)', 'high Peak freq (Hz)',...
- 'begin (sample, wtpl)', 'end (sample, wtpl)', 'duration WTPL (periods)'}';
- if pmtr.output_power
- Output.pwr = pwr_clean./pwr_pctl_high;
- Output.filtd = filtd;
- end
- disp('.');
- 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
- MRC Cognition and Brain Sciences Unit, University of Cambridge,Cambridge, CB2 7EF UK
- Edmond and Lily Safra Center for brain sciences, The Hebrew University of Jerusalem,Jerusalem, 9190401 Israel
- Present Address: Data Science Institute, Columbia University,New York, 10027 NY USA
- Department of Psychology, The Hebrew University of Jerusalem,Jerusalem, 9190401 Israel
- Department of Cognitive and Brain Sciences, The Hebrew University of Jerusalem,Jerusalem, 9190401 Israel
- Department of Experimental Psychology, University College London (UCL),London, WC1H 0AP UK
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
78386879eeb8cf9be06a1edfa6917c91b2d0d2ba, 22 July 2026Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
43 files
- matlab/
ABBA.m , MATLAB, 134 lines - matlab/
Bursts_detection_WTPL_v1 , MATLAB, 386 lines, 3 matches_0_0.m - matlab/
General_SigLims.m , MATLAB, 75 lines - matlab/
LAVI_main.m , MATLAB, 43 lines - matlab/
LAVI_walk_through.m , MATLAB, 189 lines - matlab/
LAVI_walk_through.mlx , MATLAB, not shown here - matlab/
Prepare_LAVI.m , MATLAB, 57 lines - matlab/
Pwelch2amplitude.m , MATLAB, 14 lines - matlab/
WTPL_burst_durations_v2. , MATLAB, 24 linesm - matlab/
computePinkLAVI.m , MATLAB, 86 lines - matlab/
compute_lavi.m , MATLAB, 53 lines - matlab/
dispRMVprev.m , MATLAB, 3 lines - matlab/
fit_GK.m , MATLAB, 16 lines - matlab/
getFreqSpan.m , MATLAB, 26 lines - matlab/
getFrequenciesOfFFT.m , MATLAB, 11 lines - matlab/
get_AP_of_Power.m , MATLAB, 25 lines - matlab/
get_burst_durations.m , MATLAB, 42 lines - matlab/
get_pink_iafft_coefs_pow , MATLAB, 32 lines.m - matlab/
get_pink_iafft_coefs_ran , MATLAB, 25 linesdom_ap.m - matlab/
iaaft_loop_1d.m , MATLAB, 109 lines, 1 match - matlab/
pwelchNaN.m , MATLAB, 69 lines, 1 match - matlab/
showCurrnetTime.m , MATLAB, 9 lines - matlab/
tfrLight.m , MATLAB, 172 lines, 2 matches - matlab/
waveletLight.m , MATLAB, 66 lines, 2 matches - python/
examples/ , Jupyter, 536 linesLAVI_walkthrough.ipynb - python/
examples/ , MATLAB, 217 linesLAVI_walkthrough_validat ion.m - python/
examples/ , MATLAB, 202 linesLAVI_with_MNE.m - python/
examples/ , Jupyter, 278 linesLAVI_with_mne.ipynb - python/
lavi/ , Python, 49 lines__init__.py - python/
lavi/ , Python, 135 linesabba.py - python/
lavi/ , Python, 175 linesburst_helpers.py - python/
lavi/ , Python, 302 linesbursts.py - python/
lavi/ , Python, 178 linescore.py - python/
lavi/ , Python, 31 linesio.py - python/
lavi/ , Python, 25 linesplotting.py - python/
lavi/ , Python, 178 linesspectra.py - python/
lavi/ , Python, 70 linesstatistics.py - python/
lavi/ , Python, 114 linessurrogates.py - python/
lavi/ , Python, 70 linesvalidation.py - python/
lavi/ , Python, 299 lineswavelets.py - python/
tests/ , Python, 30 linestest_smoke.py - LICENSE, License, 21 lines
- README.md, Text, 14 lines
laaanchic/WTPL
6da57b71f1084c62cfa1a4deaebee227d38f2584, 21 July 2026Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
7 files
- Bursts_detection_WTPL_v1
_0_0.m , MATLAB, 386 lines - RedBlueColorMap.m, MATLAB, 44 lines
- WTPL_main.m, MATLAB, 84 lines
- freqToWTPLwholeSession.m
, MATLAB, 40 lines - wtplComp.m, MATLAB, 44 lines
- LICENSE, License, 21 lines
- README.md, Text, 25 lines
Zenodo 19581527
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
- 28 September 2026: the link answers (HTTP 200)
21 files
- ABBA.m, MATLAB, 134 lines
- General_SigLims.m, MATLAB, 75 lines
- LAVI_main.m, MATLAB, 43 lines
- LAVI_walk_through.m, MATLAB, 189 lines
- LAVI_walk_through.mlx, MATLAB, not shown here
- Prepare_LAVI.m, MATLAB, 57 lines
- Pwelch2amplitude.m, MATLAB, 14 lines
- computePinkLAVI.m, MATLAB, 86 lines
- compute_lavi.m, MATLAB, 43 lines
- dispRMVprev.m, MATLAB, 3 lines
- fit_GK.m, MATLAB, 16 lines
- getFrequenciesOfFFT.m, MATLAB, 11 lines
- get_AP_of_Power.m, MATLAB, 25 lines
- get_pink_iafft_coefs_pow
.m , MATLAB, 32 lines - get_pink_iafft_coefs_ran
dom_ap.m , MATLAB, 25 lines - iaaft_loop_1d.m, MATLAB, 109 lines
- pwelchNaN.m, MATLAB, 69 lines
- tfrLight.m, MATLAB, 172 lines
- waveletLight.m, MATLAB, 66 lines
- LICENSE, License, 21 lines
- README.md, Text, 24 lines
Code availability
A Matlab implementation for LAVI and ABBA (including pink surrogate and look-up table generation) is available at https://
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
- dataverse.harvard.edu/
dataset.xhtml , at dataverse.harvard.edu; found in “Data availability” - doi:10.6080/
k09g5jrz , at the source; found in the references - doi:10.7910/
dvn/ , at the source; found in the referencesyd7ppu - figshare:1, at figshare; found in “Data availability”
- figshare:2, at figshare; found in “Data availability”
- figshare:27934962, at figshare; found in “Data availability”
- figshare:29519285, at figshare; found in “Data availability”
- figshare:29519639, at figshare; found in “Data availability”
- figshare:29519756, at figshare; found in “Data availability”
- osf:4hxpw, at OSF; found in “Data availability”
Data availability
Dataset I used in this study is available in the Figshare database under accession code 10.6084/
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://
BibTeX
@article{karvat2026unive
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/
url = {https://
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/
VL - 17
IS - 1
SP - 7024
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1038/
"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":
"volume": "17",
"issue": "1",
"page": "7024",
"DOI": "10.1038/
"PMID": "42218120",
"PMCID": "PMC13392403",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://
"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: iScienceIn 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-MEGJournal: n/aIn 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 mappingIn 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: eLifeIn 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 SentencesJournal: n/aIn 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: eLifeIn 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 cortexJournal: n/aIn 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.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 3 repositories of the authors' code, each at its verified commit and with its license, 65 scripts, and 9 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:82718236fbc9e130…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
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.
