The Epochs data structure: epoched data

Epochs objects are a way of representing continuous data as a collection of time-locked trials, stored in an array of shape (n_events, n_channels, n_times). They are useful for many statistical methods in neuroscience, and make it easy to quickly overview what occurs during a trial.

import mne
import os.path as op
import numpy as np
from matplotlib import pyplot as plt
Epochs objects can be created in three ways:
  1. From a Raw object, along with event times
  2. From an Epochs object that has been saved as a .fif file
  3. From scratch using EpochsArray. See Creating MNE’s data structures from scratch
data_path = mne.datasets.sample.data_path()
# Load a dataset that contains events
raw = mne.io.read_raw_fif(
    op.join(data_path, 'MEG', 'sample', 'sample_audvis_raw.fif'))

# If your raw object has a stim channel, you can construct an event array
# easily
events = mne.find_events(raw, stim_channel='STI 014')

# Show the number of events (number of rows)
print('Number of events:', len(events))

# Show all unique event codes (3rd column)
print('Unique event codes:', np.unique(events[:, 2]))

# Specify event codes of interest with descriptive labels.
# This dataset also has visual left (3) and right (4) events, but
# to save time and memory we'll just look at the auditory conditions
# for now.
event_id = {'Auditory/Left': 1, 'Auditory/Right': 2}

Out:

('Number of events:', 320)
('Unique event codes:', array([ 1,  2,  3,  4,  5, 32]))

Now, we can create an mne.Epochs object with the events we’ve extracted. Note that epochs constructed in this manner will not have their data available until explicitly read into memory, which you can do with get_data. Alternatively, you can use preload=True.

Expose the raw data as epochs, cut from -0.1 s to 1.0 s relative to the event onsets

epochs = mne.Epochs(raw, events, event_id, tmin=-0.1, tmax=1,
                    baseline=(None, 0), preload=True)
print(epochs)

Out:

<Epochs  |  n_events : 145 (all good), tmin : -0.0998976065792 (s), tmax : 1.0006410259 (s), baseline : (None, 0), ~279.1 MB, data loaded,
 'Auditory/Left': 72, 'Auditory/Right': 73>

Epochs behave similarly to mne.io.Raw objects. They have an info attribute that has all of the same information, as well as a number of attributes unique to the events contained within the object.

print(epochs.events[:3])
print(epochs.event_id)

Out:

[[27977     0     2]
 [28771     0     1]
 [29652     0     2]]
{'Auditory/Right': 2, 'Auditory/Left': 1}

You can select subsets of epochs by indexing the Epochs object directly. Alternatively, if you have epoch names specified in event_id then you may index with strings instead.

print(epochs[1:5])
print(epochs['Auditory/Right'])

Out:

<Epochs  |  n_events : 4 (all good), tmin : -0.0998976065792 (s), tmax : 1.0006410259 (s), baseline : (None, 0), ~11.4 MB, data loaded,
 'Auditory/Left': 2, 'Auditory/Right': 2>
<Epochs  |  n_events : 73 (all good), tmin : -0.0998976065792 (s), tmax : 1.0006410259 (s), baseline : (None, 0), ~142.4 MB, data loaded>

It is also possible to iterate through Epochs objects in this way. Note that behavior is different if you iterate on Epochs directly rather than indexing:

# These will be epochs objects
for i in range(3):
    print(epochs[i])

# These will be arrays
for ep in epochs[:2]:
    print(ep)

Out:

