The BrainVision recorder is a widely used software tool for recording electroencephalography (EEG) data. It provides a user-friendly interface for setting up and acquiring EEG signals from multiple channels.
After recording EEG data using the BrainVision recorder, three files are generated for each recording:
.vhdr (BrainVision Header): This file contains the header information, including metadata and channel configuration, in a plain text format.
.vmrk (BrainVision Marker): This file contains the marker information, such as event triggers and their corresponding timestamps, also in a plain text format.
.eeg (BrainVision Data): This file contains the actual raw EEG data recorded from the channels. It is typically stored in a binary format to optimize file size and access speed.
There are several ways to read and process BrainVision files in Python. Here are a few commonly used options:
MNE-Python: The MNE library provides a comprehensive set of functions for EEG data analysis, including reading BrainVision files. It offers a high-level interface for loading and manipulating EEG data, making it suitable for various preprocessing and analysis tasks.
Neo: Neo is a Python library for handling neurophysiological data, including EEG. It supports reading various file formats, including BrainVision, and provides a unified data structure for easy data access and analysis.
EEGLAB Toolbox: If you prefer using MATLAB, the EEGLAB toolbox offers functionality to read and process BrainVision files. It provides a graphical user interface (GUI) and scripting capabilities for EEG data analysis.
These are just a few examples, and there might be other libraries and tools available depending on your specific requirements and preferences. In the following sections, we will focus on using MNE-Python to load and work with BrainVision EEG data.
Now, let's proceed with loading the EEG data using MNE-Python.
In the upcoming code cell, I will demonstrate how to load the raw EEG data using the MNE library. We will read the dataset files from the 'data' folder, which is relative to the recording session of one subject.
The dataset files for this example are as follows:
Make sure that you have these files in the 'data' folder before executing the code cell.
We will use MNE's read_raw_brainvision()
function to read the EEG data, which automatically handles the loading of the header and marker files associated with the data file. Once the data is loaded, we can perform various preprocessing and analysis tasks using the MNE library.
Now, let's proceed to the code cell and load the raw EEG data using MNE.
In this code cell, we first import the necessary module, mne
, to work with EEG data. Then, we define the file paths for the EEG data file (Subj01.eeg
) and the header file (Subj01.vhdr
). Make sure that the paths are correct and the files are located in the 'data' folder relative to the notebook.
Next, we use the read_raw_brainvision()
function from MNE to load the raw EEG data. We pass the header_fname
parameter to specify the path to the header file. The preload=True
argument loads the data into memory for faster access.
Finally, we print the loaded data information using raw.info
to verify that the data has been successfully loaded.
import mne
import warnings
# Define the file paths
data_folder = 'data/'
eeg_file = data_folder + 'Subj01.eeg'
header_file = data_folder + 'Subj01.vhdr'
# Load the raw EEG data using MNE
raw = mne.io.read_raw_brainvision(vhdr_fname=header_file,
eog=('LHEOG','vEOGup','vEOGdown','RHEOG'),
misc=['RM','audio'],
preload=True)
# Print the loaded data information
print(raw.info)
Extracting parameters from data/Subj01.vhdr... Setting channel info structure... Reading 0 ... 4471799 = 0.000 ... 4471.799 secs... <Info | 8 non-empty values bads: [] ch_names: RM, Fz, F3, F7, LHEOG, FC5, FC1, C3, T7, vEOGup, CP5, CP1, Pz, ... chs: 3 misc, 57 EEG, 4 EOG custom_ref_applied: False dig: 60 items (3 Cardinal, 57 EEG) highpass: 0.0 Hz lowpass: 500.0 Hz meas_date: 2023-03-13 16:22:19 UTC nchan: 64 projs: [] sfreq: 1000.0 Hz >
In this code cell, we will create events based on the markers. The events will be used for epoching the EEG data.
I will use the mne.events_from_annotations()
function to directly load the marker file and extract the events. This function reads the marker file and returns an array of events, where each event consists of a sample number and an event code.
Now, let's proceed to the code cell and load the marker file, creating events in the process.
import numpy as np
# Define an event_id to extract only meaningful events
event_id = {
'Stimulus/S 50': 2,
}
# Extract marker information
events, event_id = mne.events_from_annotations(raw, event_id)
# Print the extracted events
# print(events)
# print(event_id)
Used Annotations descriptions: ['Stimulus/S 50']
In this code cell, we will define the parameters for epoching the EEG data. This includes specifying the time window around each event to extract as an epoch and setting the baseline correction period.
To perform the epoching, we will use the mne.Epochs
class. This class allows us to segment the continuous EEG data into epochs based on the defined parameters.
For baseline correction, we will set a period of 100ms before the event onset as the baseline interval. This will be used to correct the epochs and remove any baseline shifts or offsets.
Now, let's proceed to the code cell and define the epoch parameters.
# Define epoch parameters
tmin = -0.2 # Start time relative to the event onset
tmax = 0.8 # End time relative to the event onset
baseline = (-0.1, 0) # Baseline correction period, from the beginning to 0ms
# Create epochs based on the defined parameters
epochs = mne.Epochs(raw, events, event_id, tmin=tmin, tmax=tmax, baseline=baseline)
# Print the epoch information
print(epochs)
Not setting metadata 300 matching events found Applying baseline correction (mode: mean) 0 projection items activated <Epochs | 300 events (good & bad), -0.2 – 0.8 s, baseline -0.1 – 0 s, ~92 kB, data not loaded, 'Stimulus/S 50': 300>
In this code, epochs
refers to your MNE epochs object. The get_data()
method returns the EEG data as a numpy array. The resulting eeg_data
will be a three-dimensional array with dimensions (epochs, channels, timepoints).
# Convert epochs data to a three-dimensional array
eeg_data = epochs.get_data()
# Print the shape of the array
print(eeg_data.shape)
Using data from preloaded Raw for 300 events and 1001 original time points ... 0 bad epochs dropped (300, 64, 1001)
In this code cell, we will plot a specific epoch from the EEG data. The EEG data is stored in a three-dimensional array with dimensions (epochs, channels, timepoints). We will select a particular epoch and visualize it.
Now, let's proceed to the code cell and plot an epoch from the EEG data.
import matplotlib.pyplot as plt
# Select the epoch to plot
epoch_idx = 5
# C5, Oz
chs_idx = [40, 17]
# Get the epoch data from the three-dimensional array
epoch_data = eeg_data[epoch_idx, chs_idx, :]
# Plot the epoch
plt.figure(figsize=(10, 6))
plt.plot(epochs.times, epoch_data.T)
plt.xlabel('Time (s)')
plt.ylabel('Amplitude (V)')
plt.title(f'Epoch {epoch_idx + 1} from 2 EEG channels')
plt.show()