Epochs
data structure: epoched data¶from __future__ import print_function
import mne
import os.path as op
import numpy as np
from matplotlib import pyplot as plt
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.
Epochs
objects can be created in three ways:Raw
object, along with event timesEpochs
object that has been saved as a
.fif fileEpochsArray
. See
Creating MNE-Python’s data structures from scratchdata_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:
Opening raw data file /home/ubuntu/mne_data/MNE-sample-data/MEG/sample/sample_audvis_raw.fif...
Read a total of 3 projection items:
PCA-v1 (1 x 102) idle
PCA-v2 (1 x 102) idle
PCA-v3 (1 x 102) idle
Range : 25800 ... 192599 = 42.956 ... 320.670 secs
Ready.
Current compensation grade : 0
320 events found
Events id: [ 1 2 3 4 5 32]
('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:
145 matching events found
Created an SSP operator (subspace dimension = 3)
3 projection items activated
Loading data for 145 events and 662 original time points ...
0 bad epochs dropped
<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()
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]))
Out:
Dropped 1 epoch
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on MAG : [u'MEG 1711']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on MAG : [u'MEG 1711']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
Rejecting epoch based on EOG : [u'EOG 061']
23 bad epochs dropped
[['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)
Out:
Reading /home/ubuntu/mne_data/MNE-sample-data/MEG/sample/sample-epo.fif ...
Read a total of 3 projection items:
PCA-v1 (1 x 102) active
PCA-v2 (1 x 102) active
PCA-v3 (1 x 102) active
Found the data of interest:
t = -99.90 ... 1000.64 ms (None)
0 CTF compensation matrices available
121 matching events found
Created an SSP operator (subspace dimension = 3)
121 matching events found
Created an SSP operator (subspace dimension = 3)
3 projection items activated
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-Python’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()
To export and manipulate Epochs using Pandas see Export epochs to Pandas DataFrame.
Total running time of the script: ( 0 minutes 9.408 seconds)