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 to 474 · score 0.95 · Hilbert transform, gamma bursts, 30–60 Hz, gamma peaks, filtered signal, CircStat · Report a mismatch
- [2] § MATERIALS AND METHODS › Cross-frequency coupling of theta and gamma ↔ dataScript.m, lines 498 to 533 · score 0.94 · low gamma filtered, 30–60 Hz, amplitude envelope, gamma envelope, low gamma frequency, filtered signal · Report a mismatch
- [3] § MATERIALS AND METHODS › Intertrial phase coherence ↔ code_suppFigs.m, lines 543 to 680 · score 0.83 · respiratory phase bins, circularly shifted, passive inhalations, respiratory epochs, intentional sniffs, Fisher · Report a mismatch
- [4] § RESULTS › Theta oscillations organize the timing of gamma bursts in the olfactory bulb ↔ code_fig6.m, lines 426 to 474 · score 0.80 · gamma burst, 30–60 Hz, gamma peaks, theta phase, low gamma, sniff onset · Report a mismatch
- [5] § RESULTS › Theta oscillations organize the timing of gamma bursts in the olfactory bulb ↔ code_fig6.m, lines 301 to 424 · score 0.77 · aligned spectrogram, theta troughs, Theta peak, theta filtered, Amplitude spectrograms, theta frequency · Report a mismatch
- [6] § MATERIALS AND METHODS › Intertrial phase coherence ↔ code_fig4.m, lines 585 to 639 · score 0.77 · respiratory phase bins, circularly shifted, phase epochs, ITPC, matched, permuted · Report a mismatch
- [7] § MATERIALS AND METHODS › Statistical analysis ↔ code_fig4.m, lines 201 to 304 · score 0.71 · sign flipped, cluster mass, clusters formed, intentional sniffs, passive, threshold · Report a mismatch
- [8] § RESULTS › High-precision recordings from the human olfactory bulb ↔ code_fig3.m, lines 95 to 186 · score 0.67 · low gamma band, Low gamma odor, odor detection, High gamma, 150 Hz, 60 Hz · Report a mismatch
- [9] § MATERIALS AND METHODS › Amplitude spectrograms ↔ code_suppFigs.m, lines 403 to 541 · score 0.66 · temporally smoothed, longest, shortest, S4C, bandwidth, SD · Report a mismatch
- [10] § RESULTS › Intentional sniffs enhance and align theta oscillations in the olfactory bulb ↔ code_fig4.m, lines 201 to 304 · score 0.57 · cluster corrected permutation, passive inhales, intentional sniffs, theta amplitude, airflow, bar · Report a mismatch
- [11] § RESULTS › Sniffing behavior covaries with olfactory bulb theta oscillations ↔ code_suppFigs.m, lines 403 to 541 · score 0.55 · sniff duration, passive inhales, intentional sniffs, S4C, subset, overlapping · Report a mismatch
- [12] § RESULTS › Intentional sniffs enhance and align theta oscillations in the olfactory bulb ↔ code_fig4.m, lines 776 to 805 · score 0.55 · maximum theta ITPC, passive inhales, intentional sniff, resampling, phase, Figure 4 · Report a mismatch
- [13] § RESULTS › High-precision recordings from the human olfactory bulb ↔ code_fig2_OdorImageCue.m, lines 329 to 393 · score 0.55 · image onset, odor cues, FDR corrected, baseline, Figure 2, threshold · Report a mismatch
- [14] § RESULTS › High-precision recordings from the human olfactory bulb ↔ code_fig3.m, lines 274 to 372 · score 0.53 · Power spectra, Gamma power, cue task, low gamma, contact, Figure 3 · Report a mismatch
- [15] § RESULTS › High-precision recordings from the human olfactory bulb ↔ code_fig2_OdorImageCue.m, lines 329 to 393 · score 0.53 · image cues, Odor cues, FDR corrected, baseline, onset, Figure 2 · Report a mismatch
- [16] § RESULTS › Intentional sniffs enhance and align theta oscillations in the olfactory bulb ↔ code_suppFigs.m, lines 682 to 719 · score 0.51 · Resampled distributions, passive inhales, intentional sniffs, CI, bootstrap, subset · Report a mismatch
Paper
Loaded from Europe PMC by your browser; OSCR does not store it: 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.1073/pnas.2405395121
- Breathing orchestrates synchronization of sleep oscillations in the human hippocampus.Journal: Proceedings of the National Academy of Sciences of the United States of AmericaIn common: 18 references, 2 authors
- [2] doi:10.1016/j.isci.2025.112755 [code]
- Decoding olfactory bulb output: A behavioral assessment of rate, synchrony, and respiratory phase coding.Journal: iScienceIn common: 17 references
- [3] doi:10.7554/elife.79545 [code]
- Rhythmic coordination and ensemble dynamics in the hippocampal-prefrontal network during odor-place associative memory and decision making.Journal: eLifeIn common: Chronux, CircStat, shadedErrorBar, 4 other tools, 9 references
- [4] doi:10.1371/journal.pbio.3002849 [code]
- The human olfactory bulb communicates perceived odor valence to the piriform cortex in the gamma band and receives a refined representation back in the beta band.Journal: PLoS biologyIn common: FieldTrip, Statistics and Machine Learning Toolbox, 11 references
- [5] doi:10.7554/elife.83044 [code]
- Mechanisms and functions of respiration-driven gamma oscillations in the primary olfactory cortex.Journal: eLifeIn common: 12 references
- [6] doi:10.1038/s41467-024-45161-x [code]
- Endogenous cannabinoids in the piriform cortex tune olfactory perception.Journal: Nature communicationsIn common: Chronux, CircStat, FieldTrip, 3 other tools, 5 references
- [7] doi:10.1038/s41467-022-34513-0 [code]
- Long-range GABAergic projections contribute to cortical feedback control of sensory processing.Journal: Nature communicationsIn common: Statistics and Machine Learning Toolbox, 9 references
- [8] 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
- [9] 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
- [10] doi:10.7554/elife.92033 [code]
- Using synchronized brain rhythms to bias memory-guided decisions.Journal: eLifeIn common: Chronux, CircStat, shadedErrorBar, 4 other tools, 3 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 the code's README
If you are an author or a maintainer of this paper's code, you can add this badge. It says what OSCR knows of the paper (its code, its validated tracing map) and links the code to this page. Paste one of these snippets under the README's title. Keep the two marks around it, so that the badge can be replaced in place and is never added twice. OSCR changes nothing in your repository.
Markdown
<!-- oscr-badge:start -->
[](https://openscicode.org/badge/doi/10.1126/sciadv.aee1002)
<!-- oscr-badge:end -->reStructuredText
.. oscr-badge:start
.. image:: https://openscicode.org/badge/doi/10.1126/sciadv.aee1002.svg
:target: https://openscicode.org/badge/doi/10.1126/sciadv.aee1002
:alt: OSCR
.. oscr-badge:endHTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/doi/10.1126/sciadv.aee1002"><img src="https://openscicode.org/badge/doi/10.1126/sciadv.aee1002.svg" alt="OSCR"></a>
<!-- oscr-badge:end -->If you choose to, you can have the badge kept up to date for you, with oscr badge --write from the command line or with the GitHub Action in your repository's workflows. Every other form and option (a card, AsciiDoc, LaTeX, shields.io) is on the badge page.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: code errors and mismatches between the code and the paper about this paper and its code, from readers and its authors, beside the paper and its tracing map.
Report a mismatch between the code and the paper · Report a code error (signed in)
Reproductions: reports from readers who ran the authors' code and did not get the paper's result, what they ran, with which environment, commit and data.
Report a reproduction failure (signed in)
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
