MEG-SCANS - A comprehensive magnetoencephalography speech dataset with Stories, Chirps and Noisy Sentences
The 16 matches · 3 of them tie a paragraph to a whole file, not to given lines: weak matches, whose lines are not tinted
- [1] § Technical Validation › Cross-correlation analysis › Signal Processing ↔ speech/crosscorrelation/plot_crosscorr.m, lines 487–557 · score 0.93 · 160–230 ms, 50–90 ms, cross correlation function, 160 ms, alpha, window
- [2] § Technical Validation › Cross-correlation analysis › Signal Processing ↔ helper_functions/cal_envelope.m, the whole file · a weak match · score 0.90 · Hilbert Transform, low pass filtered, half wave, onset envelope, audio signal, rectified
- [3] § Technical Validation › Chirps › Signal Processing ↔ chirps/sourcelevel/plot_dipolfit_grouplevel.m, lines 1–25 · score 0.88 · outlier dipoles, poor fits, dipole positions, dipole moments, dipole fit, chirp stimuli
- [4] § Data Records › Derived Data ↔ maxfilter/apply_maxfilter_parallel.py, lines 262–301 · score 0.86 · Power Spectral Densities, MaxFilter, Maxwell filter, head position, MNE, tSSS
- [5] § Technical Validation ↔ speech/decoding/training_decoding.m, lines 1–27 · score 0.85 · temporal response function, mTRF, speech envelope, OLSA sentences, backward, trained
- [6] § Technical Validation › Chirps › Signal Processing ↔ chirps/sensorlevel/compute_aefs.m, lines 1–21 · score 0.84 · auditory evoked fields, baseline corrected, FieldTrip, chirp stimuli, AEFs, rejection
- [7] § Technical Validation › Decoding analysis › Signal Processing ↔ speech/decoding/training_decoding.m, lines 1–27 · score 0.80 · cross validation, speech envelopes, OLSA sentences, optimal, held, training
- [8] § Technical Validation ↔ speech/settings_speech.m, the whole file · a weak match · score 0.73 · mTRF, cross correlation, Pearson, backward, Spearman, decoder
- [9] § Data Records › Behavioral Data ↔ behavioral/plot_audiograms.m, lines 78–98 · score 0.73 · Pure tone, hearing thresholds, right ear, audiogram, Behavioral
- [10] § Technical Validation › Decoding analysis › Signal Processing ↔ helper_functions/cal_envelope.m, the whole file · a weak match · score 0.70 · Gammatone filterbank, power, hearing, segmented, onset, 5000 Hz
- [11] § Technical Validation › Cross-correlation analysis › Results ↔ speech/crosscorrelation/plot_crosscorr.m, lines 1–39 · score 0.67 · anatomical region, cross correlation, butterfly, waveforms, clusters, permutation
- [12] § Technical Validation › Chirps › Results ↔ chirps/sourcelevel/plot_dipolfit_grouplevel.m, lines 1–25 · score 0.59 · right hemispheres, dipole fit, standard error, components, template, grand
- [13] § Methods › Procedure › Study Design ↔ maxfilter/apply_maxfilter_parallel.py, lines 180–219 · score 0.58 · HPI coil, Head position, channels, MEG
- [14] § Methods › Subjects ↔ behavioral/plot_audiograms.m, lines 78–98 · score 0.55 · pure tone, audiogram, HL, hearing, sub
- [15] § Background & Summary ↔ chirps/sourcelevel/plot_dipolfit_subjectlevel.m, lines 1–35 · score 0.55 · brain regions, activity, reconstruction, linear, anatomical, MRI
- [16] § Methods › Procedure › Study Design ↔ chirps/sourcelevel/compute_headmodel_sourcemodel.m, lines 1–36 · score 0.53 · T1 weighted anatomical, MRIs, MEG
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 · 607 lines · 23 KB · BSD-3-Clause · 2 matches
- %--------------------------------------------------------------------------
- % Till Habersetzer, 01.07.2025
- % Communication Acoustics, CvO University Oldenburg
- % [email hidden]
- %
- % Description:
- % This script performs a comprehensive analysis and visualization of MEG
- % cross-correlation data. It focuses on comparing a primary experimental
- % condition ('sorted') against a shuffled null condition to identify
- % statistically significant differences. The analysis uses FieldTrip's
- % cluster-based permutation statistics and generates a wide range of plots
- % to inspect the data at both the grand-average and single-subject level.
- %
- % Key Features & Visualizations:
- % 1. Data Loading: Imports pre-computed cross-correlation results for
- % individual subjects and the grand average.
- % 2. Trial Count Summary: Plots a bar chart of the number of trials
- % retained for each subject.
- % 3. Waveform Visualization: Creates topographical plots of grand-average
- % waveforms for both magnetometers and gradiometers, overlaying the
- % sorted, shuffled, and difference waves.
- % 4. Statistical Analysis: Conducts a cluster-based permutation t-test
- % to find significant time-channel clusters where the sorted and
- % shuffled conditions differ.
- % 5. Statistical Visualization:
- % - Generates topographical plots of t-values, highlighting
- % significant clusters within specific time windows.
- % - Plots the full time-course of the statistical results.
- % 6. Detailed Channel Plots: For a selection of channels, it visualizes
- % the time-series showing the grand-average with SEM error bands and
- % the data from all individual subjects.
- % 7. Butterfly Plots: Overlays the waveforms from all sensors to provide
- % a global view, including a version where channels are color-coded
- % by their anatomical region (e.g., temporal, frontal).
- %--------------------------------------------------------------------------
- close all
- clearvars
- clc
- %% Import main settings
- %--------------------------------------------------------------------------
- current_dir = pwd;
- cd(fullfile('..'))
- settings_speech
- cd(current_dir)
- % Addpath for additional functions
- addpath(fullfile(settings.path2project,'analysis','helper_functions'))
- %% Script settings
- %--------------------------------------------------------------------------
- % Choose subject for plotting
- subjects = 1:24;
- n_subj = length(subjects);
- %% Import data
- %--------------------------------------------------------------------------
- avgs_crosscorr = cell(1,n_subj);
- avgs_crosscorr_shuffled = cell(1,n_subj);
- n_trials = zeros(1,n_subj);
- subjectnames = cell(1,n_subj);
- for sub_idx = 1:n_subj
- subject = sprintf('sub-%02d',subjects(sub_idx));
- subjectnames{sub_idx} = subject;
- data = importdata(fullfile(settings.path2derivatives,subject,'speech',sprintf('%s_crosscorr.mat',subject)));
- avgs_crosscorr{sub_idx} = data.avg_crosscorr;
- avgs_crosscorr_shuffled{sub_idx} = data.avg_crosscorr_shuffled;
- n_trials(sub_idx) = data.n_trials;
- clear data
- fprintf('%s loaded.\n',subject)
- end
- % Import grand average over all subjects
- %---------------------------------------
- subject = 'grandaverage';
- data = importdata(fullfile(settings.path2derivatives,subject,'speech',sprintf('%s_crosscorr.mat',subject)));
- gavg_crosscorr = data.gavg_crosscorr;
- gavg_crosscorr_shuffled = data.gavg_crosscorr_shuffled;
- n_subj_gavg = data.n_subjects;
- clear data
- if ~isequal(n_subj_gavg,n_subj)
- error('Unexpected number of subjects for group analysis! Recompute grandaverage!')
- end
- % Compute raweffect
- %------------------
- cfg = [];
- cfg.operation = 'subtract';
- cfg.parameter = 'avg';
- gavg_crosscorr_raweffect = ft_math(cfg,gavg_crosscorr,gavg_crosscorr_shuffled);
- %% Plot kept trials
- %--------------------------------------------------------------------------
- figure;
- b1 = bar(1:n_subj, n_trials, 'FaceColor', [0.8 0.8 0.8]); % Light grey
- ax = gca;
- ax.XTick = 1:n_subj;
- ax.XTickLabel = subjectnames;
- ax.XTickLabelRotation = 45;
- title(sprintf('Number of trials (Trialduration: %is)',settings.crosscorr.trialdur));
- ylabel('Number of Trials');
- xlabel('Subject');
- grid on;
- %% Plot crosscorrelations for all sensors arranged topographically
- %--------------------------------------------------------------------------
- figure
- cfg = [];
- cfg.showlabels = 'yes';
- cfg.fontsize = 6;
- cfg.layout = 'neuromag306mag_helmet.lay';
- cfg.linestyle = {'--','-.','-'};
- cfg.linecolor = 'rmb';
- ft_multiplotER(cfg, gavg_crosscorr,gavg_crosscorr_shuffled,gavg_crosscorr_raweffect);
- title('gavg: magnetometer')
- % Gradiometer
- %------------
- figure
- cfg = [];
- cfg.showlabels = 'yes';
- cfg.fontsize = 6;
- cfg.layout = 'neuromag306planar_helmet.lay';
- cfg.linestyle = {'--','-.','-'};
- cfg.linecolor = 'rmb';
- ft_multiplotER(cfg, gavg_crosscorr,gavg_crosscorr_shuffled,gavg_crosscorr_raweffect);
- title('gavg: gradiometer')
- %% Calculate cluster-based permutation statistic and show clusters
- %--------------------------------------------------------------------------
- % Within-subjects experiment (within-UO design)
- % null hypothesis: the probability distribution of the condition-specific averages
- % is independent of the experimental conditions.
- % choose sensors
- %---------------
- % you may need to change alpha value and cfg.minnbchan
- sensortype = 'megmag';
- cfg = [];
- switch sensortype
- case 'megmag'
- layout = 'neuromag306mag_helmet.mat';
- cfg.channel = sensortype;
- cfg.method = 'template';
- cfg.template = 'neuromag306mag_neighb.mat';
- neighbours = ft_prepare_neighbours(cfg);
- case 'megplanar'
- layout = 'neuromag306planar_helmet.mat';
- cfg.channel = sensortype;
- cfg.method = 'template';
- cfg.template = 'neuromag306planar_neighb.mat';
- neighbours = ft_prepare_neighbours(cfg);
- end
- cfg.neighbours = neighbours;
- cfg.grad = avgs_crosscorr{1}.grad;
- ft_neighbourplot(cfg)
- cfg = [];
- cfg.channel = sensortype;
- cfg.method = 'montecarlo';
- cfg.statistic = 'depsamplesT'; % the dependent samples T-statistic (within-UO)
- cfg.correctm = 'cluster'; % MCP by calculating a so-called cluster-based test statistic
- cfg.clusteralpha = 0.05; % alpha level of the sample-specific test statistic that will be used for thresholding
- cfg.clusterstatistic = 'maxsum';
- cfg.minnbchan = 2; % megmag = 2, megplanar 3, meg = 4 / % minimum number of neighborhood channels that is required for a selected sample to be included
- cfg.tail = 0; % -1, 1 or 0 (default = 0); one-sided or two-sided test
- cfg.clustertail = 0;
- cfg.alpha = 0.025; % alpha level of the permutation test
- cfg.numrandomization = 5000;
- cfg.neighbours = neighbours;
- design = zeros(2,2*n_subj);
- design(1,:) = [1:n_subj 1:n_subj];
- design(2,:) = [ones(1,n_subj) ones(1,n_subj)*2];
- cfg.design = design;
- cfg.uvar = 1; % row of design matrix that contains unit of observation
- cfg.ivar = 2; % row of design matrix that contains independent variable
- stat = ft_timelockstatistics(cfg,avgs_crosscorr{:},avgs_crosscorr_shuffled{:});
- % Show a specific cluster
- %--------------------------------------------------------------------------
- cluster_number = 1;
- pos = any(ismember(stat.posclusterslabelmat,cluster_number),2);
- neg = any(ismember(stat.negclusterslabelmat,cluster_number),2);
- % stat.selected_cluster = pos;
- stat.selected_cluster = neg;
- figure('Color', 'w');
- cfg = [];
- cfg.xlim = [0.06,0.1];
- cfg.parameter = 'stat';
- cfg.comment = 'no';
- cfg.highlight = 'on';
- cfg.highlightchannel = stat.label(stat.selected_cluster);
- cfg.highlightcolor = 'k';
- cfg.highlightsize = 60;
- cfg.highlightsymbol = '.';
- cfg.layout = layout;
- cfg.interactive = 'no';
- ft_topoplotER(cfg,stat);
- colormap(bluewhitered)
- %% Visualize Statistic over time
- %--------------------------------------------------------------------------
- % Set alpha-value for mask
- %-------------------------
- alpha_mask = 0.025;
- mask = give_stat_mask(stat,alpha_mask);
- stat.mask = mask;
- % Plot mask
- % imagesc(mask);
- % colormap(gray);
- % Time windows for topoplots
- %---------------------------
- timewindows_statistic = [50, 90; 160, 230]/1000; % sec
- time_idx = dsearchn(stat.time',reshape(timewindows_statistic,1,numel(timewindows_statistic))');
- time_idx = reshape(time_idx,size(timewindows_statistic,1),size(timewindows_statistic,2));
- minval = min(gavg_crosscorr_raweffect.avg(:));
- maxval = max(gavg_crosscorr_raweffect.avg(:));
- % Plot over statistic
- %--------------------
- % First ensure the channels to have the same order in the average and in the statistical output.
- % This might not be the case, because ft_math might shuffle the order
- [i1,i2] = match_str(gavg_crosscorr_raweffect.label, stat.label);
- figure('Color', 'w')
- % Pre-allocate an array to store the handles of the subplots
- ax = gobjects(1, size(timewindows_statistic,1));
- for p_idx = 1:size(timewindows_statistic,1)
- chan2highlight = zeros(numel(gavg_crosscorr_raweffect.label),1);
- chan2highlight(i1) = all(stat.mask(i2, time_idx(p_idx,1):time_idx(p_idx,2)), 2);
- % less strict
- % chan2highlight(i1) = any(stat.mask(i2,time_idx(p_idx,1):time_idx(p_idx,2)), 2);
- % Store the handle of the current subplot
- ax(p_idx) = subplot(1,2,p_idx);
- cfg = [];
- cfg.xlim = timewindows_statistic(p_idx,:);
- cfg.zlim = [minval,maxval];
- cfg.highlight = 'on';
- cfg.highlightchannel = find(chan2highlight);
- cfg.highlightcolor = 'k';
- cfg.highlightsize = 50;
- cfg.highlightsymbol = '.';
- cfg.comment = 'xlim';
- cfg.commentpos = 'title';
- cfg.layout = layout;
- cfg.interactive = 'no';
- cfg.figure = gca; % Use the current axes handle
- ft_topoplotER(cfg, gavg_crosscorr_raweffect);
- colormap(bluewhitered)
- end
- % Get the position of the second subplot using its stored handle
- pos2 = get(ax(2), 'Position'); % [left, bottom, width, height]
- c = colorbar;
- c.Position = [pos2(1) + pos2(3) + 0.02, pos2(2), 0.03, pos2(4)]; % [left, bottom, width, height]
- c.LineWidth = 1;
- c.FontSize = 15;
- title(c, '$\hat{R}$', 'fontweight', 'bold', 'Interpreter', 'latex');
- sgtitle(sprintf('%s: Correlation-values condition contrast', sensortype), 'fontweight', 'bold', 'FontSize', 20);
- % Crosscorrelation timeseries with statistic
- %-------------------------------------------
- cfg = [];
- cfg.layout = 'neuromag306all_helmet.mat';
- cfg.parameter = 'stat';
- cfg.maskparameter = 'mask';
- cfg.graphcolor = 'r';
- figure('Color', 'w')
- ft_multiplotER(cfg,stat);
- sgtitle(sprintf('%s: Cluster-based permutation test ',sensortype),'fontweight','bold','FontSize',20)
- %% Visualize cross correlation timeseries of both conditions
- %--------------------------------------------------------------------------
- % Compute standard error of mean
- gavg_crosscorr_sem = sqrt(gavg_crosscorr.var) ./ sqrt(gavg_crosscorr.dof);
- gavg_crosscorr_shuffled_sem = sqrt(gavg_crosscorr_shuffled.var) ./ sqrt(gavg_crosscorr_shuffled.dof);
- % Plot selected channels for grand average (order not important) with
- % standard error of mean (sem) and individual time courses (optional)
- %--------------------------------------------------------------------------
- % channels to plot
- chan2plot = {'MEG0341','MEG1221','MEG0231','MEG1341','MEG1611','MEG2421'};
- n_chan = length(chan2plot);
- error_alpha = 0.2; % Shaded error area transparency
- timevec = gavg_crosscorr.time*1000;
- subject_alpha = 0.6;
- subject_color = [0.8, 0.8, 0.8];
- subject_color_shuffled = [0.5, 0.5, 0.5];
- axis_font_size = 16;
- legend_font_size = 18;
- title_font_size = 14;
- xlims = [-100,900];
- idx = find(contains(gavg_crosscorr.label,chan2plot));
- minval = min(gavg_crosscorr.avg(idx,:)-gavg_crosscorr_sem(idx,:),[],'all');
- maxval = max(gavg_crosscorr.avg(idx,:)+gavg_crosscorr_sem(idx,:),[],'all');
- % ylims = [-0.02,0,0.02];
- figure('Color', 'w')
- t = tiledlayout(3, 2, 'TileSpacing', 'compact', 'Padding', 'compact');
- axis_handles = gobjects(1, n_chan); % Pre-allocate an array for axis handles
- for ch_idx = 1:n_chan
- chan_name = chan2plot{ch_idx};
- idx = find(contains(gavg_crosscorr.label,chan_name));
- % Go to the next tile (subplot)
- axis_handles(ch_idx) = nexttile;
- hold on;
- % Plot individual subjects
- for sub_idx = 1:n_subj
- plot(timevec, avgs_crosscorr_shuffled{sub_idx}.avg(idx,:),'LineWidth', 1,'Color', [subject_color_shuffled,subject_alpha], 'LineStyle', '-','HandleVisibility', 'off');
- plot(timevec, avgs_crosscorr{sub_idx}.avg(idx,:),'LineWidth', 1,'Color', [subject_color,subject_alpha], 'LineStyle', '-','HandleVisibility', 'off');
- % update minval, maxval
- % minval = min([minval,min([avgs_crosscorr_shuffled{sub_idx}.avg(idx,:),avgs_crosscorr{sub_idx}.avg(idx,:)])]);
- % maxval = max([maxval,max([avgs_crosscorr_shuffled{sub_idx}.avg(idx,:),avgs_crosscorr{sub_idx}.avg(idx,:)])]);
- end
- ft_plot_vector(timevec, [gavg_crosscorr_shuffled.avg(idx,:) + gavg_crosscorr_shuffled_sem(idx,:); gavg_crosscorr_shuffled.avg(idx,:) - gavg_crosscorr_shuffled_sem(idx,:)], 'highlightstyle', 'difference', 'facealpha', error_alpha, 'facecolor', 'r')
- plt1 = ft_plot_vector(timevec, gavg_crosscorr_shuffled.avg(idx,:), 'color', 'r', 'linewidth', 2, 'style', '--');
- ft_plot_vector(timevec, [gavg_crosscorr.avg(idx,:) + gavg_crosscorr_sem(idx,:); gavg_crosscorr.avg(idx,:) - gavg_crosscorr_sem(idx,:)], 'highlightstyle', 'difference', 'facealpha', error_alpha, 'facecolor', 'b')
- plt2 = ft_plot_vector(timevec, gavg_crosscorr.avg(idx,:), 'color', 'b', 'linewidth', 2, 'style', '-');
- if ch_idx > 4
- xlabel('t / ms')
- end
- ylabel('$\hat{R}$','Interpreter','Latex')
- title(chan_name, 'FontSize', title_font_size)
- xticks(xlims(1):200:xlims(2)); % Set x-axis ticks in steps of 100 ms
- % yticks(ylims);
- set(gca, 'FontSize', axis_font_size); % Set font size for axis values
- grid on;
- grid minor;
- box on;
- % Add legend only for the first subplot
- if ch_idx == 1
- legend([plt1, plt2],{'shuffled','sorted'},'Interpreter', 'none','Location','Southeast','FontSize',legend_font_size)
- end
- if ch_idx <= 4
- xticklabels([]); % Hides the numbers, but keeps grid lines
- end
- end
- % Link the X-axes of all subplots
- linkaxes(axis_handles, 'xy');
- % Setting it on one linked axis will propagate to all others
- ylims = [minval, maxval]; % Centralized Y-axis limits
- set(axis_handles, 'XLim', xlims, 'YLim', ylims);
- % Cross-correlation timeseries
- %-----------------------------
- figure('Color', 'w')
- cfg = [];
- cfg.showlabels = 'yes';
- cfg.fontsize = 6;
- cfg.layout = 'neuromag306mag_helmet.lay';
- % cfg.layout = 'neuromag306planar_helmet.lay';
- cfg.linestyle = {'-','-'};
- cfg.linecolor = 'rb'; % shuffled: red, sorted: blue
- cfg.showlabels = 'on';
- cfg.showcomment = 'off';
- cfg.showscale = 'off';
- cfg.linewidth = 1;
- ft_multiplotER(cfg,gavg_crosscorr_shuffled,gavg_crosscorr);
- %% Visualize cross correlations
- %--------------------------------------------------------------------------
- sensortype = 'megmag';
- % sensortype = 'megplanar';
- switch sensortype
- case 'megmag'
- is_sensor = endsWith(gavg_crosscorr.label, '1');
- is_sensor2 = endsWith(gavg_crosscorr_shuffled.label, '1');
- case 'megplanar'
- is_sensor = endsWith(gavg_crosscorr.label, '2') | endsWith(gavg_crosscorr.label, '3');
- is_sensor2 = endsWith(gavg_crosscorr_shuffled.label, '2') | endsWith(gavg_crosscorr_shuffled.label, '3');
- end
- % Check if the two logical arrays are identical. If not, throw an error.
- if ~isequal(is_sensor, is_sensor2)
- error('Mismatch in sensor labels: The order or type of channels in the two datasets does not match.');
- end
- n_channels = sum(is_sensor);
- timevec = gavg_crosscorr.time*1000;
- xlims = [-100,900];
- axis_font_size = 16;
- legend_font_size = 16;
- title_font_size = 18;
- % All channels same color
- %--------------------------------------------------------------------------
- figure;
- h1 = plot(timevec, gavg_crosscorr.avg(is_sensor,:), 'b', 'LineWidth', 1);
- hold on;
- h2 = plot(timevec, gavg_crosscorr_shuffled.avg(is_sensor,:), 'r', 'LineWidth', 1);
- hold off;
- xlabel('t / ms')
- ylabel('$\hat{R}$','Interpreter','Latex')
- title('Comparison of Original and Shuffled Cross-Correlations');
- xticks(xlims(1):200:xlims(2)); % Set x-axis ticks in steps of 100 ms
- set(gca, 'FontSize', axis_font_size); % Set font size for axis values
- legend([h1(1), h2(1)], {'Sorted', 'Shuffled'}, 'Location', 'Southeast');
- grid on;
- grid minor;
- box on;
- % Color grouped by sensor location
- %--------------------------------------------------------------------------
- channel_layout_meg = importdata('channel_layout_meg.mat');
- channel_subsets = cell(1,4);
- channel_subsets{4} = unique([channel_layout_meg.occipital_left(:); channel_layout_meg.occipital_right(:)]); % occipital_channels
- channel_subsets{3} = unique([channel_layout_meg.parietal_left(:); channel_layout_meg.parietal_right(:)]); % parietal_channels
- channel_subsets{2} = unique([channel_layout_meg.frontal_left(:); channel_layout_meg.frontal_right(:)]); % frontal channels
- channel_subsets{1} = unique([channel_layout_meg.temporal_left(:); channel_layout_meg.temporal_right(:)]); % temporal channels
- channel_subsets_label = {'Sorted (temporal)','Sorted (frontal)','Sorted (parietal)','Sorted (occipital)'};
- cmap = [
- 0.0000 0.2980 0.5294; % Dark Blue (#004C87)
- 0.2000 0.7451 0.9333; % Cyan (#33BEE7)
- 0.4660 0.6740 0.1880; % Green (#77AB30)
- 0.9290 0.5940 0.1920 % Orange (#ED9731)
- ];
- line_styles = {'-','--',':','-.'};
- % line_styles = {'-','-','-','-'};
- % Compute limits
- %---------------
- all_data = [gavg_crosscorr.avg(is_sensor,:); gavg_crosscorr_shuffled.avg(is_sensor,:)];
- % 2. Find the absolute min and max across all the data
- min_val = min(all_data(:));
- max_val = max(all_data(:));
- clear all_data
- data_range = max_val - min_val;
- padding = 0.05 * data_range;
- yLims = [min_val - padding, max_val + padding];
- figure;
- subplot(2,1,1)
- hold on;
- % Pre-allocate a vector to store plot handles for the legend
- h = gobjects(1, length(channel_subsets) + 2);
- for loc_idx = 1:length(channel_subsets)
- subset_idx = contains(gavg_crosscorr.label, channel_subsets{loc_idx});
- chan_idx = and(is_sensor,subset_idx); % channel type + subsets
- plot_handles = plot(timevec, gavg_crosscorr.avg(chan_idx,:), 'color', cmap(loc_idx,:), 'LineWidth', 1, 'LineStyle', line_styles{loc_idx});
- % Save only the FIRST handle from this group for the legend
- if ~isempty(plot_handles)
- h(loc_idx) = plot_handles(1);
- end
- end
- plot_handles = plot(timevec, gavg_crosscorr_shuffled.avg(is_sensor,:), 'color', 'r', 'LineWidth', 1);
- h(length(channel_subsets)+1) = plot_handles(1);
- % Define patch properties
- patchColor = [1, 1, 0]; % A light, transparent yellow
- patchAlpha = 0.2;
- % Create the first patch for the 50-90ms window
- p1 = patch([timewindows_statistic(1,1), timewindows_statistic(1,2), timewindows_statistic(1,2), timewindows_statistic(1,1)]*1000, [yLims(1), yLims(1), yLims(2), yLims(2)], ...
- patchColor, 'FaceAlpha', patchAlpha, 'EdgeColor', 'none');
- h(end) = p1;
- % Create the second patch for the 160-230ms window
- p2 = patch([timewindows_statistic(2,1), timewindows_statistic(2,2), timewindows_statistic(2,2), timewindows_statistic(2,1)]*1000, [yLims(1), yLims(1), yLims(2), yLims(2)], ...
- patchColor, 'FaceAlpha', patchAlpha, 'EdgeColor', 'none');
- % Send the patches to the background, behind the data lines
- uistack([p1, p2], 'bottom');
- hold off;
- xlabel('t / ms')
- ylabel('$\hat{R}$','Interpreter','Latex')
- title('Butterfly plot cross-correlation functions');
- xticks(xlims(1):200:xlims(2)); % Set x-axis ticks in steps of 100 ms
- set(gca, 'FontSize', axis_font_size); % Set font size for axis values
- ylim(yLims)
- legend(h, [channel_subsets_label, 'Shuffled', 'time window statistic'], 'Location', 'Southeast', 'NumColumns', 5);
- grid on;
- grid minor;
- box on;
- % Create dummy data for mapping color coding of sensors
- %------------------------------------------------------
- dummy_data = gavg_crosscorr_raweffect;
- dummy_data.time = 0;
- dummy_data.avg = zeros(306,1);
- for loc_idx = 1:length(channel_subsets)
- subset_idx = contains(dummy_data.label, channel_subsets{loc_idx});
- dummy_data.avg(subset_idx) = loc_idx;
- end
- % Highlight channels in topoplot
- %-------------------------------
- fig = figure('Color', 'w');
- hold on
- cfg = [];
- cfg.comment = 'no';
- cfg.xlim = [0,0];
- cfg.markersize = 20;
- cfg.markersymbol = '.';
- cfg.highlight = 'on';
- cfg.highlightchannel = chan2plot;
- cfg.highlightcolor = 'k';
- cfg.highlightsize = 50;
- cfg.highlightsymbol = '.';
- cfg.layout = 'neuromag306mag_helmet.lay';
- cfg.interactive = 'no';
- cfg.colorbar = 'yes';
- cfg.interpolation = 'nearest';
- cfg.figure = fig;
- ft_topoplotER(cfg,dummy_data); % plot difference
- colormap(cmap)
- %% Functions
- %--------------------------------------------------------------------------
- function mask = give_stat_mask(stat,alpha)
- %--------------------------------------------------------------------------
- % Till Habersetzer, 01.07.2025
- % Communication Acoustics, CvO University Oldenburg
- % [email hidden]
- %
- % MASK = GIVE_STAT_MASK(STAT, ALPHA) takes the output of a FieldTrip
- % cluster-based permutation analysis (STAT) and a desired alpha-value.
- % It returns a binary mask (MASK) where significant clusters (p < ALPHA)
- % are marked with 'true' and non-significant areas with 'false'.
- % This mask can be used for visualizing statistically significant regions.
- %
- % Inputs:
- % stat - Structure array containing the results of ft_timelockstatistics
- % or ft_sourcestatistics, including cluster information.
- % alpha - Desired significance level (e.g., 0.05) for thresholding the clusters.
- %
- % Output:
- % mask - A logical array (binary mask) indicating the significant
- % clusters. True for significant, false for non-significant.
- %
- % Example Usage for plotting the mask:
- % Assuming 'stat' is the result of a FieldTrip cluster analysis
- % and 'alpha' is your significance level (e.g., 0.05)
- % mask = give_stat_mask(stat, alpha);
- % figure;
- % imagesc(mask);
- % colormap(gray); % or any suitable colormap for binary masks
- %--------------------------------------------------------------------------
- % positive clusters
- %------------------
- pos_cluster_pvals = [stat.posclusters(:).prob];
- pos_signif_clust = find(pos_cluster_pvals < alpha);
- pos = ismember(stat.posclusterslabelmat, pos_signif_clust);
- % negative clusters
- %------------------
- neg_cluster_pvals = [stat.negclusters(:).prob];
- neg_signif_clust = find(neg_cluster_pvals < alpha);
- neg = ismember(stat.negclusterslabelmat, neg_signif_clust);
- % combine clusters
- %-----------------
- mask = or(neg,pos);
- end
plot_crosscorr.m at commit 32bfc69, under BSD-3-Clause · at the source
Overview
- Communication Acoustics, Department of Medical Physics and Acoustics and Cluster of Excellence ”Hearing4all”, Carl von Ossietzky Universität Oldenburg, Oldenburg, Germany
- TUD Dresden University of Technology, Dresden, Germany
- Department of Otolaryngology, Head and Neck Surgery, Carl von Ossietzky Universität Oldenburg, Oldenburg, Germany
Abstract
The abstract is not reproduced here: the paper's license (none stated) does not allow it. Read it in the paper, at the publisher or on Europe PMC.
Repositories
Its files are read in the Code ↔ Paper reader above, with 16 matches between paragraphs and lines of code.
tillhabersetzer/MEG-SCANS
32bfc690e28e7591b45d96615c59b2d53b6a7165, 10 December 2025Availability: 1 check, the latest on 26 September 2026: the link answers
- 26 September 2026: the link answers
47 files
- behavioral/
plot_audiograms.m , MATLAB, 98 lines, 2 matches - chirps/
sensorlevel/ , MATLAB, 317 lines, 1 matchcompute_aefs.m - chirps/
sensorlevel/ , MATLAB, 401 linesplot_aefs_grouplevel.m - chirps/
sensorlevel/ , MATLAB, 115 linesplot_aefs_subjectlevel.m - chirps/
settings_chirps.m , MATLAB, 41 lines - chirps/
sourcelevel/ , MATLAB, 129 linescheck_coregistration.m - chirps/
sourcelevel/ , MATLAB, 192 linescompute_dipolfit.m - chirps/
sourcelevel/ , MATLAB, 299 lines, 1 matchcompute_headmodel_source model.m - chirps/
sourcelevel/ , MATLAB, 420 lines, 2 matchesplot_dipolfit_grouplevel .m - chirps/
sourcelevel/ , MATLAB, 227 lines, 1 matchplot_dipolfit_subjectlev el.m - helper_functions/
._my_trialfun_audiobook. , MATLAB, not shown herem - helper_functions/
bluewhitered.m , MATLAB, 122 lines - helper_functions/
cal_envelope.m , MATLAB, 146 lines, 2 matches - helper_functions/
check_diploc.m , MATLAB, 34 lines - helper_functions/
constrained_dipolfitting , MATLAB, 155 lines.m - helper_functions/
distinguishable_colors.m , MATLAB, 152 lines - helper_functions/
getpos.m , MATLAB, 182 lines - helper_functions/
hatchfill2.m , MATLAB, 1,095 lines - helper_functions/
legendflex.m , MATLAB, 924 lines - helper_functions/
my_trialfun_audiobook.m , MATLAB, 74 lines - helper_functions/
my_trialfun_olsa.m , MATLAB, 68 lines - helper_functions/
read_events_modified.m , MATLAB, 109 lines - helper_functions/
setpos.m , MATLAB, 189 lines - maxfilter/
apply_maxfilter_parallel , Python, 404 lines, 2 matches.py - maxfilter/
check_maxfilter_stats.py , Python, 116 lines - maxfilter/
plot_trafo.py , Python, 135 lines - speech/
._settings_speech.m , MATLAB, not shown here - speech/
audio_envelopes_audioboo , MATLAB, 201 linesk.m - speech/
audio_envelopes_olsa.m , MATLAB, 276 lines - speech/
crosscorrelation/ , MATLAB, not shown here._compute_crosscorr.m - speech/
crosscorrelation/ , MATLAB, not shown here._preprocessing_crosscor r.m - speech/
crosscorrelation/ , MATLAB, 105 linesanalysis_pipeline_crossc orr.m - speech/
crosscorrelation/ , MATLAB, 135 linescomputation_crosscorr.m - speech/
crosscorrelation/ , MATLAB, 67 linescomputation_gavg_crossco rr.m - speech/
crosscorrelation/ , MATLAB, 607 lines, 2 matchesplot_crosscorr.m - speech/
crosscorrelation/ , MATLAB, 210 linespreprocessing_audio.m - speech/
crosscorrelation/ , MATLAB, 308 linespreprocessing_crosscorr. m - speech/
decoding/ , MATLAB, 112 linesanalysis_pipeline_decodi ng.m - speech/
decoding/ , MATLAB, 770 linesplot_decoding.m - speech/
decoding/ , MATLAB, 256 linespreprocessing_audiobooks .m - speech/
decoding/ , MATLAB, 314 linespreprocessing_audiobooks _decoding.m - speech/
decoding/ , MATLAB, 135 linespreprocessing_olsa.m - speech/
decoding/ , MATLAB, 221 linespreprocessing_olsa_decod ing.m - speech/
decoding/ , MATLAB, 386 lines, 2 matchestraining_decoding.m - speech/
settings_speech.m , MATLAB, 64 lines, 1 match - LICENSE, License, 28 lines
- README.md, Text, 176 lines
Zenodo 17397581
Availability: 1 check, the latest on 26 September 2026: the link answers (HTTP 200)
- 26 September 2026: the link answers (HTTP 200)
47 files
- behavioral/
plot_audiograms.m , MATLAB, 98 lines - chirps/
sensorlevel/ , MATLAB, 317 linescompute_aefs.m - chirps/
sensorlevel/ , MATLAB, 401 linesplot_aefs_grouplevel.m - chirps/
sensorlevel/ , MATLAB, 115 linesplot_aefs_subjectlevel.m - chirps/
settings_chirps.m , MATLAB, 41 lines - chirps/
sourcelevel/ , MATLAB, 129 linescheck_coregistration.m - chirps/
sourcelevel/ , MATLAB, 192 linescompute_dipolfit.m - chirps/
sourcelevel/ , MATLAB, 299 linescompute_headmodel_source model.m - chirps/
sourcelevel/ , MATLAB, 420 linesplot_dipolfit_grouplevel .m - chirps/
sourcelevel/ , MATLAB, 227 linesplot_dipolfit_subjectlev el.m - helper_functions/
._my_trialfun_audiobook. , MATLAB, not shown herem - helper_functions/
bluewhitered.m , MATLAB, 122 lines - helper_functions/
cal_envelope.m , MATLAB, 146 lines - helper_functions/
check_diploc.m , MATLAB, 34 lines - helper_functions/
constrained_dipolfitting , MATLAB, 155 lines.m - helper_functions/
distinguishable_colors.m , MATLAB, 152 lines - helper_functions/
getpos.m , MATLAB, 182 lines - helper_functions/
hatchfill2.m , MATLAB, 1,095 lines - helper_functions/
legendflex.m , MATLAB, 924 lines - helper_functions/
my_trialfun_audiobook.m , MATLAB, 74 lines - helper_functions/
my_trialfun_olsa.m , MATLAB, 68 lines - helper_functions/
read_events_modified.m , MATLAB, 109 lines - helper_functions/
setpos.m , MATLAB, 189 lines - maxfilter/
apply_maxfilter_parallel , Python, 404 lines.py - maxfilter/
check_maxfilter_stats.py , Python, 116 lines - maxfilter/
plot_trafo.py , Python, 135 lines - speech/
._settings_speech.m , MATLAB, not shown here - speech/
audio_envelopes_audioboo , MATLAB, 201 linesk.m - speech/
audio_envelopes_olsa.m , MATLAB, 276 lines - speech/
crosscorrelation/ , MATLAB, not shown here._compute_crosscorr.m - speech/
crosscorrelation/ , MATLAB, not shown here._preprocessing_crosscor r.m - speech/
crosscorrelation/ , MATLAB, 105 linesanalysis_pipeline_crossc orr.m - speech/
crosscorrelation/ , MATLAB, 135 linescomputation_crosscorr.m - speech/
crosscorrelation/ , MATLAB, 67 linescomputation_gavg_crossco rr.m - speech/
crosscorrelation/ , MATLAB, 607 linesplot_crosscorr.m - speech/
crosscorrelation/ , MATLAB, 210 linespreprocessing_audio.m - speech/
crosscorrelation/ , MATLAB, 308 linespreprocessing_crosscorr. m - speech/
decoding/ , MATLAB, 112 linesanalysis_pipeline_decodi ng.m - speech/
decoding/ , MATLAB, 770 linesplot_decoding.m - speech/
decoding/ , MATLAB, 256 linespreprocessing_audiobooks .m - speech/
decoding/ , MATLAB, 314 linespreprocessing_audiobooks _decoding.m - speech/
decoding/ , MATLAB, 135 linespreprocessing_olsa.m - speech/
decoding/ , MATLAB, 221 linespreprocessing_olsa_decod ing.m - speech/
decoding/ , MATLAB, 386 linestraining_decoding.m - speech/
settings_speech.m , MATLAB, 64 lines - LICENSE, License, 28 lines
- README.md, Text, 175 lines
Code availability statement
The paper has a code availability statement. Its license (none stated) does not allow reproducing it here; in short, from what the harvester recognized in it:
- it points to the authors' code: tillhabersetzer/
MEG-SCANS
Read it in the paper: doi.org/10.1038/s41597-025-06397-4.
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:
- 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 90 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
Datasets cited
- doi:10.18112/
openneuro.ds005346.v1.0. , at OpenNeuro; found in the references3 - doi:10.18112/
openneuro.ds006468.v1.1. , at OpenNeuro; found in the references1 - github.com/
nemardatasets/ , at github.com; found in DataCiteon006468 - openneuro:ds006468, at OpenNeuro; found in the text, “Data Records”
- zenodo:12793944, at Zenodo; found in the references
- zenodo:12794769, at Zenodo; found in the references
- zenodo:12794808, at Zenodo; found in the references
Data availability statement
The paper has a data availability statement. Its license (none stated) does not allow reproducing it here; in short, from what the harvester recognized in it:
- no repository, dataset or request procedure was recognized in it
Read it in the paper: doi.org/10.1038/s41597-025-06397-4.
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, 4 authors, 2 keywords, 6 MeSH terms, 1 funder, 61 references.
Cite
This paper
Habersetzer, T., Steuer, S., Radeloff, A., & Meyer, B. T. (2025). MEG-SCANS - A comprehensive magnetoencephalography speech dataset with Stories, Chirps and Noisy Sentences. Scientific Data, 12(1), 1938. https://
BibTeX
@article{habersetzer2025
author = {Habersetzer, Till and Steuer, Svea and Radeloff, Andreas and Meyer, Bernd T},
title = {{MEG-SCANS - A comprehensive magnetoencephalography speech dataset with Stories, Chirps and Noisy Sentences}},
journal = {Scientific Data},
year = {2025},
volume = {12},
number = {1},
pages = {1938},
publisher = {Nature Publishing Group},
issn = {2052-4463},
doi = {10.1038/
url = {https://
pmcid = {PMC12695901}
}
RIS
TY - JOUR
AU - Habersetzer, Till
AU - Steuer, Svea
AU - Radeloff, Andreas
AU - Meyer, Bernd T
TI - MEG-SCANS - A comprehensive magnetoencephalography speech dataset with Stories, Chirps and Noisy Sentences
T2 - Scientific Data
J2 - Sci Data
PY - 2025
DA - 2025
VL - 12
IS - 1
SP - 1938
SN - 2052-4463
PB - Nature Publishing Group
DO - 10.1038/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1038/
"type": "article-journal",
"title": "MEG-SCANS - A comprehensive magnetoencephalography speech dataset with Stories, Chirps and Noisy Sentences",
"container-title": "Scientific Data",
"author": [
{
"family": "Habersetzer",
"given": "Till"
},
{
"family": "Steuer",
"given": "Svea"
},
{
"family": "Radeloff",
"given": "Andreas"
},
{
"family": "Meyer",
"given": "Bernd T"
}
],
"container-title-short":
"volume": "12",
"issue": "1",
"page": "1938",
"DOI": "10.1038/
"PMCID": "PMC12695901",
"ISSN": "2052-4463",
"publisher": "Nature Publishing Group",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2025
]
]
}
}
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.1523/eneuro.0069-26.2026 [code]
- Electrophysiological Indices of Hierarchical Speech Processing Differentially Reflect the Comprehension of Speech in Noise.Journal: eNeuroIn common: Statistics and Machine Learning Toolbox, 12 references
- [2] doi:10.1038/s41597-026-07215-1 [code]
- The Brain, Body, and Behavior Dataset (BBBD): Multimodal Recordings during Educational Videos.Journal: Scientific dataIn common: MNE-Python, Signal Processing Toolbox, Statistics and Machine Learning Toolbox, 4 other tools, methods / tools, 4 references
- [3] doi:10.1111/ejn.70598 [code]
- Enhanced Time-Locked Decoding for Spoken Words but Not Environmental Sounds in Natural-Like Auditory Conditions.Journal: The European journal of neuroscienceIn common: MEG, 8 references
- [4] doi:10.1162/imag.a.1227 [code]
- Large language models reveal the neural tracking of linguistic context in attended and unattended multi-talker speech.Journal: Imaging neuroscience (Cambridge, Mass.)In common: MNE-Python, pandas, SciPy, 2 other tools, 5 references
- [5] doi:10.1162/imag.a.1040 [code]
- Novel 4 He-OPMs support waveform-specific beta burst analysis comparable to SQUID-MEGJournal: n/aIn common: FieldTrip, MNE-Python, Signal Processing Toolbox, 5 other tools, MEG, 2 references
- [6] doi:10.1038/s41597-026-07350-9 [code]
- An open multi-center MEG-EEG dataset for studying conscious visual perception.Journal: Scientific dataIn common: MNE-Python, Statistics and Machine Learning Toolbox, pandas, 3 other tools, MEG, structural MRI / diffusion, 4 references
- [7] doi:10.1038/s41467-026-73553-8 [code]
- Universal rhythmic architecture uncovers two modes of neural dynamics.Journal: Nature communicationsIn common: FieldTrip, MNE-Python, Signal Processing Toolbox, 5 other tools, 3 references
- [8] doi:10.1162/imag.a.1269 [code]
- From early to contemporary normative modeling: Mapping individual differences in neurophysiological signals.Journal: Imaging neuroscience (Cambridge, Mass.)In common: MNE-Python, pandas, SciPy, 2 other tools, MEG, 6 references
- [9] doi:10.1111/ejn.70538 [code]
- Neural Tracking of Sustained Attention, Attention Switching, and Natural Conversation in Audiovisual Environments Using Wearable EEG.Journal: The European journal of neuroscienceIn common: MNE-Python, pandas, SciPy, 2 other tools, 5 references
- [10] doi:10.1038/s41597-025-05174-7 [code]
- A large-scale MEG and EEG dataset for object recognition in naturalistic scenesJournal: n/aIn common: MNE-Python, pandas, SciPy, 2 other tools, MEG, methods / tools, 4 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: 2 repositories of the authors' code, each at its verified commit and with its license, 90 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:9b2a1b39a3685de0…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