<Epochs  |  n_events : 1 (all good), tmin : -0.0998976065792 (s), tmax : 1.0006410259 (s), baseline : (None, 0), ~5.7 MB, data loaded>
<Epochs  |  n_events : 1 (all good), tmin : -0.0998976065792 (s), tmax : 1.0006410259 (s), baseline : (None, 0), ~5.7 MB, data loaded>
<Epochs  |  n_events : 1 (all good), tmin : -0.0998976065792 (s), tmax : 1.0006410259 (s), baseline : (None, 0), ~5.7 MB, data loaded>
[[ -1.56510152e-12  -6.00746037e-13   3.63609444e-13 ...,  -5.42252344e-12
   -3.49381248e-12   8.07845329e-12]
 [  4.71111366e-12   2.78240270e-12  -1.10663744e-13 ...,  -2.03937471e-12
   -1.07501922e-12   1.81804722e-12]
 [  1.27694161e-13   1.26810933e-13   8.74659808e-14 ...,   3.27176412e-14
    5.59107736e-14   6.80975243e-14]
 ...,
 [ -7.88218509e-06  -9.77900515e-06  -9.28950320e-06 ...,  -6.53605473e-06
   -7.14793216e-06  -8.80000125e-06]
 [ -6.95813002e-06  -8.06909195e-06  -7.19201674e-06 ...,  -6.25646985e-06
   -6.60729993e-06  -8.36145036e-06]
 [  1.26772322e-05   1.26772322e-05   1.33309187e-05 ...,  -1.41239155e-05
   -1.41239155e-05  -1.15091693e-05]]
[[ -1.38645862e-11  -1.48289417e-11  -1.48289417e-11 ...,   4.45816796e-12
    4.45816796e-12   8.31558988e-12]
 [ -9.01119056e-12  -1.19042570e-11  -1.28686125e-11 ...,   1.59671973e-12
    3.52543069e-12   3.52543069e-12]
 [ -6.12059507e-13  -6.39043401e-13  -7.73632967e-13 ...,   1.21753954e-14
    2.69203700e-14   7.25978380e-15]
 ...,
 [ -4.51786226e-06  -4.76261324e-06  -2.74341769e-06 ...,   3.89254358e-05
    3.80688074e-05   3.61107996e-05]
 [ -1.06849808e-05  -1.15035843e-05  -1.05680374e-05 ...,   2.79648003e-05
    2.49242729e-05   2.21761039e-05]
 [  3.34344584e-06   7.28699735e-07  -3.19341943e-06 ...,   7.50132080e-08
   -5.78673319e-07   3.34344584e-06]]

You can manually remove epochs from the Epochs object by using epochs.drop(idx), or by using rejection or flat thresholds with epochs.drop_bad(reject, flat). You can also inspect the reason why epochs were dropped by looking at the list stored in epochs.drop_log or plot them with epochs.plot_drop_log(). The indices from the original set of events are stored in epochs.selection.

epochs.drop([0], reason='User reason')
epochs.drop_bad(reject=dict(grad=2500e-13, mag=4e-12, eog=200e-6), flat=None)
print(epochs.drop_log)
epochs.plot_drop_log()
print('Selection from original events:\n%s' % epochs.selection)
print('Removed events (from numpy setdiff1d):\n%s'
      % (np.setdiff1d(np.arange(len(events)), epochs.selection).tolist(),))
print('Removed events (from list comprehension -- should match!):\n%s'
      % ([li for li, log in enumerate(epochs.drop_log) if len(log) > 0]))
../_images/sphx_glr_plot_object_epochs_001.png

Out:

[['User reason'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [u'EOG 061'], ['IGNORED'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], [], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], ['IGNORED'], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], ['IGNORED'], ['IGNORED'], [], ['IGNORED'], [u'MEG 1711'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], [], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], ['IGNORED'], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [u'MEG 1711'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], ['IGNORED'], ['IGNORED'], [], ['IGNORED'], [u'EOG 061', u'MEG 1421'], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], ['IGNORED'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [u'EOG 061', u'MEG 1421'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], ['IGNORED'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], [u'EOG 061'], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], ['IGNORED'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], [], ['IGNORED'], ['IGNORED']]
Selection from original events:
[  2   4   6   8  10  12  14  19  21  23  25  27  29  31  33  35  38  42
  44  46  48  50  52  54  56  58  63  65  67  69  71  73  75  77  88  90
  92  94  96  98 101 103 105 107 109 111 113 115 117 122 126 128 130 132
 134 136 138 140 142 145 151 153 155 157 159 161 168 170 174 176 178 182
 184 189 191 193 197 199 201 206 214 218 220 222 224 229 231 233 235 237
 239 241 243 245 248 250 252 254 256 258 262 264 269 271 273 281 285 290
 292 294 296 298 300 302 304 306 308 310 313 315 317]
