Creating EEG Objects

Epoch Creation

from simpl_eeg import eeg_objects

Module Overview

The eeg_objects module contains helper classes for storing and manipulating relevant information regarding epochs to pass to other package functions. It contains two classes. Typically you will only you use the eeg_objects.Epochs directly, which by default contains a eeg_objects.EEG_File object in the eeg_file attribute. Below are the docstrings for the two classes:

# Class for reading and importing EEG files
help(eeg_objects.EEG_File)
Help on class EEG_File in module simpl_eeg.eeg_objects:

class EEG_File(builtins.object)
 |  EEG_File(folder_path, file_name='auto', events_file='auto', montage='auto')
 |  
 |  A class to import and store relevant eeg files
 |  
 |  Attributes:
 |      folder_path: str
 |          path to experiment folder.
 |      experiment: str
 |          the name of the folder containing experiment files.
 |      mat: list of ints
 |          a list of integers representing impact times.
 |      raw: mne.io.eeglab.eeglab.RawEEGLAB
 |          raw experiment data in FIF format.
 |  
 |  Methods defined here:
 |  
 |  __init__(self, folder_path, file_name='auto', events_file='auto', montage='auto')
 |      Imports and stores EEG data files. Can be used to attach events data from
 |      an external file if none exists in the primary data. Can be used to load
 |      a pre-set electrode layout montage.
 |      
 |      Parameters:
 |          folder_path: str
 |              The folder path containing the experiment data.
 |          file_name: str (optional)
 |              The file name for the primary data file to read in. Should be provided
 |              as the file name only, with folder_path used to specify a directory.
 |              If 'auto' is provided then the first alphabetical file name with one
 |              of the supported file types within the folder_path directory will
 |              be loaded. The supported and tested filetypes are ".set", ".vhdr"
 |              and ".edf". Support for ".gdf" and ".cnt" exists but montage's have
 |              not been successfully loaded in test files. ".bdf', ".nxe", and ".EEG"
 |              can be imported but events cannot be read.
 |              Defaults to 'auto'.
 |          events_file: str (optional)
 |              The file name for the event file to read in. The supported filetypes
 |              are ".mat" and ".vmrk". Will only be used if events do not already
 |              exist in the primary data file. If 'auto' is provided then the first
 |              alphabetical file in the folder_path direcotry with a supported file
 |              type will be loaded. If an events file is flagged for containing
 |              over 5,000 events it's assumed a non-events file was loaded and it
 |              will be not be loaded, with the second file in alphabetical order
 |              being loaded instead.
 |              None can be passed if you do not want to load an events file.
 |              Defalts to 'auto'.
 |          montage: str (optional)
 |              The pre-set montage to load. If a montage already exists in the data
 |              then providing a montage will overwrite it in the generated data 
 |              object. If 'auto' is provided and a pre-existing montage exists
 |              in the data it will be used but if there isn't then the function 
 |              will try to load an "easycap-M1" montage. A complete list of available
 |              montages can be found here:
 |              https://mne.tools/dev/generated/mne.channels.make_standard_montage.html
 |              None can be passed if you do not want to load a montage.
 |              Defaults to 'auto'.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
# Class for storing, generating, and adjusting epoch objects
help(eeg_objects.Epochs)
Help on class Epochs in module simpl_eeg.eeg_objects:

