Theta oscillations are an organizational unit of odor processing in the olfactory bulb.
The 16 matches
- [1] § MATERIALS AND METHODS › Cross-frequency coupling of theta and gamma ↔ code_fig6.m, lines 426–474 · score 0.95 · Hilbert transform, gamma bursts, 30–60 Hz, gamma peaks, filtered signal, CircStat
- [2] § MATERIALS AND METHODS › Cross-frequency coupling of theta and gamma ↔ dataScript.m, lines 498–533 · score 0.94 · low gamma filtered, 30–60 Hz, amplitude envelope, gamma envelope, low gamma frequency, filtered signal
- [3] § MATERIALS AND METHODS › Intertrial phase coherence ↔ code_suppFigs.m, lines 543–680 · score 0.83 · respiratory phase bins, circularly shifted, passive inhalations, respiratory epochs, intentional sniffs, Fisher
- [4] § RESULTS › Theta oscillations organize the timing of gamma bursts in the olfactory bulb ↔ code_fig6.m, lines 426–474 · score 0.80 · gamma burst, 30–60 Hz, gamma peaks, theta phase, low gamma, sniff onset
- [5] § RESULTS › Theta oscillations organize the timing of gamma bursts in the olfactory bulb ↔ code_fig6.m, lines 301–424 · score 0.77 · aligned spectrogram, theta troughs, Theta peak, theta filtered, Amplitude spectrograms, theta frequency
- [6] § MATERIALS AND METHODS › Intertrial phase coherence ↔ code_fig4.m, lines 585–639 · score 0.77 · respiratory phase bins, circularly shifted, phase epochs, ITPC, matched, permuted
- [7] § MATERIALS AND METHODS › Statistical analysis ↔ code_fig4.m, lines 201–304 · score 0.71 · sign flipped, cluster mass, clusters formed, intentional sniffs, passive, threshold
- [8] § RESULTS › High-precision recordings from the human olfactory bulb ↔ code_fig3.m, lines 95–186 · score 0.67 · low gamma band, Low gamma odor, odor detection, High gamma, 150 Hz, 60 Hz
- [9] § MATERIALS AND METHODS › Amplitude spectrograms ↔ code_suppFigs.m, lines 403–541 · score 0.66 · temporally smoothed, longest, shortest, S4C, bandwidth, SD
- [10] § RESULTS › Intentional sniffs enhance and align theta oscillations in the olfactory bulb ↔ code_fig4.m, lines 201–304 · score 0.57 · cluster corrected permutation, passive inhales, intentional sniffs, theta amplitude, airflow, bar
- [11] § RESULTS › Sniffing behavior covaries with olfactory bulb theta oscillations ↔ code_suppFigs.m, lines 403–541 · score 0.55 · sniff duration, passive inhales, intentional sniffs, S4C, subset, overlapping
- [12] § RESULTS › Intentional sniffs enhance and align theta oscillations in the olfactory bulb ↔ code_fig4.m, lines 776–805 · score 0.55 · maximum theta ITPC, passive inhales, intentional sniff, resampling, phase, Figure 4
- [13] § RESULTS › High-precision recordings from the human olfactory bulb ↔ code_fig2_OdorImageCue.m, lines 329–393 · score 0.55 · image onset, odor cues, FDR corrected, baseline, Figure 2, threshold
- [14] § RESULTS › High-precision recordings from the human olfactory bulb ↔ code_fig3.m, lines 274–372 · score 0.53 · Power spectra, Gamma power, cue task, low gamma, contact, Figure 3
- [15] § RESULTS › High-precision recordings from the human olfactory bulb ↔ code_fig2_OdorImageCue.m, lines 329–393 · score 0.53 · image cues, Odor cues, FDR corrected, baseline, onset, Figure 2
- [16] § RESULTS › Intentional sniffs enhance and align theta oscillations in the olfactory bulb ↔ code_suppFigs.m, lines 682–719 · score 0.51 · Resampled distributions, passive inhales, intentional sniffs, CI, bootstrap, subset
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,002 lines · 45 KB · CC-BY-4.0 · 4 matches
- %% Load data
- load data_supp
- %% Fig S2A - Odor vs. Image spectrograms
- % CUE TASK ODOR
- % Calculate spectrogram - concatenated 6 subs
- tic
- ts = data_supp.lfpData_cueSniffOdor_combinedSubs;
- sniffonset_conds = { data_supp.sniffonsets_cueOdorSniff_combinedSubs };
- para = [];
- para.freq = logspace( log10( 1), log10( 200), 100); % center frequencies for filtering
- para.bandwidth = logspace( log10( 2), log10( 30), 100); % bandwidth of each center frequency
- para.srate = srate; % sampling rate, in Hz
- para.events = sniffonset_conds; % in samples
- para.epoch = [-1, 5]; % in seconds, relative to events
- para.baseline = [-0.6, -0.1]; % in seconds, relative to events
- para.smooth_win = 0.01; % temporal smoothing, in secondsj
- para.nbpermuts = 10000; % number of permutations,
- para.measure = 'amplitude'; % or 'power'
- para.baseline_condition = []; % which condition to use as baseline (empty for just before each of multiple conditions)
- para.trl = 'mean'; % 'mean' o r'median' value across trials
- [stats_cueSniffOdor, epoch_time_cueSniffOdor, ev_epochs_cueSniffOdor, ~, sd_cueSniffOdor] = PermutAmpChange_Commonbaseline(ts, para);
- % IMAGE ONSETS
- ts = data_supp.lfp_visualCue_combinedSubs;
- sniffonset_conds = { data_supp.imageonsets_combinedSubs };
- para = [];
- para.freq = logspace( log10( 1), log10( 200), 100); % center frequencies for filtering
- para.bandwidth = logspace( log10( 2), log10( 30), 100); % bandwidth of each center frequency
- para.srate = srate; % sampling rate, in Hz
- para.events = sniffonset_conds; % in samples
- para.epoch = [-1, 5]; % in seconds, relative to events
- para.baseline = [-0.6, -0.1]; % in seconds, relative to events
- para.smooth_win = 0.01; % temporal smoothing, in secondsj
- para.nbpermuts = 10000; % number of permutations,
- para.measure = 'amplitude'; % or 'power'
- para.baseline_condition = []; % which condition to use as baseline (empty for just before each of multiple conditions)
- para.trl = 'mean'; % 'mean' o r'median' value across trials
- [stats_imageOnsets, epoch_time_imageOnsets, ev_epochs_imageOnsets, ~, sd_imageOnsets] = PermutAmpChange_Commonbaseline(ts, para);
- % CALCULATE DIFFERENCE BETWEEN CUE TASK SNIFF ODOR AND CUE TASK VISUAL IMAGE
- mat = cat(3,ev_epochs_cueSniffOdor{1},ev_epochs_imageOnsets{1});
- mat = permute(mat, [3 1 2]);
- g = [ones(length(data_supp.sniffonsets_cueOdorSniff_combinedSubs),1) ; 2*ones(length(data_supp.imageonsets_combinedSubs),1)];
- AmpChange_CueTasks_OdorVsImage = G_PowChange_Clust(mat, g, epoch_time_imageOnsets, para.freq, 'baseline', para.baseline,'db_transf', 'no','common_bs','no');
- % PLOT DIFFERENCE BETWEEN CUE TASK SNIFF ODOR AND CUE TASK VISUAL IMAGE
- % Respiratory overlays
- resp_epochs_cueSniffOdor_combinedSubs = squeeze(zscore(G_EpochTS(data_supp.resp_cueSniffOdor_combinedSubs, data_supp.sniffonsets_cueOdorSniff_combinedSubs, [-1,5]*srate)));
- resp_meanEpochs_cueSniffOdor_combinedSubs = squeeze(mean(resp_epochs_cueSniffOdor_combinedSubs,2));
- resp_epochs_imageOnsets_combinedSubs = squeeze(zscore(G_EpochTS(data_supp.resp_visualCue_combinedSubs, data_supp.imageonsets_combinedSubs, [-1,5]*srate)));
- resp_meanEpochs_imageOnsets_combinedSubs = squeeze(mean(resp_epochs_imageOnsets_combinedSubs,2));
- % Calculate significance threshld using FDR correction
- %Odor Cue Task - Sniff Odor
- P_cueSniffOdor.P = G_z2p(stats_cueSniffOdor.Z{1});
- FDR_cueSniffOdor_Odor.FDR = fdr(P_cueSniffOdor.P(:));
- thresh_cueSniffOdor_Odor.thresh = G_p2z(FDR_cueSniffOdor_Odor.FDR);
- %Visual Cue Task - Image Onset
- P_visualCue_image.P = G_z2p(stats_imageOnsets.Z{1});
- FDR_visualCue_image.FDR = fdr(P_visualCue_image.P(:));
- thresh_visualCue_image.thresh = G_p2z(FDR_visualCue_image.FDR);
- %amplitude difference
- AmpChange_P= G_z2p(AmpChange_CueTasks_OdorVsImage.statsmap);
- AmpChange_FDR = fdr(AmpChange_P(:));
- AmpChange_thresh = G_p2z( AmpChange_FDR);
- % Plot spectrogram
- Time = -1 : 1/srate : 5;
- subplot(3,1,1)
- % subplot(1,3,1)
- G_Imagesc(stats_cueSniffOdor.Z{1},'yaxis',para.freq,'overlay',resp_meanEpochs_cueSniffOdor_combinedSubs,...
- 'xaxis', Time, 'xtick', [-0.3,0:0.5:5], 'threshold',thresh_cueSniffOdor_Odor.thresh,...
- 'ytick', [1,3,8,15,30,50,100,200],'Fontsize',14,'clim',[-10,10],'ctick', [-10,0,10],...
- 'ytick_precision',0,'xlabel','Time (s)','ylabel','Frequency (Hz)');
- xlim([0.69*srate,3.51*srate]);
- title('Odor');
- subplot(3,1,2)
- % subplot(1,3,2)
- G_Imagesc(stats_imageOnsets.Z{1},'yaxis',para.freq,'overlay',resp_meanEpochs_imageOnsets_combinedSubs,...
- 'xaxis', Time, 'xtick', [-0.3,0:0.5:5], 'threshold',thresh_visualCue_image.thresh,...
- 'ytick', [1,3,8,15,30,50,100,200],'Fontsize',14,'clim',[-10,10],'ctick', [-10,0,10],...
- 'ytick_precision',0,'xlabel','Time (s)','ylabel','Frequency (Hz)');
- xlim([0.69*srate,3.51*srate]);
- title('Image');
- subplot(3,1,3)
- % subplot(1,3,3)
- h=G_Imagesc(AmpChange_CueTasks_OdorVsImage.statsmap,'yaxis',para.freq,...
- 'xaxis', Time, 'xtick', [-0.3,0:0.5:5], 'threshold',AmpChange_thresh,...
- 'ytick', [1,3,8,15,30,50,100,200],'Fontsize',14,...
- 'clim',[-5,5],'ctick', [-5,0,5],...
- 'ytick_precision',0,'xlabel','Time (s)','ylabel','Frequency (Hz)');
- xlim([0.69*srate,3.51*srate]);
- title('Odor minus Image');
- % for k = 1:length(AmpChange_CueTasks_OdorVsImage.clust{1}.both.info.PixelIdxList)
- % mask = zeros(AmpChange_CueTasks_OdorVsImage.clust{1}.both.info.ImageSize);
- % if AmpChange_CueTasks_OdorVsImage.clust{1}.both.statssum_pval(k) < 0.05
- % mask(AmpChange_CueTasks_OdorVsImage.clust{1}.both.info.PixelIdxList{k}) = 1;
- % G_Outline_Pixels(h,mask,'linecolor','m','linewidth',1);
- % end
- % end
- % set(gcf,'pos',[367 571 1722 411]); % For 3 columns x 1 row
- set(gcf,'pos',[1000 281 507 957]); % For 1 column x 3 rows
- xlim([0.69*srate,3.51*srate]);
- ax = gca; ax.LineWidth = 1; ax.FontSize = 16;
- %% Fig S2A - Image onsets no sniff
- ts = data_supp.lfp_visualCue_combinedSubs;
- sniffonset_conds = { data_supp.imageonsets_noSniff_combinedSubs };
- para = [];
- para.freq = logspace( log10( 1), log10( 200), 100); % center frequencies for filtering
- para.bandwidth = logspace( log10( 2), log10( 30), 100); % bandwidth of each center frequency
- para.srate = srate; % sampling rate, in Hz
- para.events = sniffonset_conds; % in samples
- para.epoch = [-1, 5]; % in seconds, relative to events
- para.baseline = [-0.6, -0.1]; % in seconds, relative to events
- para.smooth_win = 0.01; % temporal smoothing, in secondsj
- para.nbpermuts = 10000; % number of permutations,
- para.measure = 'amplitude'; % or 'power'
- para.baseline_condition = []; % which condition to use as baseline (empty for just before each of multiple conditions)
- para.trl = 'mean'; % 'mean' o r'median' value across trials
- [stats_imageOnsetsNoSniff, epoch_time_imageOnsetsNoSniff, ev_epochs_imageOnsetsNoSniff, ~, sd_imageOnsetsNoSniff] = PermutAmpChange_Commonbaseline(ts, para);
- % Respiratory overlay
- resp_epochs_imageOnsetsNoSniff_combinedSubs = squeeze(zscore(G_EpochTS(data_supp.resp_visualCue_combinedSubs, data_supp.imageonsets_noSniff_combinedSubs, [-1,5]*srate)));
- resp_meanEpochs_imageOnsetsNoSniff_combinedSubs = squeeze(mean(resp_epochs_imageOnsetsNoSniff_combinedSubs,2));
- % Significance threshold
- P_imageOnsetsNoSniff.P = G_z2p(stats_imageOnsetsNoSniff.Z{1});
- FDR_imageOnsetsNoSniff.FDR = fdr(P_imageOnsetsNoSniff.P(:));
- thresh_imageOnsetsNoSniff.thresh = G_p2z(FDR_imageOnsetsNoSniff.FDR);
- % Plot spectrogram
- G_Imagesc(stats_imageOnsetsNoSniff.Z{1},'yaxis',para.freq,'overlay',resp_meanEpochs_imageOnsetsNoSniff_combinedSubs,...
- 'xaxis', Time, 'xtick', [-0.3,0:0.5:5], 'threshold',thresh_imageOnsetsNoSniff.thresh,...
- 'ytick', [1,3,8,15,30,50,100,200],'Fontsize',14,'clim',[-10,10],'ctick', [-10,0,10],...
- 'ytick_precision',0,'xlabel','Time (s)','ylabel','Frequency (Hz)');
- %% Fig S3 - Difference spectrogram for odor vs. air on detection task
- % Calculate Subject-wiser Spectrograms at Gamma Frequencies
- for sub = 1:num_subs
- ts = data_supp.lfp_detect{sub};
- sniffonset_conds = { data_supp.sniffonsets_odor{sub}, data_supp.sniffonsets_air{sub} };
- para = [];
- % para.freq = logspace( log10( 1), log10( 200), 100); % center frequencies for filtering
- % para.bandwidth = logspace( log10( 2), log10( 30), 100); % bandwidth of each center frequency
- para.freq = linspace( 35, 175, 40); % center frequencies for filtering
- para.bandwidth = linspace( 10, 35, length(para.freq)); % bandwidth of each center frequency
- para.srate = srate; % sampling rate, in Hz
- para.events = sniffonset_conds; % in samples
- para.epoch = [-1, 5]; % in seconds, relative to events
- para.baseline = [-0.6, -0.1]; % in seconds, relative to events
- para.smooth_win = 0.01; % temporal smoothing, in secondsj
- para.nbpermuts = 10000; % number of permutations,
- para.measure = 'amplitude'; % or 'power'
- para.baseline_condition = 1; % which condition to use as baseline (empty for just before each of multiple conditions)
- para.trl = 'mean'; % 'mean' o r'median' value across trials
- [stats{sub}, epoch_time{sub}, ev_epochs{sub}, ~, sd{sub}] = PermutAmpChange_Commonbaseline(ts, para);
- end
- z_odor = []; z_air = [];
- for sub = 1:num_subs
- z_odor(sub,:,:) = stats{sub}.Z{1};
- z_air(sub,:,:) = stats{sub}.Z{2};
- end
- % Average spectrogram output across subjects
- z_mean_odor = squeeze(mean(z_odor,1));
- z_mean_air = squeeze(mean(z_air,1));
- % Calculate amplitude difference between Passive inhale vs. Cued sniff combined subjects
- % Combine ev_epochs across subjects
- ev_epochs_6normosmics_odor = cat( 3,ev_epochs{1}{1},ev_epochs{2}{1},ev_epochs{3}{1},ev_epochs{4}{1},ev_epochs{5}{1},ev_epochs{6}{1} );
- ev_epochs_6normosmics_air = cat( 3,ev_epochs{1}{2},ev_epochs{2}{2},ev_epochs{3}{2},ev_epochs{4}{2},ev_epochs{5}{2},ev_epochs{6}{2} );
- mat = cat(3,ev_epochs_6normosmics_odor,ev_epochs_6normosmics_air);
- mat = permute(mat, [3 1 2]);
- g = [ones(size(ev_epochs_6normosmics_odor,3),1) ; 2*ones(size(ev_epochs_6normosmics_air,3),1)];
- AmpChange_odorVair_comBase = G_PowChange_Clust(mat, g, epoch_time{sub}, ...
- para.freq, 'baseline', para.baseline,'db_transf', 'no','common_bs','yes');
- % Significance threshold
- AmpChange_P = []; AmpChange_FDR=[]; AmpChange_thresh=[];
- AmpChange_P = G_z2p(AmpChange_odorVair_comBase.statsmap);
- AmpChange_FDR = fdr(AmpChange_P(:));
- AmpChange_thresh = G_p2z( AmpChange_FDR)
- % Plot difference spectrogram
- h=G_Imagesc(AmpChange_odorVair_comBase.statsmap,'yaxis',para.freq,...
- 'xaxis', Time, 'xtick', [-0.3,0:0.5:5],'threshold',AmpChange_thresh,...
- 'ytick', 35:10:175,'Fontsize',14,...
- 'clim',[-4,4],'ctick', [-4,-2,0,2,4],...
- 'ytick_precision',0);
- for k = 1:length(AmpChange_odorVair_comBase.clust{1}.both.info.PixelIdxList)
- mask = zeros(AmpChange_odorVair_comBase.clust{1}.both.info.ImageSize);
- if AmpChange_odorVair_comBase.clust{1}.both.statssum_pval(k) < 0.05
- mask(AmpChange_odorVair_comBase.clust{1}.both.info.PixelIdxList{k}) = 1;
- G_Outline_Pixels(h,mask,'linecolor','k','LineWidth',1.5);
- end
- end
- xlim([0.69*srate,3.51*srate]);
- title('Difference');
- set(gcf,'pos',[334 553 1407 299]);
- %% Fig S4 - controlling for sniff features
- num_subs=6;
- numTrials_passive = cellfun(@length,data_supp.exhale_onsets_passive_bySub);
- numTrials_cuedSniff = cellfun(@length,data_supp.exhale_onsets_cuedSniff_bySub);
- inhaleDur_passive=[];inhaleDur_cuedSniff=[]; inhalePk_CuedSniff_bySub=[];
- time2inhalePk_ind_CuedSniff_bySub=[]; inhalePk_Passive_bySub=[];
- time2inhalePk_ind_Passive_bySub=[]; time2inhalePk_ms_Passive=[]; time2inhalePk_ms_CuedSniff=[];
- for sub = 1:num_subs
- inhaleDur_passive{sub} = (data_supp.exhale_onsets_passive_bySub{sub} - data_supp.sniffonsets_Passive{sub}) / srate;
- inhaleDur_cuedSniff{sub} = (data_supp.exhale_onsets_cuedSniff_bySub{sub} - data_supp.sniffonsets_CuedSniff{sub}) / srate;
- for i = 1:numTrials_cuedSniff(sub)
- [inhalePk_CuedSniff_bySub{sub}(i,1), time2inhalePk_ind_CuedSniff_bySub{sub}(i,1)] = max(resp_epochs_CuedSniff_bySub{sub}(500:1000,i));
- end
- for i = 1:numTrials_passive(sub)
- [inhalePk_Passive_bySub{sub}(i,1), time2inhalePk_ind_Passive_bySub{sub}(i,1)] = max(resp_epochs_Passive_bySub{sub}(500:1000,i));
- end
- time2inhalePk_ms_Passive{sub} = time2inhalePk_ind_Passive_bySub{sub} / srate * 1000;
- time2inhalePk_ms_CuedSniff{sub} = time2inhalePk_ind_CuedSniff_bySub{sub} / srate * 1000;
- end
- %% Fig S4B - histograms of sniff features
- % Check how variables look with histograms for each subject
- % Passive
- tiledlayout(3,2)
- for sub = 1:num_subs
- nexttile
- histogram(inhaleDur_passive{sub})
- % histogram(inhalePk_Passive_bySub{sub})
- % histogram(time2inhalePk_ms_Passive{sub})
- sgtitle('passive');
- end
- figure
- for sub = 1:num_subs
- nexttile
- histogram(inhaleDur_cuedSniff{sub})
- % histogram(inhalePk_CuedSniff_bySub{sub})
- % histogram(time2inhalePk_ms_CuedSniff{sub})
- sgtitle('intentional');
- end
- sub_titles = {'P1','P2','P3','P4','P5','P6'};
- tiledlayout(3,2)
- for sub = 1:num_subs
- nexttile
- histogram(inhaleDur_passive{sub},'FaceColor',[1 0.6 0])
- hold on
- histogram(inhaleDur_cuedSniff{sub},'FaceColor',[0 0.6 1])
- if sub == 1
- ylabel('Trial count');
- legend({'Passive','Intentional'},'Location','northwest');
- end
- if sub == 5
- xlabel('Inhale duration (s)');
- end
- ax=gca; ax.FontSize = 14; ax.TickDir = 'out'; ax.LineWidth = 1; box off
- title(sub_titles{sub});
- end
- set(gcf,'pos',[300 300 859 702]);
- %% Fig S4A - summary statistics of sniff kinematics
- % Data structure for mixed effects model
- nSub = 6;
- DV1_all = [];
- DV2_all = [];
- DV3_all = [];
- Condition = [];
- Subject = [];
- for s = 1:nSub
- % ===== Condition 1 =====
- dv1 = inhaleDur_passive{s}(:);
- dv2 = inhalePk_Passive_bySub{s}(:);
- dv3 = time2inhalePk_ms_Passive{s}(:);
- % Sanity check (important!)
- assert(numel(dv1)==numel(dv2) && numel(dv1)==numel(dv3), ...
- 'Mismatch in trial counts for subject %d, condition C1', s);
- n = numel(dv1);
- DV1_all = [DV1_all; dv1];
- DV2_all = [DV2_all; dv2];
- DV3_all = [DV3_all; dv3];
- Condition = [Condition; repmat("C1", n, 1)];
- Subject = [Subject; repmat(s, n, 1)];
- % ===== Condition 2 =====
- dv1 = inhaleDur_cuedSniff{s}(:);
- dv2 = inhalePk_CuedSniff_bySub{s}(:);
- dv3 = time2inhalePk_ms_CuedSniff{s}(:);
- assert(numel(dv1)==numel(dv2) && numel(dv1)==numel(dv3), ...
- 'Mismatch in trial counts for subject %d, condition C2', s);
- n = numel(dv1);
- DV1_all = [DV1_all; dv1];
- DV2_all = [DV2_all; dv2];
- DV3_all = [DV3_all; dv3];
- Condition = [Condition; repmat("C2", n, 1)];
- Subject = [Subject; repmat(s, n, 1)];
- end
- % Build the table
- tbl = table;
- tbl.Subject = categorical(Subject);
- tbl.Condition = categorical(Condition);
- tbl.duration = DV1_all;
- tbl.peak = DV2_all;
- tbl.timeToPeak = DV3_all;
- tbl.Condition = reordercats(tbl.Condition,{'C1','C2'});
- % Sanity checks
- height(tbl)
- varfun(@numel,tbl,'InputVariables','duration','GroupingVariables',{'Subject','Condition'})
- varfun(@numel, tbl,'InputVariables','peak','GroupingVariables',{'Subject','Condition'})
- varfun(@numel, tbl,'InputVariables','timeToPeak','GroupingVariables',{'Subject','Condition'})
- % % Baseline mixed-effects model - Is there a fixed effect of Condition
- % accounting for subject-to-subject differences?
- % For each dependent variable, start with a random intercept model
- lme1 = fitlme(tbl, 'duration ~ Condition + (1|Subject)')
- % If each subject may respond differently to condition manipution,
- % include random slopes
- lme1_2 = fitlme(tbl, 'duration ~ Condition + (Condition|Subject)')
- % Compare models
- compare(lme1,lme1_2)
- % The small pvalue and large likelihood ratio stat show that including
- % random slopes is better, but stick with
- anova(lme1_2)
- anova(lme1)
- % Effect sizes
- beta = lme1.Coefficients.Estimate(2)
- sd_resid = sqrt(lme1.MSE)
- d = beta / sd_resid
- beta = lme1_2.Coefficients.Estimate(2)
- sd_resid = sqrt(lme1_2.MSE)
- d = beta / sd_resid
- % % Handling 3 dependent variables
- % Separate models + correction
- % Fit one model per DV:
- lme1 = fitlme(tbl, 'duration ~ Condition + (1|Subject)');
- lme2 = fitlme(tbl, 'peak ~ Condition + (1|Subject)');
- lme3 = fitlme(tbl, 'timeToPeak ~ Condition + (1|Subject)');
- % Correct for multiple testing
- p = [lme1.Coefficients.pValue(2), lme2.Coefficients.pValue(2), lme3.Coefficients.pValue(2)];
- p_fdr = mafdr(p,'BHFDR',true);
- % Visualization
- tiledlayout(1,3)
- nexttile
- boxchart(tbl,"Condition","duration",'MarkerStyle','none','BoxFaceColor','k')
- ax=gca; ax.TickDir='out'; ax.LineWidth=1; ax.FontSize=14; box off
- ylabel('Duration (s)');
- ax.XTickLabel = {'Passive','Intentional'};
- xlabel('');
- hold on
- for s = categories(tbl.Subject)'
- idx = tbl.Subject == s{1};
- means = groupsummary(tbl(idx,:), 'Condition', 'mean', 'duration');
- plot([1 2], means.mean_duration, '-o', 'Color',[.7 .7 .7]);
- end
- nexttile
- boxchart(tbl,"Condition","peak",'MarkerStyle','none','BoxFaceColor','k')
- ax=gca; ax.TickDir='out'; ax.LineWidth=1; ax.FontSize=14; box off
- ylabel('Peak airflow (au)');
- ax.XTickLabel = {'Passive','Intentional'};
- xlabel('');
- hold on
- for s = categories(tbl.Subject)'
- idx = tbl.Subject == s{1};
- means = groupsummary(tbl(idx,:), 'Condition', 'mean', 'peak');
- plot([1 2], means.mean_peak, '-o', 'Color',[.7 .7 .7]);
- end
- nexttile
- boxchart(tbl,"Condition","timeToPeak",'MarkerStyle','none','BoxFaceColor','k')
- ax=gca; ax.TickDir='out'; ax.LineWidth=1; ax.FontSize=14; box off
- ylabel('Time to peak (ms)');
- ax.XTickLabel = {'Passive','Intentional'};
- xlabel('');
- hold on
- for s = categories(tbl.Subject)'
- idx = tbl.Subject == s{1};
- means = groupsummary(tbl(idx,:), 'Condition', 'mean', 'timeToPeak');
- plot([1 2], means.mean_timeToPeak, '-o', 'Color',[.7 .7 .7]);
- end
- set(gcf,'pos',[300 300 1658 508]);
- %% Fig S4C - spectrogram of subset of passive inhales matched for duration of intentional sniffs
- % 1b. Bin intentional sniffs and passive inhales by overlapping duration within each subject
- % Apart from Subject 2, all subjects show increase in duration for
- % intentional vs. passive sniff.
- % So try sorting sniff duration for each condition, and take shortest
- % duration bin from each subject, except for subject 2 take longest
- % duration bin
- % Try for 20 subsampled trials of passive inhales for each subject
- % Ascending order by default
- [inhaleDur_passive_bySub_sorted, inhaleDur_passive_bySub_sortInd] = cellfun(@sort,inhaleDur_passive,'UniformOutput',false);
- % Bin sniff onsets by the 20 trials of shortest duration for 5 of 6 subs
- sub_inds = [1,3,4,5,6];
- for i = 1:length(sub_inds)
- sniffonsets_subset_passive(:,sub_inds(i)) = sniffonsets_Passive{sub_inds(i)}(inhaleDur_passive_bySub_sortInd{sub_inds(i)}(1:20));
- end
- sniffonsets_subset_passive(:,2) = sniffonsets_Passive{2}(inhaleDur_passive_bySub_sortInd{2}(end-19:end));
- % Caclulate spectrogram by subjects for the subset of passive inhales
- for sub = 1:num_subs
- ts = lfp_Passive{sub};
- sniffonset_conds = { sniffonsets_subset_passive(:,sub) };
- para = [];
- para.freq = logspace( log10( 1), log10( 200), 100); % center frequencies for filtering
- para.bandwidth = logspace( log10( 2), log10( 30), 100); % bandwidth of each center frequency
- para.srate = srate; % sampling rate, in Hz
- para.events = sniffonset_conds; % in samples
- para.epoch = [-1, 5]; % in seconds, relative to events
- para.baseline = [-0.6, -0.1]; % in seconds, relative to events
- para.smooth_win = 0.01; % temporal smoothing, in secondsj
- para.nbpermuts = 10000; % number of permutations,
- para.measure = 'amplitude'; % or 'power'
- para.baseline_condition = []; % which condition to use as baseline (empty for just before each of multiple conditions)
- para.trl = 'mean'; % 'mean' o r'median' value across trials
- [stats_passive{sub}, epoch_time_passive{sub}, ev_epochs_passive{sub}, ~, sd_passive{sub}] = PermutAmpChange_Commonbaseline(ts, para);
- end
- save('spectro_passive_subsetMatchDur_bySub','para','stats_passive','ev_epochs_passive','epoch_time_passive','sd_passive','-v7.3');
- % Combined subs spectrogram for subset of Passive Inhales
- % % Subset is for 20 trials that are shortest duration inhale which overlap
- % with duration of intentional sniffs, except for sub2 they are the fastest
- % Load in previously calculated cued sniff spectrograms to compare
- % Should have variable stats_6normosmic_cuedSniff
- for sub = 1:6 % 6 normosmics
- z_cuedSniff(sub,:,:) = data_supp.stats_6normosmic_cuedSniff{sub}.Z{1};
- z_passiveSubset(sub,:,:) = stats_passive{sub}.Z{1};
- end
- % Average spectrogram output across subjects
- z_mean_cuedSniff = squeeze(mean(z_cuedSniff,1));
- z_mean_passiveSubset = squeeze(mean(z_passiveSubset,1));
- P.P_passive = G_z2p(z_mean_passiveSubset);
- FDR.FDR_passive = fdr(P.P_passive(:));
- thresh.thresh_passive = G_p2z(FDR.FDR_passive);
- P = []; FDR = []; thresh=[];
- P.P_cuedSniff = G_z2p(z_mean_cuedSniff);
- FDR.FDR_cuedSniff = fdr(P.P_cuedSniff(:));
- thresh.thresh_cuedSniff = G_p2z(FDR.FDR_cuedSniff);
- for sub = 1:num_subs
- resp_epochs_passiveSubset_bySub{sub} = squeeze(G_EpochTS(resp_Passive{sub},sniffonsets_subset_passive(:,sub),[-1,5]*srate));
- resp_epochs_cuedSniff_bySub{sub} = squeeze(G_EpochTS(resp_CuedSniff{sub},sniffonsets_CuedSniff{sub},[-1,5]*srate));
- end
- resp_epochs_passiveSubset_acrossSubs = cell2mat(resp_epochs_passiveSubset_bySub);
- resp_mean_epoch_passiveSubset = mean(resp_epochs_passiveSubset_acrossSubs,2);
- resp_epochs_cuedSniff_acrossSubs = cell2mat(resp_epochs_cuedSniff_bySub);
- resp_mean_epoch_cuedSniff = mean(resp_epochs_cuedSniff_acrossSubs,2);
- % Calculate amplitude difference between Passive inhale vs. Cued sniff combined subjects
- % Combine ev_epochs across subjects
- ev_epochs_6normosmic_cuedSniff = data_supp.ev_epochs_6normosmic_cuedSniff;
- ev_epochs_6normosmics_cuedSniff = cat( 3,ev_epochs_6normosmic_cuedSniff{1}{1},ev_epochs_6normosmic_cuedSniff{2}{1},ev_epochs_6normosmic_cuedSniff{3}{1},...
- ev_epochs_6normosmic_cuedSniff{4}{1},ev_epochs_6normosmic_cuedSniff{5}{1},ev_epochs_6normosmic_cuedSniff{6}{1} );
- ev_epochs_6normosmics_passiveSubset = cat( 3,ev_epochs_passive{1}{1},ev_epochs_passive{2}{1},ev_epochs_passive{3}{1},...
- ev_epochs_passive{4}{1},ev_epochs_passive{5}{1},ev_epochs_passive{6}{1} );
- tic
- mat = cat(3,ev_epochs_6normosmics_cuedSniff,ev_epochs_6normosmics_passiveSubset);
- mat = permute(mat, [3 1 2]);
- g = [ones(size(ev_epochs_6normosmics_cuedSniff,3),1) ; 2*ones(size(ev_epochs_6normosmics_passiveSubset,3),1)];
- AmpChange_cuedVsPassiveSubsetMatchedDur = G_PowChange_Clust(mat, g, epoch_time_passive{1}, para.freq, 'baseline', para.baseline,'db_transf', 'no','common_bs','yes');
- save('AmpChange_cuedVsPassiveSubsetMatchedDur','AmpChange_cuedVsPassiveSubsetMatchedDur','para','-v7.3');
- toc
- AmpChange_P = []; AmpChange_FDR=[]; AmpChange_thresh=[];
- AmpChange_P = G_z2p(AmpChange_cuedVsPassiveSubsetMatchedDur.statsmap);
- AmpChange_FDR = fdr(AmpChange_P(:));
- AmpChange_thresh = G_p2z( AmpChange_FDR)
- % Plot mean spectrogram for Cued Sniff vs. Passive Inhale averaged across subjects
- Time = -1 : 1/srate : 5;
- tiledlayout(1,3)
- nexttile
- [h, c, clusts, clustinfo]=G_Imagesc(z_mean_cuedSniff,'yaxis',freq,...
- 'xaxis', Time, 'xtick', [-0.3,0:0.5:5],'threshold',thresh.thresh_cuedSniff,...
- 'ytick', [1,2,3,8,15,30,50,100,200],'Fontsize',16,'overlay',resp_mean_epoch_cuedSniff,...
- 'clim',[-3,3],'ctick', [-3,0,3],...
- 'ytick_precision',0,'xlabel','Time (s)','ylabel','Frequency (Hz)');
- ax=gca;
- ax.FontSize = 16; ax.LineWidth = 1; box off
- xlim([0.69*srate,3.51*srate]);
- title('Intentional Sniff');
- colorbar off
- nexttile
- G_Imagesc(z_mean_passiveSubset,'yaxis',freq,...
- 'xaxis', Time, 'xtick', [-0.3,0:0.5:5],'threshold',thresh.thresh_passive,...
- 'ytick', [1,2,3,8,15,30,50,100,200],'Fontsize',16,'overlay',resp_mean_epoch_passiveSubset,'overlay_ref',resp_mean_epoch_cuedSniff,...
- 'clim',[-3,3],'ctick', [-3,0,3],'clabel','Amplitude (z score)',...
- 'ytick_precision',0);
- xlim([0.69*srate,3.51*srate]);
- title('Passive Inhale');
- ylabel('');
- xlabel('');
- ax=gca;
- ax.FontSize = 16; ax.LineWidth = 1; box off
- % set(gcf,'pos',[758 784 1047 478]); % without difference plot
- nexttile
- h=G_Imagesc(AmpChange_cuedVsPassiveSubsetMatchedDur.statsmap,'yaxis',para.freq,...
- 'xaxis', Time, 'xtick', [-0.3,0:0.5:5], ...
- 'ytick', [1,2,8,15,30,50,100,200],'Fontsize',16,...
- 'clim',[-3,3],'ctick', [-3,0,3],'clabel','Amplitude Difference (z score)',...
- 'ytick_precision',0);
- xlabel(''); ylabel('');
- title('Difference');
- for k = 1:length(AmpChange_cuedVsPassiveSubsetMatchedDur.clust{1}.both.info.PixelIdxList)
- mask = zeros(AmpChange_cuedVsPassiveSubsetMatchedDur.clust{1}.both.info.ImageSize);
- if AmpChange_cuedVsPassiveSubsetMatchedDur.clust{1}.both.statssum_pval(k) < 0.05
- mask(AmpChange_cuedVsPassiveSubsetMatchedDur.clust{1}.both.info.PixelIdxList{k}) = 1;
- G_Outline_Pixels(h,mask,'linecolor','k','LineWidth',1.5);
- end
- end
- xlim([0.69*srate,3.51*srate]);
- set(gcf,'pos',[758 784 1499 478]); % With difference plot
- ax.FontSize = 16; ax.LineWidth = 1; box off
- %% Fig S4D to E
- ph_epochs_byRespPhaseBin = data_supp.ph_epochs_byRespPhaseBin;
- ph_epochs_byRespPhase_combinedSubs{1} = cat(3,ph_epochs_byRespPhaseBin{1}{1}(:,:,inhaleDur_passive_bySub_sortInd{1}),ph_epochs_byRespPhaseBin{1}{2}(:,:,inhaleDur_passive_bySub_sortInd{2}),...
- ph_epochs_byRespPhaseBin{1}{3}(:,:,inhaleDur_passive_bySub_sortInd{3}),ph_epochs_byRespPhaseBin{1}{4}(:,:,inhaleDur_passive_bySub_sortInd{4}),...
- ph_epochs_byRespPhaseBin{1}{5}(:,:,inhaleDur_passive_bySub_sortInd{5}),ph_epochs_byRespPhaseBin{1}{6}(:,:,inhaleDur_passive_bySub_sortInd{6}));
- ph_epochs_byRespPhase_combinedSubs{2} = cat(3,ph_epochs_byRespPhaseBin{2}{1},ph_epochs_byRespPhaseBin{2}{2},ph_epochs_byRespPhaseBin{2}{3},...
- ph_epochs_byRespPhaseBin{2}{4},ph_epochs_byRespPhaseBin{2}{5},ph_epochs_byRespPhaseBin{2}{6});
- ph_epochs_cuedSniff = data_supp.ph_epochs_byRespPhase_combinedSubs{2};
- ph_epochs_passive = cat(3,ph_epochs_byRespPhaseBin{1}{1},ph_epochs_byRespPhaseBin{1}{2},...
- ph_epochs_byRespPhaseBin{1}{3},ph_epochs_byRespPhaseBin{1}{4},...
- ph_epochs_byRespPhaseBin{1}{5},ph_epochs_byRespPhaseBin{1}{6});
- param.freq = logspace( log10( 1), log10( 100), 80); % logarithmic steps in frequency for filtering
- param.bandwidth = logspace( log10( 2), log10( 20), 80); % logarithmic steps in bandwidth for filtering
- % Calculate ITPC difference between combined subs respiratory-normalized conditions
- % % Calculate ITPC difference between Cued sniff and Passive
- ITPCdiff_normResp_combinedSubs = data_supp.ITPC_normResp_combinedSubs{2} - data_supp.ITPC_normResp_combinedSubs{1};
- ITPCdiff_fisherZ_normResp_combinedSubs = atanh(ITPCdiff_normResp_combinedSubs);
- % % Permutation of ITPC over circularly shifted data, 1000 iterations
- numpts = size(ph_epochs_byRespPhase_combinedSubs{2},2);
- num_perms = 1000;
- for perm = 1:num_perms
- fprintf( 'Permutation: %d/%d \r', perm, num_perms);
- ph_tmp_passive=ph_epochs_byRespPhase_combinedSubs{1};
- ph_tmp_cuedSniff=ph_epochs_byRespPhase_combinedSubs{2};
- for trial = 1:size(ph_epochs_byRespPhase_combinedSubs{1},3)
- shift_amount = circshift( 1:numpts, randsample( 1:numpts, 1));
- ph_tmp_passive( :, :, trial) = ph_epochs_byRespPhase_combinedSubs{1}( :, shift_amount, trial );
- end
- for trial = 1:size(data_supp.ph_epochs_byRespPhase_combinedSubs{2},3)
- shift_amount = circshift( 1:numpts, randsample( 1:numpts, 1));
- ph_tmp_cuedSniff( :, :, trial) = ph_epochs_byRespPhase_combinedSubs{2}( :, shift_amount, trial);
- end
- permuteITPC_passive_tmp = []; permuteITPC_cuedSniff_tmp = [];
- permuteITPC_passive_tmp(:,:,perm) = squeeze(abs(mean(exp(1i * ph_tmp_passive), 3)));
- permuteITPC_cuedSniff_tmp(:,:,perm) = squeeze(abs(mean(exp(1i * ph_tmp_cuedSniff), 3)));
- permuteITPCdiff_normResp_combinedSubs(:,:,perm) = permuteITPC_cuedSniff_tmp(:,:,perm) - permuteITPC_passive_tmp(:,:,perm);
- permuteITPCdiff_fisherZ_passiveVcuedsniff_normResp(:,:,perm) = atanh(permuteITPCdiff_normResp_combinedSubs(:,:,perm));
- end
- % % % Cluster-based correction
- [h_clust_normResp_combinedSubs_ITPCdiff, p_clust_normResp_combinedSubs_ITPCdiff, clustinfo_normResp_combinedSubs_ITPCdiff] = cluster_test(ITPCdiff_fisherZ_normResp_combinedSubs, permuteITPCdiff_fisherZ_passiveVcuedsniff_normResp);
- % Plot ITPC difference between Cued Sniff and passive with Resp Overlay
- % Respiratory epochs for overlay
- resp_epochs_byRespPhaseBin = data_supp.resp_epochs_byRespPhaseBin;
- resp_epochs_byRespPhaseBin_allsubs_cuedSniff = squeeze(cat(3,resp_epochs_byRespPhaseBin{2}{1},resp_epochs_byRespPhaseBin{2}{2},resp_epochs_byRespPhaseBin{2}{3},...
- resp_epochs_byRespPhaseBin{2}{4},resp_epochs_byRespPhaseBin{2}{5},resp_epochs_byRespPhaseBin{2}{6}));
- resp_meanEpoch_byRespPhaseBin_cuedSniff = mean(resp_epochs_byRespPhaseBin_allsubs_cuedSniff,2);
- resp_epochs_byRespPhaseBin_allsubs_Passive = squeeze(cat(3,resp_epochs_byRespPhaseBin{1}{1},resp_epochs_byRespPhaseBin{1}{2},resp_epochs_byRespPhaseBin{1}{3},...
- resp_epochs_byRespPhaseBin{1}{4},resp_epochs_byRespPhaseBin{1}{5},resp_epochs_byRespPhaseBin{1}{6}));
- resp_meanEpoch_byRespPhaseBin_Passive = mean(resp_epochs_byRespPhaseBin_allsubs_Passive,2);
- [redblue,red,blue]=CustomColormap;
- % subplot(3,2,sub);
- h=G_Imagesc(ITPCdiff_fisherZ_normResp_combinedSubs,'yaxis',param.freq,...
- 'ytick',[1,2,3,8,15,30,50,100],'xtick',1:50:202,'ytick_precision',1,'clim',[0,0.5],...
- 'ylabel','Frequency (Hz)','xlabel','','overlay',resp_meanEpoch_byRespPhaseBin_cuedSniff);
- title(sub_IDs{sub});
- for k = 1:length(clustinfo_normResp_combinedSubs_ITPCdiff.pos_clusters)
- if clustinfo_normResp_combinedSubs_ITPCdiff.pos_clusters(k).p < 0.05
- G_Outline_Pixels(h,clustinfo_normResp_combinedSubs_ITPCdiff.pos_clusters(k).inds,'linecolor','k','linewidth',1.5);
- end
- end
- colormap(red);
- title('Intentional Sniff vs. Passive Nasal Inhalation');
- ax=gca;
- ax.XTickLabel={'-\pi','','0','','\pi'};
- ax.FontSize = 16;
- ax.XLabel.String='Respiratory Phase';
- cb=colorbar;
- cb.Label.String='ITPC difference value (Fisher-transformed)';
- cb.Limits = [0,0.5];
- cb.Ticks = 0:0.25:1;
- % cb.Label.String='ITPCz';
- % cb.Limits = [0,16];
- % %% Plot combined subjects cued sniff and passive normalized by respiratory phase
- [redblue,red,blue]=CustomColormap;
- tiledlayout(1,2)
- nexttile
- h=G_Imagesc(ITPC_normResp_combinedSubs{2},'yaxis',param.freq,...
- 'ytick',[1,2,3,8,15,30,50,100],'xtick',1:50:202,'ytick_precision',1,'clim',[0,0.5],...
- 'ylabel','Frequency (Hz)','xlabel','','overlay',resp_meanEpoch_byRespPhaseBin_cuedSniff);
- title(sub_IDs{sub});
- for k = 1:length(clustinfo_normResp_combinedSubs{2}.pos_clusters)
- if clustinfo_normResp_combinedSubs{2}.pos_clusters(k).p < 0.05
- G_Outline_Pixels(h,clustinfo_normResp_combinedSubs{2}.pos_clusters(k).inds,'linecolor','k','linewidth',1.5);
- end
- end
- colormap(red);
- title('Intentional Sniff');
- ax=gca;
- ax.XTickLabel={'-\pi','','0','','\pi'};
- ax.FontSize = 16;
- ax.XLabel.String='Respiratory Phase';
- cb=colorbar;
- cb.Label.String='ITPC';
- cb.Limits = [0,0.5];
- cb.Ticks = 0:0.25:1;
- colorbar off
- % Plot combined subjects passive normalized by respiratory phase
- [redblue,red,blue]=CustomColormap;
- nexttile
- % subplot(3,2,sub);
- h=G_Imagesc(ITPC_normResp_combinedSubs{1},'yaxis',param.freq,...
- 'ytick',[1,2,3,8,15,30,50,100],'xtick',1:50:202,'ytick_precision',1,'clim',[0,0.5],...
- 'ylabel','Frequency (Hz)','xlabel','','overlay',resp_meanEpoch_byRespPhaseBin_Passive);
- title(sub_IDs{sub});
- for k = 1:length(clustinfo_normResp_combinedSubs{1}.pos_clusters)
- if clustinfo_normResp_combinedSubs{1}.pos_clusters(k).p < 0.05
- G_Outline_Pixels(h,clustinfo_normResp_combinedSubs{1}.pos_clusters(k).inds,'linecolor','k','linewidth',1.5);
- end
- end
- colormap(red);
- title('Passive Inhalation');
- ax=gca;
- ax.XTickLabel={'-\pi','','0','','\pi'};
- ax.FontSize = 16;
- ax.XLabel.String='Respiratory Phase';
- cb=colorbar;
- cb.Label.String='ITPC';
- cb.Limits = [0,0.5];
- cb.Ticks = 0:0.25:1;
- xlabel('');
- ylabel('');
- % cb.Label.String='ITPCz';
- % cb.Limits = [0,16];
- % saveas(gcf,'ITPC_Passive_normResp_combined6subs','fig');
- % saveas(gcf,'ITPC_Passive_normResp_combined6subs','png');
- set(gcf,'pos',[537 818 1023 420]);
- %% ITPC Permuted Distribution for Cued sniff vs. Passive inhale Subset matched inhale dur
- total_trials_cued = size(ph_epochs_cuedSniff,3);
- total_trials_passive = size(ph_epochs_passive,3);
- freq = logspace( log10( 1), log10( 100), 80); % logarithmic steps in frequency for filtering
- theta_ind = find(freq>=2&freq<=8);
- tic
- for i = 1:1000
- % rand_passive_inds = randperm( total_trials, num_fixedTrials ); % old
- rand_inds_cued = randi( total_trials_cued, [1, total_trials_cued] );
- ph_epochs_resample_cuedSniff = ph_epochs_cuedSniff(:,:,rand_inds_cued);
- ITPC_resample_cuedSniff{i} = squeeze(abs(mean(exp(1i * ph_epochs_resample_cuedSniff), 3))); % length of mean vector over trials (dimension 3 of phase mat) = ITPC
- ITPC_distr_maxTheta_cuedSniff(i) = max(ITPC_resample_cuedSniff{i}(theta_ind,:),[],'all');
- rand_inds_passive = randi( total_trials_passive, [1, total_trials_passive] );
- ph_epochs_resample_passive = ph_epochs_passive(:,:,rand_inds_passive);
- ITPC_resample_passive{i} = squeeze(abs(mean(exp(1i * ph_epochs_resample_passive), 3))); % length of mean vector over trials (dimension 3 of phase mat) = ITPC
- ITPC_distr_maxTheta_passive(i) = max(ITPC_resample_passive{i}(theta_ind,:),[],'all');
- end
- toc
- % Plot resampled distribution of passive vs. intentional sniff
- histogram(ITPC_distr_maxTheta_cuedSniff,32,'FaceColor',[0 0.6 1])
- hold on
- histogram(ITPC_distr_maxTheta_passive,32,'FaceColor',[1 0.6 0])
- legend('Intentional Sniff', 'Passive Inhale','box','off');
- ax=gca; ax.TickDir = 'out'; ax.LineWidth=1; box off; ax.FontSize=16;
- xlabel('ITPC');
- ylabel('Resample #');
- saveas(gcf,'ITPC_resampled_cuedVsPassiveSubsetMatchedDur','fig');
- exportgraphics(gcf,'ITPC_resampled_cuedVsPassiveSubsetMatchedDur.pdf','ContentType','vector');
- ITPC_distr_maxTheta_cuedSniff - ITPC_distr_maxTheta_passive;
- histogram(ans,32)
- % Stats on bootstrapped ITPC difference between Intentional sniff and
- % Passive Inhale
- bootstrap_ITPCdiff = ITPC_distr_maxTheta_cuedSniff - ITPC_distr_maxTheta_passive;
- [muHat_ITPCdiff,sigmaHat_ITPCdiff,muCI_ITPCdiff,sigmaCI_ITPCdiff] = normfit(bootstrap_ITPCdiff, 0.05)
- %% Fig S4F
- ev_epochs_6normosmic_Passive = data_supp.ev_epochs_6normosmic_Passive;
- sd_6_normosmic_Passive = data_supp.sd_6_normosmic_Passive;
- para = data_supp.para;
- for sub = 1:6 % first 6 subs are normosmic
- resp_epochs_Passive_bySub{sub} = squeeze(zscore(G_EpochTS(data_supp.resp_Passive{sub}, (data_supp.sniffonsets_Passive{sub}, [-1,5]*srate)));
- resp_meanEpoch_Passive_bySub{sub} = squeeze(mean(resp_epochs_Passive_bySub{sub},2));
- end
- % Passive - first 6 subs are normosmics
- baseline = para.baseline;
- baselineloc = G_RangeLoc( epoch_time{1}, baseline);
- freq = para.freq;
- % theta_ind = find(freq >= 3 & freq <= 8);
- theta_ind = find(freq > 2 & freq <= 8);
- num_freqs = size(ev_epochs_6normosmic_Passive{1}{1},1);
- numtrials=[]; avg_Passive=[]; response_Passive=[]; amp_epochs_corec_Passive=[]; amp_epochs_theta_Passive=[]; mean_amp_theta_Passive=[]; sem_amp_theta_Passive=[];
- for sub = 1:6 % first 6 subs are normosmics
- numtrials(sub) = size(ev_epochs_6normosmic_Passive{sub}{1},3);
- avg_Passive{sub} = mean(ev_epochs_6normosmic_Passive{sub}{1}(:,baselineloc),2);
- rand_passive_inds_sub{sub} = randperm( size(ev_epochs_6normosmic_Passive{sub}{1},3),size(ev_epochs_6normosmic_cuedSniff{sub}{1},3) );
- response_Passive{sub} = bsxfun( @minus, ev_epochs_6normosmic_Passive{sub}{1}, avg_Passive{sub} );
- response_theta_Passive{sub} = squeeze(mean(response_Passive{sub}(theta_ind,:,:),1));
- amp_epochs_corec_Passive{sub} = bsxfun( @rdivide, response_Passive{sub}, sd_6_normosmic_Passive{sub}{1} );
- amp_epochs_theta_Passive{sub} = squeeze(mean(amp_epochs_corec_Passive{sub}(theta_ind,:,:),1));
- inc_theta_Passive{sub} = squeeze(mean(amp_epochs_theta_Passive{sub}(post500ms_ind,rand_passive_inds_sub{sub}) - amp_epochs_theta_Passive{sub}(pre500ms_ind,rand_passive_inds_sub{sub}),1));
- inc_theta_Passive{sub} = mean(inc_theta_Passive{sub},1);
- mean_amp_theta_Passive(:,sub) = mean(amp_epochs_theta_Passive{sub},2);
- sem_amp_theta_Passive(:,sub) = std(amp_epochs_theta_Passive{sub},[],2) / sqrt(numtrials(sub));
- end
- % collapse across subjects
- thetaAmp_epochs_Passive=[]; resp_epochs_Passive_acrossSubs=[];
- thetaAmp_epochs_Passive = cell2mat(amp_epochs_theta_Passive);
- resp_epochs_Passive_acrossSubs = cell2mat(resp_epochs_Passive_bySub(1:6));
- inc_theta_Passive_allSubs = cell2mat(inc_theta_Passive);
- inc_theta_Passive_allSubs = cell2mat(inc_theta_Passive);
- % calculate inhale peak, latency to inhale peak, theta peak,
- % latency to theta peak for Passive
- inhalePk_Passive=[]; time2inhalePk_ind_Passive=[]; thetaPk_CuedSniff=[]; time2thetaPk_ind_Passive=[]; numTrials_Passive_allSubs=[];
- numTrials_Passive_allSubs = size(thetaAmp_epochs_Passive,2);
- for trial = 1:size(resp_epochs_Passive_acrossSubs,2)
- [inhalePk_Passive(trial), time2inhalePk_ind_Passive(trial)] = max(resp_epochs_Passive_acrossSubs(500:1500,trial));
- [thetaPk_Passive(trial), time2thetaPk_ind_Passive(trial)] = max(thetaAmp_epochs_Passive(500:1500,trial));
- end
- time2inhalePk_ms_Passive=[]; time2thetaPk_ms_Passive=[];
- time2inhalePk_ms_Passive = ((time2inhalePk_ind_Passive) / srate) * 1000;
- time2thetaPk_ms_Passive = ((time2thetaPk_ind_Passive) / srate) * 1000;
- isoutlier(thetaPk_Passive);
- thetaPk_Passive_outliersRem = thetaPk_Passive(~isoutlier(thetaPk_Passive));
- inhalePk_Passive_outliersRem = inhalePk_Passive(~isoutlier(thetaPk_Passive));
- [r,p] = corr(thetaPk_Passive_outliersRem',inhalePk_Passive_outliersRem')
- scatter(inhalePk_Passive_outliersRem', thetaPk_Passive_outliersRem', 'filled','MarkerEdgeColor', [0 0 0.7],'MarkerFaceColor',[0 0 0.7])
- ax=gca; ax.TickDir='out'; ax.LineWidth = 1; box off; ax.FontSize=16;
- xlabel('Peak inhale magnitude (z score)');
- ylabel('Maximal Theta Amplitude (normalized)');
- ax = gca; ax.TickDir = 'out'; ax.FontSize = 16; ax.LineWidth = 1;
- text(0.75,27.5,append('r = ',num2str(r,2)),'FontSize',14)
- text(0.75,25,append('p = ',num2str(p,1)),'FontSize',14)
- l=lsline;
- l.LineWidth = 2;
- set(gcf,'pos',[1000 728 815 510]);
- %% Fig S5 - Modulation index on proximal vs. distal contacts
- % Filtered steps for phase frequency across theta band - ODOR
- para.ph_freq = linspace(2,8,19);
- para.ph_bandwidth = 2;
- para.amp_freq = logspace(log10(29),log10(153),32);
- para.amp_bandwidth = logspace(log10(15),log10(42),32);
- nbamps = length( para.amp_freq);
- nbphs = length(para.ph_freq);
- ph=[]; amp=[]; ph_epochs=[]; amp_epochs=[]; ph_concat=[]; amp_concat=[];
- ph_allTrials=[]; amp_allTrials=[]; amp_ts=[]; ph_ts=[];
- for sub = 1:num_subs
- for freq_idx = 1 : nbphs
- bpfreq = para.ph_freq( freq_idx) + [-0.5, 0.5]*para.ph_bandwidth;
- % fprintf( 'phase filtering %d %d\n', bpfreq(1), bpfreq(2));
- if bpfreq(1) < eps
- ph_ts{sub}( freq_idx, :) = ft_preproc_lowpassfilter( distalCh_odorTasks{sub}, srate, bpfreq(2), [], 'fir');
- else
- ph_ts{sub}( freq_idx, :) = ft_preproc_bandpassfilter( distalCh_odorTasks{sub}, srate, bpfreq, [], 'fir');
- end
- end
- ph{sub} = angle( hilbert( ph_ts{sub}'));
- ph{sub} = wrapTo2Pi( ph{sub});
- ph{sub} = ph{sub}';
- ph_epochs{sub} = squeeze(G_EpochTS(ph{sub}, sniffonsets_odorTasks{sub}, [1,4]*srate));
- % ph_epochs{sub} = squeeze(G_EpochTS(ph{sub}, trough_thresh_times{sub}, [-0.25,0.25]*srate));
- for freq_idx = 1 : nbamps
- bpfreq = para.amp_freq( freq_idx) + [-0.5, 0.5]*para.amp_bandwidth( freq_idx);
- fprintf( 'amplitude filtering %d %d\n', bpfreq(1), bpfreq(2));
- amp_ts{sub}( freq_idx, :) = ft_preproc_bandpassfilter( lfp_odorTasks{sub}, srate, bpfreq, [], 'fir');
- end
- amp{sub} = abs(hilbert(amp_ts{sub}));
- amp_epochs{sub} = squeeze(G_EpochTS(amp{sub}, sniffonsets_odorTasks{sub}, [1,4]*srate));
- % amp_epochs{sub} = squeeze(G_EpochTS(amp{sub}, trough_thresh_times{sub}, [-0.25,0.25]*srate));
- end
- % Concatenate phase and amplitude epochs
- ph_allTrials = cat(3,ph_epochs{1},ph_epochs{2},ph_epochs{3},ph_epochs{4},...
- ph_epochs{5}, ph_epochs{6});
- ph_concat = reshape(ph_allTrials, size(ph_allTrials,1), []);
- amp_allTrials = cat(3,amp_epochs{1},amp_epochs{2},amp_epochs{3},...
- amp_epochs{4},amp_epochs{5},amp_epochs{6});
- amp_concat = reshape(amp_allTrials,length(para.amp_freq),[]);
- % Calculate MI
- para.nbsurrogate = 200;
- para.nbbins = 18;
- [raw_MI_distal, norm_MI_distal, bin_amp_distal, ph_wins_distal] = G_MI( ph_concat, amp_concat, para.nbsurrogate, para.nbbins, srate);
- % Plot proximal vs. distal
- norm_MI_proximal = data_supp.MI_proximal.norm_MI;
- norm_MI_p = G_z2p(norm_MI_proximal);
- norm_MI_FDR = fdr(norm_MI_p(:));
- norm_MI_thresh = G_p2z(norm_MI_FDR)
- norm_MI_distal = norm_MI;
- plot(para.amp_freq,norm_MI_proximal(:,7),'k','LineWidth',2)
- yline(norm_MI_thresh(2),'Color',[0.7 0 0],'LineStyle','--','LineWidth',1)
- hold on
- plot(para.amp_freq,norm_MI_distal(:,7),'Color',[0.6 0.6 0.6],'LineWidth',2)
- legend({'Proximal','','Distal'},'box','off');
- ax=gca; ax.FontSize = 16; ax.LineWidth=1; ax.TickDir='out'; box off
- xlim([29 150]);
- xlabel('Frequency (Hz)');
- ylabel('Modulation Index (z score)');
- set(gcf,'pos',[300 300 673 571]);
- %% Fig S6 - Sniffs with and without intranasal electrode in place
- %% Fig S6A - Sniff traces
- Time = -0.5 : 1/srate : 3;
- figure
- for sub = 1:7
- plot(Time,data_supp.resp_epochs{sub},'Color',[1 0 0 0.1],'LineWidth',1)
- hold on
- end
- for sub = 8:13
- plot(Time,data_supp.resp_epochs{sub-7},'Color',[0 0 1 0.1],'LineWidth',1);
- hold on
- end
- % Create "dummy" lines with max alpha (alpha = 1) for the legend only
- % Set 'HandleVisibility' to 'off' so they don't show up in the main plot
- h1_legend = plot(NaN, NaN, 'r-', 'LineWidth', 2, 'HandleVisibility', 'off');
- h2_legend = plot(NaN, NaN, 'b-', 'LineWidth', 2, 'HandleVisibility', 'off');
- % Note: The 'HandleVisibility' does not affect how they appear in the legend
- % once you explicitly include their handles.
- % Create the legend using the handles of the dummy lines
- legend([h1_legend, h2_legend], {'Without', 'With'}, 'Location', 'best','box','off');
- hold off;
- set(gcf,'pos',[300 300 913 732]);
- ax=gca; ax.TickDir = 'out'; ax.LineWidth=1; box off; ax.FontSize=16;
- ylabel('Airflow (z score)');
- xlabel('Time (s)');
- %% Fig S6B - histogram of sniff duration with and without intranasal electrode
- % Mark exhale onsets to find duration
- nbsamps = size(data_supp.resp_epochs{1},1);
- base_idx = zeros([1,nbsamps]);
- % Time = -1 : 1/srate : 5;
- % base_idx(Time >= -1 & Time <= 0) = ones([1,length(0:1*srate)]);
- Time = -0.5 : 1/srate : 3.5;
- base_idx(1:0.5*srate+1) = ones([1,length(1:0.5*srate+1)]);
- resp_meanCorec_epochs = [];
- % baseline correct with scale - values fall from 0 to 1
- for sub = 1:num_total_subs
- resp_bc_epochs{sub} = G_BaselineCorrect(data_supp.resp_epochs{sub},1,base_idx,'scale');
- resp_meanCorec_epochs(:,sub) = mean(resp_bc_epochs{sub},2);
- end
- % Inputs:
- % resp_data : 1x13 cell array
- % each cell = [samples x trials] matrix
- % time : [samples x 1] time vector from -0.5 to 3 s
- nSub = numel(resp_bc_epochs);
- % Preallocate output
- exhale_sample = cell(nSub,1);
- exhale_time = cell(nSub,1);
- % Define detection window
- win_idx = find(Time >= 0.25 & Time <= 3);
- for s = 1:nSub
- data = resp_bc_epochs{s}; % samples x trials
- [nSamp, nTrials] = size(data);
- exhale_sample{s} = nan(1,nTrials);
- exhale_time{s} = nan(1,nTrials);
- for tr = 1:nTrials
- y = data(:,tr);
- % Restrict to detection window
- y_win = y(win_idx);
- t_win = Time(win_idx);
- % Find falling crossings of 0.5
- cross_idx = find(y_win(1:end-1) >= 0.5 & ...
- y_win(2:end) < 0.5);
- if ~isempty(cross_idx)
- % Take first falling crossing
- idx = cross_idx(1);
- % Linear interpolation for better precision
- y1 = y_win(idx);
- y2 = y_win(idx+1);
- t1 = t_win(idx);
- t2 = t_win(idx+1);
- frac = (0.5 - y1) / (y2 - y1);
- t_cross = t1 + frac * (t2 - t1);
- % Store
- exhale_time{s}(tr) = t_cross;
- % Convert to nearest global sample index
- [~, global_idx] = min(abs(Time - t_cross));
- exhale_sample{s}(tr) = global_idx;
- end
- end
- end
- % Calculate sniff duration for ECoG patients vs. OBE participants
- ECoG_IDs = data_supp.resp_epochs_IDs(1:7);
- OB_IDs = data_supp.resp_epochs_IDs(8:13);
- num_ECoG = length(ECoG_IDs);
- num_OB = length(OB_IDs);
- for sub = 1:num_ECoG
- sniff_duration_ECoG{sub} = (exhale_sample{sub} - 0.5*srate)/srate;
- end
- meanBySub_sniff_duration_ECoG = cellfun(@mean, sniff_duration_ECoG);
- mean_sniff_duration_ECoG = mean(meanBySub_sniff_duration_ECoG)
- sem_sniff_duration_ECoG = std(meanBySub_sniff_duration_ECoG,[])/sqrt(num_ECoG);
- for sub = 1:num_OB
- sniff_duration_OB{sub} = (exhale_sample{sub+num_ECoG} - 0.5*srate) / srate;
- end
- meanBySub_sniff_duration_OB = cellfun(@mean, sniff_duration_OB);
- mean_sniff_duration_OB = mean(meanBySub_sniff_duration_OB);
- sem_sniff_duration_OB = std(meanBySub_sniff_duration_OB,[])/sqrt(num_OB);
- % Bar plot of sniff duration between OBE and ECoG
- [h,p,ci,stats]=ttest2(meanBySub_sniff_duration_OB, meanBySub_sniff_duration_ECoG)
- mean_sniffDur_OB_ECoG(1) = mean_sniff_duration_OB;
- mean_sniffDur_OB_ECoG(2) = mean_sniff_duration_ECoG;
- sem_sniffDur_OB_ECoG(1) = sem_sniff_duration_OB;
- sem_sniffDur_OB_ECoG(2) = sem_sniff_duration_ECoG;
- % plot_IDs2 = {'','P1','P2','P3','P4','P5','P6'};
- bar( mean_sniffDur_OB_ECoG, 'FaceColor','none',...
- 'EdgeColor','k','LineWidth',1)
- hold on
- scatter(1, meanBySub_sniff_duration_OB, 75, sub_colors,'LineWidth',1)
- scatter(2, meanBySub_sniff_duration_ECoG, 75, 'k', 'LineWidth',1)
- er = errorbar(mean_sniffDur_OB_ECoG, sem_sniffDur_OB_ECoG);
- er.Color = [0 0 0];
- er.LineStyle = 'none';
- er.LineWidth = 1;
- set(gcf,'pos',[300 300 566 603]);
- xticklabels({'With','Without'});
- xlabel('Presence of intranasal electrode');
- ylabel('Sniff duration (s)');
- ax=gca; ax.TickDir='out'; ax.LineWidth=1; ax.FontSize=16; box off
code_suppFigs.m, under CC-BY-4.0 · at the source
Overview
- Department of Neurology, Northwestern University Feinberg School of Medicine, Chicago, IL, USA
- Department of Psychology, The University of Chicago, Chicago, IL, USA
- Institute for Mind and Biology, The University of Chicago, Chicago, IL, USA
- Department of Otolaryngology—Head and Neck Surgery, Northwestern University Feinberg School of Medicine, Chicago, IL, USA
Abstract
When sampling odors, humans typically take a single long sniff, unlike most other mammals who sample odors through bouts of rapid repetitive sniffing. Decades of work has established that rapid sniffing rhythms underlie the organizational principles of odor coding, with sniff speed clocking odor responses in the olfactory bulb. In the absence of rapid sniffing, how are odor responses organized in the human olfactory system? Because most mammals sniff at rates centered around the theta frequency, we hypothesized that the olfactory bulb exploits a theta-range neural oscillation to set the pace of odor coding in the system. Here, we used high-precision neural recordings from the human olfactory bulb to show that initiation of a sniff elicits and temporally aligns theta oscillations in the bulb and that sniff-induced theta oscillations organize the timing and amplitude of odor responses. These findings suggest that, despite the lack of rapid sniffing bouts in humans, the system has preserved a similarly timed unit of olfactory processing.
Reproduced under the paper's license (CC BY), from the paper cited above.
Repository
Its files are read in the Code ↔ Paper reader above, with 16 matches between paragraphs and lines of code.
Zenodo 18791231
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
- 27 September 2026: the link answers (HTTP 200)
22 files
- CustomColormap.m, MATLAB, 195 lines
- G_EpochTS.m, MATLAB, 162 lines
- G_Imagesc.m, MATLAB, 1,763 lines
- G_Outline_Pixels.m, MATLAB, 293 lines
- G_Outline_Range.m, MATLAB, 89 lines
- G_PowChange_Clust.m, MATLAB, 283 lines
- G_RangeLoc.m, MATLAB, 50 lines
- G_Rescale.m, MATLAB, 103 lines
- G_Smooth.m, MATLAB, 129 lines
- G_SparseArgs.m, MATLAB, 124 lines
- G_fdr.m, MATLAB, 153 lines
- G_p2z.m, MATLAB, 18 lines
- PermutAmpChange_Commonba
seline.m , MATLAB, 253 lines - Script_Figure1plots.m, MATLAB, 131 lines
- code_fig1h.m, MATLAB, 44 lines
- code_fig2_OdorImageCue.m
, MATLAB, 394 lines, 2 matches - code_fig2a.m, MATLAB, 126 lines
- code_fig3.m, MATLAB, 429 lines, 2 matches
- code_fig4.m, MATLAB, 838 lines, 4 matches
- code_fig6.m, MATLAB, 598 lines, 3 matches
- code_suppFigs.m, MATLAB, 1,002 lines, 4 matches
- dataScript.m, MATLAB, 776 lines, 1 match
The paper's code and data availability statement is in the Data section.
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;
- 22 scripts, each with its path and the digest of its content;
- 16 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, code, and materials availability
All data and code needed to evaluate and reproduce the results in the paper are present in the paper and/
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, 27 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 13 authors, 6 MeSH terms, 2 funders, 118 references, 3 RRIDs.
Cite
This paper
Sheriff, A., Omidbeigi, M., Lane, G., Yang, Q., Zhou, G., Dede, A., Arriaga, N., Sagar, V., Holubecki, A. M., Braga, R. M., Kay, L. M., Tan, B. K., & Zelano, C. (2026). Theta oscillations are an organizational unit of odor processing in the olfactory bulb. Science advances, 12(27), eaee1002. https://
BibTeX
@article{sheriff2026thet
author = {Sheriff, Andrew and Omidbeigi, Mahmoud and Lane, Gregory and Yang, Qiaohan and Zhou, Guangyu and Dede, Adam and Arriaga, Naelly and Sagar, Vivek and Holubecki, Ania M. and Braga, Rodrigo M. and Kay, Leslie M. and Tan, Bruce K. and Zelano, Christina},
title = {{Theta oscillations are an organizational unit of odor processing in the olfactory bulb}},
journal = {Science advances},
year = {2026},
month = jul,
volume = {12},
number = {27},
pages = {eaee1002},
publisher = {American Association for the Advancement of Science},
issn = {2375-2548},
doi = {10.1126/
url = {https://
pmid = {42397924},
pmcid = {PMC13330860}
}
RIS
TY - JOUR
AU - Sheriff, Andrew
AU - Omidbeigi, Mahmoud
AU - Lane, Gregory
AU - Yang, Qiaohan
AU - Zhou, Guangyu
AU - Dede, Adam
AU - Arriaga, Naelly
AU - Sagar, Vivek
AU - Holubecki, Ania M.
AU - Braga, Rodrigo M.
AU - Kay, Leslie M.
AU - Tan, Bruce K.
AU - Zelano, Christina
TI - Theta oscillations are an organizational unit of odor processing in the olfactory bulb
T2 - Science advances
J2 - Sci Adv
PY - 2026
DA - 2026/
VL - 12
IS - 27
SP - eaee1002
SN - 2375-2548
PB - American Association for the Advancement of Science
DO - 10.1126/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1126/
"type": "article-journal",
"title": "Theta oscillations are an organizational unit of odor processing in the olfactory bulb",
"container-title": "Science advances",
"author": [
{
"family": "Sheriff",
"given": "Andrew"
},
{
"family": "Omidbeigi",
"given": "Mahmoud"
},
{
"family": "Lane",
"given": "Gregory"
},
{
"family": "Yang",
"given": "Qiaohan"
},
{
"family": "Zhou",
"given": "Guangyu"
},
{
"family": "Dede",
"given": "Adam"
},
{
"family": "Arriaga",
"given": "Naelly"
},
{
"family": "Sagar",
"given": "Vivek"
},
{
"family": "Holubecki",
"given": "Ania M."
},
{
"family": "Braga",
"given": "Rodrigo M."
},
{
"family": "Kay",
"given": "Leslie M."
},
{
"family": "Tan",
"given": "Bruce K."
},
{
"family": "Zelano",
"given": "Christina"
}
],
"container-title-short":
"volume": "12",
"issue": "27",
"page": "eaee1002",
"DOI": "10.1126/
"PMID": "42397924",
"PMCID": "PMC13330860",
"ISSN": "2375-2548",
"publisher": "American Association for the Advancement of Science",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
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.1038/s41467-026-73106-z [code]
- Respiratory pauses highlight sleep architecture in mice.Journal: Nature communicationsIn common: Chronux, CircStat, FieldTrip, 3 other tools, 4 references
- [2] doi:10.1371/journal.pbio.3003810 [code]
- Olfactory bulb-cortex oscillations encode perceived odor intensity rather than concentration.Journal: PLoS biologyIn common: FieldTrip, Image Processing Toolbox, Statistics and Machine Learning Toolbox, 7 references
- [3] doi:10.7554/elife.110795 [code]
- REM sleep prefrontal high-frequency oscillation chains mediate distinct cortical - hippocampal reactivation patterns compared to NREM sleep.Journal: eLifeIn common: Chronux, CircStat, shadedErrorBar, 4 other tools, 3 references
- [4] doi:10.1038/s41467-026-72445-1 [code]
- Perception and neural representation of intermittent odor stimuli in mice.Journal: Nature communicationsIn common: 8 references
- [5] doi:10.1038/s41467-026-73001-7 [code]
- Separable and integrated pleasantness coding for appetitive and aversive odors across olfactory and ventral prefrontal cortices.Journal: Nature communicationsIn common: Signal Processing Toolbox, Statistics and Machine Learning Toolbox, 2 authors
- [6] doi:10.1126/sciadv.aed3610 [code]
- Dexterous single sniffs for ethological active olfaction.Journal: Science advancesIn common: 8 references
- [7] doi:10.1016/j.isci.2026.116240 [code]
- Physical activity enhances theta-periodicity of visual attentional allocation.Journal: iScienceIn common: CircStat, shadedErrorBar, Signal Processing Toolbox, 1 other tool, 4 references
- [8] doi:10.1371/journal.pbio.3003938 [code]
- Theta oscillations tag episodic memories for sleep-dependent consolidation.Journal: PLoS biologyIn common: CircStat, shadedErrorBar, FieldTrip, 3 other tools, 2 references
- [9] doi:10.1016/j.celrep.2026.117646 [code]
- Medial entorhinal-hippocampal desynchronization parallels the emergence of memory impairment in a mouse model of Alzheimer's disease pathology.Journal: Cell reportsIn common: Chronux, CircStat, FieldTrip, 3 other tools, 1 reference
- [10] doi:10.1038/s41467-026-75345-6 [code]
- Hippocampal ripples initiate cortical dimensionality expansion for memory retrieval.Journal: Nature communicationsIn common: FieldTrip, Image Processing Toolbox, Signal Processing Toolbox, 1 other tool, 5 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: 1 repository of the authors' code, each at its verified commit and with its license, 22 scripts, and 16 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:c09cd300a42eece5…
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
[.
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.