Removed events (from numpy setdiff1d):
[0, 1, 3, 5, 7, 9, 11, 13, 15, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 37, 39, 40, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 60, 61, 62, 64, 66, 68, 70, 72, 74, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 89, 91, 93, 95, 97, 99, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 119, 120, 121, 123, 124, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 144, 146, 147, 148, 149, 150, 152, 154, 156, 158, 160, 162, 163, 164, 165, 166, 167, 169, 171, 172, 173, 175, 177, 179, 180, 181, 183, 185, 186, 187, 188, 190, 192, 194, 195, 196, 198, 200, 202, 203, 204, 205, 207, 208, 209, 210, 211, 212, 213, 215, 216, 217, 219, 221, 223, 225, 226, 227, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 247, 249, 251, 253, 255, 257, 259, 260, 261, 263, 265, 266, 267, 268, 270, 272, 274, 275, 276, 277, 278, 279, 280, 282, 283, 284, 286, 287, 288, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 311, 312, 314, 316, 318, 319]
Removed events (from list comprehension -- should match!):
[0, 1, 3, 5, 7, 9, 11, 13, 15, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 37, 39, 40, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 60, 61, 62, 64, 66, 68, 70, 72, 74, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 89, 91, 93, 95, 97, 99, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 119, 120, 121, 123, 124, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 144, 146, 147, 148, 149, 150, 152, 154, 156, 158, 160, 162, 163, 164, 165, 166, 167, 169, 171, 172, 173, 175, 177, 179, 180, 181, 183, 185, 186, 187, 188, 190, 192, 194, 195, 196, 198, 200, 202, 203, 204, 205, 207, 208, 209, 210, 211, 212, 213, 215, 216, 217, 219, 221, 223, 225, 226, 227, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 247, 249, 251, 253, 255, 257, 259, 260, 261, 263, 265, 266, 267, 268, 270, 272, 274, 275, 276, 277, 278, 279, 280, 282, 283, 284, 286, 287, 288, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 311, 312, 314, 316, 318, 319]

If you wish to save the epochs as a file, you can do it with mne.Epochs.save(). To conform to MNE naming conventions, the epochs file names should end with ‘-epo.fif’.

epochs_fname = op.join(data_path, 'MEG', 'sample', 'sample-epo.fif')
epochs.save(epochs_fname)

Later on you can read the epochs with mne.read_epochs(). For reading EEGLAB epochs files see mne.read_epochs_eeglab(). We can also use preload=False to save memory, loading the epochs from disk on demand.

epochs = mne.read_epochs(epochs_fname, preload=False)

If you wish to look at the average across trial types, then you may do so, creating an Evoked object in the process. Instances of Evoked are usually created by calling mne.Epochs.average(). For creating Evoked from other data structures see mne.EvokedArray and Creating MNE’s data structures from scratch.

ev_left = epochs['Auditory/Left'].average()
ev_right = epochs['Auditory/Right'].average()

f, axs = plt.subplots(3, 2, figsize=(10, 5))
_ = f.suptitle('Left / Right auditory', fontsize=20)
_ = ev_left.plot(axes=axs[:, 0], show=False)
_ = ev_right.plot(axes=axs[:, 1], show=False)
plt.tight_layout()
../_images/sphx_glr_plot_object_epochs_002.png

To export and manipulate Epochs using Pandas see Export epochs to Pandas DataFrame.

Total running time of the script: ( 0 minutes 9.589 seconds)

Gallery generated by Sphinx-Gallery