class Epochs(builtins.object)
 |  Epochs(folder_path, tmin=-0.3, tmax=0.7, start_second=None, file_name='auto', events_file='auto', montage='auto', **kwargs)
 |  
 |  A class to represent epochs and underlying data
 |  
 |  Attributes:
 |      eeg_file: EEG_File
 |          eeg file data
 |      all_epochs: mne.Epochs
 |          the generated epoch data
 |      epoch: mne.Epochs
 |          the selected epoch of interest
 |  
 |  Methods:
 |      generate_epochs(duration, start_second):
 |          Calculates epochs based on a duration and start second.
 |      get_epoch(epoch_num):
 |          Set and return the epoch of interest.
 |      skip_n_steps(num_steps):
 |          Returns a subset of the epoch by skipping records in increments of num_steps.
 |  
 |  Methods defined here:
 |  
 |  __init__(self, folder_path, tmin=-0.3, tmax=0.7, start_second=None, file_name='auto', events_file='auto', montage='auto', **kwargs)
 |      Generates epochs and stores related information
 |      
 |      Parameters:
 |          folder_path: str
 |              The folder path containing the experiment data.
 |          tmin: float
 |              Number of seconds before the event time to include in epoch.
 |          tmax: float
 |              Number of seconds after the event time to include in epoch.
 |          start_second: int | None
 |              Second of the event time,
 |              or None if autodetected event time should be used
 |          file_name: str (optional)
 |              The file name for the primary data file to read in. Should be provided
 |              as the file name only, with folder_path used to specify a directory.
 |              If 'auto' is provided then the first alphabetical file name with one
 |              of the supported file types within the folder_path directory will
 |              be loaded. The supported and tested filetypes are ".set", ".vhdr"
 |              and ".edf". Support for ".gdf" and ".cnt" exists but montage's have
 |              not been successfully loaded in test files. ".bdf', ".nxe", and ".EEG"
 |              can be imported but events cannot be read.
 |              Defaults to 'auto'.
 |          events_file: str (optional)
 |              The file name for the event file to read in. The supported filetypes
 |              are ".mat" and ".vmrk". Will only be used if events do not already
 |              exist in the primary data file. If 'auto' is provided then the first
 |              alphabetical file in the folder_path direcotry with a supported file
 |              type will be loaded. If an events file is flagged for containing
 |              over 5,000 events it's assumed a non-events file was loaded and it
 |              will be not be loaded, with the second file in alphabetical order
 |              being loaded instead.
 |              None can be passed if you do not want to load an events file.
 |              Defalts to 'auto'.
 |          montage: str (optional)
 |              The pre-set montage to load. If a montage already exists in the data
 |              then providing a montage will overwrite it in the generated data 
 |              object. If 'auto' is provided and a pre-existing montage exists
 |              in the data it will be used but if there isn't then the function 
 |              will try to load an "easycap-M1" montage. A complete list of available
 |              montages can be found here:
 |              https://mne.tools/dev/generated/mne.channels.make_standard_montage.html
 |              None can be passed if you do not want to load a montage.
 |              Defaults to 'auto'.
 |          **kwargs: dict (optional)
 |              Additional parameters to pass to the mne.Epochs() constructor.
 |      
 |              Full list of options available at
 |              https://mne.tools/stable/generated/mne.Epochs.html
 |  
 |  average_n_steps(self, num_steps)
 |      Return new epoch containing every nth frame for the selected epoch
 |      Averages steps bewteen frames
 |      
 |      Parameters:
 |          num_steps: int
 |              The number of time steps to average
 |      
 |      Returns:
 |          mne.Evoked:
 |              The reduced size epoch in evoked format
 |  
 |  generate_epochs(self, tmin, tmax, start_second, **kwargs)
 |      Generates an epoch object based on the given input
 |      
 |      Parameters:
 |          tmin: float
 |              Number of seconds before the event time to include in epoch
 |          tmax: float
 |              Number of seconds after the event time to include in epoch
 |          start_second: int
 |              Second of the event time,
 |              or None if autodetected event time should be used
 |          **kwargs: dict (optional)
 |              Additional parameters to pass to the mne.Epochs() constructor
 |      
 |              Full list of options available at
 |              https://mne.tools/stable/generated/mne.Epochs.html
 |      
 |      Returns:
 |          mne.Epochs:
 |              The generated epoch(s)
 |  
 |  get_epoch(self, epoch_num)
 |      Get the nth epoch from the genertated epochs
 |      
 |      Parameters:
 |          epoch_num: int
 |              The epoch to select
 |      Returns:
 |          mne.Epoch:
 |              The epoch of interest
 |  
 |  skip_n_steps(self, num_steps, use_single=True)
 |      Return new epoch containing every nth frame
 |      Skips steps between frames
 |      
 |      Parameters:
 |          num_steps: int
 |              The number of time steps to skip
 |          use_single: bool (optional)
 |              Whether to apply the skipping to all epochs or the
 |              current selected epoch only
 |      
 |      Returns:
 |          mne.Epochs:
 |              The reduced size epoch
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)

