How to extract pre and post event data segments from evoked/epoch data?

HI everyone,

I am looking to replicate the following analysis:

evoked_stats

On the left, is the evoked data (GFP) plot for a selection of sensors for one condition vs. another. On the right, is the averaged GFP data represented on the left plot on the corresponding dark grey and light grey time segments.

I searched through the MNE API to see if there is a direct way of extracting two subsets of data of different time windows from a single mne.epochs output, but there doesn’t seem to be any.

I thought about splitting an epoch into two subsets using evoked_data.crop(-1.5,-1.0) and evoked_data.crop(1.0,1.5) but that wouldn’t work since MNE would not be able to simultaneously plot the two data sets since they are of different time windows and they can’t seem be re-centred to 0.0s.

Alternatively, I think it is possible to create two different new events (pre and post event) by manipulating the original data’s time stamp, then add them via raw.add_events at the data pre-processing stage. But this is extremely tedious for me since I have multiple event types and I will end up with a large, messy set of events_id.

So my question is, is there any MNE function out there that I am not aware of that is capable of helping me get what I require here in the neatest way possible? If not, then how do people usually do this using what is already available on MNE? To summarize, I am looking to:

  1. Be able to extract subsets of an epoch data based on specified time windows,
  2. Access the epoch data (epoch.data doesn’t work) so I can calculate the mean evoked value (eg. average GFP of GFP activity between -1.5 to -1.0s) explicitly from these extracts.

epochs.get_data() will return a copy of the data as a numpy array. You can then use numpy array slicing to extract the time window(s) of your choice. To get the array indices you may find epochs.time_as_index() to be useful.

1 Like

Hi @drammock ,

Thank you for the advice. So I tried to play around with slicing the data and all and managed to get somewhat what I was looking for.

However, the bar plot here is still a little off. The Evoked data was plotted using mne.viz.plot_compare_evokeds. At first I tried to look into the source code for mne.viz.plot_compare_evokeds to try to extract the data used for both the blue and orange lines, but I found myself lost in the sea of codes. So I tried to extract the data myself using the same two Evoked data set sent to mne.viz.plot_compare_evokeds for the evoked plot. I did this by:

  1. Extracting the raw evoked data from the corresponding Evoked data for both conditions at the greyed time windows.
  2. I then averaged the data falling within each grey time windows for the 2 conditions (so 4 mean values in total - 2 condition x 2 time windows), then averaged the data again across all sensors used.

But I am getting negative values from this calculation (2nd bar in bar plot), which is puzzling since the mne.viz.plot_compare_evokeds line plots are all positive. I suppose some sort of re-plotting of raw evoked data into Ft/cm took place involved squaring or making a value absolute at some point.

Can I get pin pointed to the formula used in mne.viz.plot_compare_evokeds to convert the evoked data into Ft/cm? Or even better, is there a way I can just simply extract the values from the mne.viz.plot_compare_evokeds that was used to plot the evoked data?

Here’s an example that uses our sample data that should do what you want. I’ve tried to make the variable names sufficiently descriptive that you can figure out what’s going on, but feel free to ask if something doesn’t make sense. I didn’t go all-out on the colors/labels for the barplot, LMK if you need help with that.

import os
import numpy as np
import matplotlib.pyplot as plt
import mne
plt.ion()
sample_data_folder = mne.datasets.sample.data_path()
sample_data_evk_file = os.path.join(sample_data_folder, 'MEG', 'sample',
                                    'sample_audvis-ave.fif')
evokeds_list = mne.read_evokeds(
    sample_data_evk_file, 
    condition=['Left Auditory', 'Left visual'],
    baseline=(None, 0),
    proj=True,
    verbose=False)

t_ranges = dict(baseline=(-0.15, -0.05), n100=(0.05, 0.15))

bar_data = dict()
for evk_name, evk in zip(('aud', 'vis'), evokeds_list):
    for name, t_range in t_ranges.items():
        idx = evk.time_as_index(t_range)
        data = evk.copy().pick('eeg').data[:, slice(*idx)]
        gfp = (data * 1e6).std(axis=0, ddof=0)  # 1e6 converts V → μV
        bar_data[f'{evk_name}_{name}'] = gfp.mean()

fig, axs = plt.subplots(1, 2, figsize=(8, 3),
                        gridspec_kw=dict(width_ratios=(2, 1)))
mne.viz.plot_compare_evokeds(evokeds_list, picks='eeg', axes=axs[0])
for t_range in t_ranges.values():
    axs[0].axvspan(*t_range, color='k', alpha=0.2)

bar_x = (1, 2, 4, 5)
bar_y = [bar_data[key] for key in
         ('aud_n100', 'vis_n100', 'aud_baseline', 'vis_baseline')]

axs[1].bar(bar_x, bar_y)

Here is the result:

1 Like