Define parameters

The only required parameter to create an epoch object is the folder_path for the experiment of interest, however additional parameters may be used to customize your epoch object.

  • file_name

    • If you specify a file_name, and the file exists in the folder_path directory, then it will be used as the main data file for the epoch.

    • If you do not specify a file_name then the alphabetical first file with a supported main file type in folder_path will be automatically loaded.

  • events_file

    • If you specify an events_file, and the file exists in the folder_path directory, then it will be used as the events data file for the epoch.

    • If you do not specify an events_file then the alphabetical first file with a supported events file type in folder_path will be automatically loaded.

    • If you try to load an events_file (automatically or manually) with over 5,000 events or if the final column in the loaded dictionary does not contain a numerical value in its first index (both forms of error catching) then the file will be rejected and will not be loaded.

    • If you want to force no events data to be loaded you can pass and events_file of None.

  • montage

    • If you specify a montage, it will load a standard montage with the specified name into the epoch data.

    • If montage data already exists in the main data file and a montage is provided the original data overwritten in the epoch object.

    • If you do not specify a montage and montage data already exists in the main data then it will be used instead.

    • If you do not specify a montage and montage data does not exist in the main data then one attempt will be made to load a “easycap-M1” montage. If this fails then no montage information will be loaded.

    • If you want to force no montage to be loaded data to be loaded you can pass and events_file of None.

  • start_second

    • If you specify a start_second, a single epoch will be generated with an impact event at the specified second.

    • If you do not specify a start_second, epochs will be automatically generated using the impact times found in the impact locations.mat file in the selected experiment_folder.

  • tmin

    • specifies the number of seconds before the impact to use,

  • tmax

    • specifies the number of seconds after the impact.

# path to the experiment folder
folder_path = "../../data/109"

# the name of the main data file to load (optional)
file_name = "fixica.set"

# the name of the events file to load (optional)
events_file = "impact locations.mat"

# the montage type to load (optional)
montage = None

# number of seconds before the impact, should be a negative number for before impact (optional)
tmin = -1

# number of seconds after the impact (optional)
tmax = 1

# if creating a custom epoch, select a starting second (optional)
start_second = None

Create epoched data

The following data formats are currently supported. Note that due to limited availability of test files not all formats have been fully tested (see Notes).

Main File

Secondary File

Events File

Notes

EEGLAB

.set

.fdt

.mat

BrainVision

.vhdr

.eeg

.vmrk

European data format

.edf

N/A

N/A

BioSemi data format

.bdf

N/A

N/A

Montage has not be successfully loaded with test files.

General data format

.gdf

N/A

N/A

Events have not be successfully loaded with test files.

Neuroscan CNT

.cnt

N/A

N/A

Montage has not be successfully loaded with test files.

eXimia

.nxe

N/A

N/A

Events have not be successfully loaded with test files.

Nihon Kohden EEG data

.eeg

.pnt AND .21e

.log

Montage has not be successfully loaded with test files.

  • A main file represents the lead file used to load in your EEG data. This is the file that may be passed as your file_name.

  • A secondary file contains some secondary information for some data types. They will be automatically loaded to when the main file is loaded.

  • A events file contains a list of the annotations associated with events in your EEG data. This is the file that may be passed as your events_file.

  • A montage must exist in your epoch in order to visualize it. This contains information about your node locations in 3D space. A complete list of usable montages is available here: https://mne.tools/dev/generated/mne.channels.make_standard_montage.html.

You can create epoched data using the Epochs class.

epochs = eeg_objects.Epochs(
    folder_path = folder_path,
    file_name = file_name,
    events_file = events_file,
    montage = montage,
    tmin = tmin,
    tmax = tmax,
    start_second = start_second
)
Reading /Users/mpin/Documents/MDS/capstone/simpl_eeg_capstone/data/109/fixica.fdt
/Users/mpin/Documents/MDS/capstone/simpl_eeg_capstone/simpl_eeg/eeg_objects.py:199: RuntimeWarning: Data file name in EEG.data (109 whole fixed ica.fdt) is incorrect, the file name must have changed on disk, using the correct file name (fixica.fdt).
  raw = mne.io.read_raw_eeglab(data_path)
loaded raw from ../../data/109/fixica.set
Not setting metadata
Not setting metadata
33 matching events found
Setting baseline interval to [-1.0, 0.0] sec
Applying baseline correction (mode: mean)
0 projection items activated
Loading data for 33 events and 4097 original time points ...
0 bad epochs dropped

The generated epoch data is found within the all_epochs attribute. Here we are generating epochs with automatically detected impact times, so we can see that there are multiple events.

epochs.all_epochs
Number of events 33
Events 1027 seconds: 1
1138 seconds: 1
1253 seconds: 1
1370 seconds: 1
1585 seconds: 1
1697 seconds: 1
1812 seconds: 1
1935 seconds: 1
2055 seconds: 1
2219 seconds: 1
2363 seconds: 1
2472 seconds: 1
2594 seconds: 1
2713 seconds: 1
2898 seconds: 1
3033 seconds: 1
3150 seconds: 1
3269 seconds: 1
3389 seconds: 1
3518 seconds: 1
3628 seconds: 1
3774 seconds: 1
3945 seconds: 1
4061 seconds: 1
4180 seconds: 1
4319 seconds: 1
4463 seconds: 1
4662 seconds: 1
4785 seconds: 1
4906 seconds: 1
5029 seconds: 1
735 seconds: 1
892 seconds: 1
Time range -1.000 – 1.000 sec
Baseline -1.000 – 0.000 sec

If instead we create epochs with a custom start second, we will only create a single epoch with an impact the given start_second.

start_second = 15  # record event at second 15
custom_epoch = eeg_objects.Epochs(folder_path, tmin, tmax, start_second) 

custom_epoch.all_epochs
Reading /Users/mpin/Documents/MDS/capstone/simpl_eeg_capstone/data/109/fixica.fdt
loaded raw from ../../data/109/fixica.set
Not setting metadata
Not setting metadata
1 matching events found
Setting baseline interval to [-1.0, 0.0] sec
Applying baseline correction (mode: mean)
0 projection items activated
Loading data for 1 events and 4097 original time points ...
0 bad epochs dropped
/Users/mpin/Documents/MDS/capstone/simpl_eeg_capstone/simpl_eeg/eeg_objects.py:199: RuntimeWarning: Data file name in EEG.data (109 whole fixed ica.fdt) is incorrect, the file name must have changed on disk, using the correct file name (fixica.fdt).
  raw = mne.io.read_raw_eeglab(data_path)
Number of events 1
Events 15 seconds: 1
Time range -1.000 – 1.000 sec
Baseline -1.000 – 0.000 sec

Get information about epochs

In addition to the epochs contained in the all_epochs attribute, the Epoch object also contains information about the file used and has a selected epoch for quick access.

eeg_file = epochs.eeg_file
print(eeg_file.folder_path)  # experiment folder path
print(eeg_file.experiment)  # experiment number
print(eeg_file.raw)  # raw data
print(eeg_file.file_source) # primary data file the EEG data was loaded from
print(eeg_file.events_source) # source file of events
print(eeg_file.montage_source) # source of the montage (may be pre-set montage name)
print(eeg_file.events)  # impact times
../../data/109
109
<RawEEGLAB | fixica.fdt, 19 x 11175225 (5456.7 s), ~30 kB, data not loaded>
fixica.set
impact locations.mat
primary data file
[[1506127, 0, 735], [1828393, 0, 892], [2103572, 0, 1027], [2332113, 0, 1138], [2566359, 0, 1253], [2806427, 0, 1370], [3246204, 0, 1585], [3475576, 0, 1697], [3712770, 0, 1812], [3963481, 0, 1935], [4208934, 0, 2055], [4544740, 0, 2219], [4840659, 0, 2363], [5064290, 0, 2472], [5314417, 0, 2594], [5557193, 0, 2713], [5936062, 0, 2898], [6213199, 0, 3033], [6451715, 0, 3150], [6695044, 0, 3269], [6941686, 0, 3389], [7206205, 0, 3518], [7431075, 0, 3628], [7731054, 0, 3774], [8080362, 0, 3945], [8317857, 0, 4061], [8562682, 0, 4180], [8847325, 0, 4319], [9142217, 0, 4463], [9549010, 0, 4662], [9801198, 0, 4785], [10049013, 0, 4906], [10301077, 0, 5029]]

Select specific epoch

If you have a specific epoch of interest you can specify it with the get_epoch method. You can retrieve it later by accessing the epoch attribute.

nth_epoch = 5  # the epoch of interest to select, the 6th impact
single_epoch = epochs.get_epoch(nth_epoch)
single_epoch
Number of events 1
Events 1370 seconds: 1
Time range -1.000 – 1.000 sec
Baseline -1.000 – 0.000 sec
epochs.epoch
Number of events 1
Events 1370 seconds: 1
Time range -1.000 – 1.000 sec
Baseline -1.000 – 0.000 sec

Getting an evoked object

You can also use the get_epoch method to retrieve an evoked object, which represents an averaging of each event in your epoch. Note that evoked data is its own type of object and is not guaranteed to work with every function in this package.

evoked = epochs.get_epoch("evoked")
type(evoked)
mne.evoked.EvokedArray
evoked.info
Measurement date Unknown
Experimenter Unknown
Participant Unknown
Digitized points 19 points
Good channels 0 magnetometer, 0 gradiometer, and 19 EEG channels
Bad channels
EOG channels Not available
ECG channels Not available
Sampling frequency 2048.00 Hz
Highpass 0.00 Hz
Lowpass 1024.00 Hz

Decimate the epoch (optional)

To reduce the size of the selected epoch you can choose to skip a selected number of time steps by calling the skip_n_steps method. If use_single=True (the default), it will only be run on the current selected epoch from the previous step, contained in the epoch attribute. Otherwise it will run on all the epochs contained within the all_epochs attribute.

Skipping steps will greatly reduce animation times for the other functions in the package. The greater the number of steps skipped, the fewer the frames to animate. In the example below we are reducing the selected epoch from 4097 time steps to 81 time steps.

single_epoch.get_data().shape
(1, 19, 4097)
num_steps = 50
smaller_epoch = epochs.skip_n_steps(num_steps)
smaller_epoch.get_data().shape
/Users/mpin/Documents/MDS/capstone/simpl_eeg_capstone/simpl_eeg/eeg_objects.py:823: RuntimeWarning: The measurement information indicates a low-pass frequency of 1024 Hz. The decim=50 parameter will result in a sampling frequency of 40.96 Hz, which can cause aliasing artifacts.
  return epochs.copy().decimate(num_steps)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-14-2117361c8207> in <module>
      1 num_steps = 50
      2 smaller_epoch = epochs.skip_n_steps(num_steps)
----> 3 smaller_epoch.get_data().shape

AttributeError: 'EvokedArray' object has no attribute 'get_data'

Average the epoch (optional)

To reduce the size of the selected epoch you can choose to average a selected number of time steps by calling the average_n_steps method. It will be run on the current selected epoch from the previous step, contained in the epoch attribute.

Averaging works the same way as decimating above, but instead of simply ignoring records between steps it takes an average.

num_steps = 50
average_epoch = epochs.average_n_steps(num_steps)
average_epoch.get_data()

MNE functions

Now that you have access epoched data, you can use the simpl_eeg package functions as well as any MNE functions which act on mne.epoch objects. Below are some useful examples for the MNE objects contained within the object we created.

Raw data

https://mne.tools/stable/generated/mne.io.Raw.html

raw = epochs.eeg_file.raw
raw.info
raw.plot_psd();

Epoch data

# first 3 epochs
epochs.all_epochs.plot(n_epochs=3);
# specific epoch
epochs.epoch.plot();
# specific epoch with steps skipped
epochs.skip_n_steps(100).plot();