Working with Raw EEG and MEG data
Authors
import numpy as np
import mneRaw EEG and MEG data contains recordings from multiple sensors distributed across the scalp. EEG sensors are electrodes that directly pick up the electrical fields generated by neuronal activity. MEG channels come in two types: magnetometers and gradiometers. While magnetometers measure the absolute strength of the magnetic field, gradiometers measure the spatial gradient of the magnetic field between two nearby points. For each MEG sensor location, there are three channels: one magnetometer and two gradiometers. In this notebook, you are going to learn how to load and explore raw EEG and MEG data using MNE-Python.
Setup
Download Sample Data
Execute the cell below to download a sample dataset from MNE and store it in the variable raw.
data_path = mne.datasets.sample.data_path()
raw = mne.io.read_raw_fif(data_path/"MEG"/"sample"/"sample_audvis_raw.fif")
rawOpening raw data file /home/atleeri/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.| General | ||
|---|---|---|
| Filename(s) | sample_audvis_raw.fif | |
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:04:38 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 166,800 | |
| Channels | ||
| Magnetometers | ||
| Gradiometers | and | |
| EEG | and | |
| EOG | ||
| Stimulus | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
| Projections |
PCA-v1 (off)
PCA-v2 (off) PCA-v3 (off) |
|
Section 1: Inspecting Raw Data
Background
In MNE-Python, raw EEG and MEG data is stored in an instance of the Raw class. A Raw object is a container that stores the sensor values, the time points at which those values were recorded, as well as an Info object that contains important metadata such as the names and locations of the sensors, the sampling rate at which the data were recorded and the filters that have been applied to the data. The Raw class also provides a .plot() method that allows you to explore the data in an interactive graphical interface.
Exercises
In this section, you are going to learn how to work with Raw objects in MNE-Python. You are going to visualize the raw data, read different kinds of metadata from the Raw object’s .info attribute and export the raw sensor recordings as a numpy array. Here are the code examples required to solve the exercises:
| Code | Description |
|---|---|
mne.datasets.sample.data_path() |
Download the MNE sample data and return the path where it is stored |
raw = mne.io.read_raw_fif("recording.fif") |
Read raw data from a FIF file and store it in the variable raw |
raw.info |
Get the .info of the raw object |
raw.info["ch_names"] |
Get the list of channel names from raw.info |
raw.info["bads"] |
Get the list of bad channels from raw.info |
raw.info["sfreq"] |
Get the sampling frequency from raw.info |
raw.plot() |
Create an interactive plot of the raw data |
raw.times |
Get the array of .times for all samples in raw |
raw.get_data() |
Get the data array from raw |
Exercise: Use the .plot() method to visualize the raw data. Use the sidebar to scroll through channels and the left and right arrow keys to move through time. What differences can you spot between MEG and EEG channels?
Solution
raw.plot();Exercise: Get the .info of the raw object.
Solution
raw.info| General | ||
|---|---|---|
| MNE object type | Info | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Sampling frequency | 600.61 Hz | |
| Channels | ||
| Magnetometers | ||
| Gradiometers | and | |
| EEG | and | |
| EOG | ||
| Stimulus | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
| Projections |
PCA-v1 (off)
PCA-v2 (off) PCA-v3 (off) |
|
Example: Get the sampling frequency ("sfreq") from raw.info.
raw.info["sfreq"]600.614990234375Exercise: Get the list of channel names ("ch_names") from raw.info.
Solution
raw.info["ch_names"]['MEG 0113',
'MEG 0112',
'MEG 0111',
'MEG 0122',
'MEG 0123',
'MEG 0121',
'MEG 0132',
'MEG 0133',
'MEG 0131',
'MEG 0143',
'MEG 0142',
'MEG 0141',
'MEG 0213',
'MEG 0212',
'MEG 0211',
'MEG 0222',
'MEG 0223',
'MEG 0221',
'MEG 0232',
'MEG 0233',
'MEG 0231',
'MEG 0243',
'MEG 0242',
'MEG 0241',
'MEG 0313',
'MEG 0312',
'MEG 0311',
'MEG 0322',
'MEG 0323',
'MEG 0321',
'MEG 0333',
'MEG 0332',
'MEG 0331',
'MEG 0343',
'MEG 0342',
'MEG 0341',
'MEG 0413',
'MEG 0412',
'MEG 0411',
'MEG 0422',
'MEG 0423',
'MEG 0421',
'MEG 0432',
'MEG 0433',
'MEG 0431',
'MEG 0443',
'MEG 0442',
'MEG 0441',
'MEG 0513',
'MEG 0512',
'MEG 0511',
'MEG 0523',
'MEG 0522',
'MEG 0521',
'MEG 0532',
'MEG 0533',
'MEG 0531',
'MEG 0542',
'MEG 0543',
'MEG 0541',
'MEG 0613',
'MEG 0612',
'MEG 0611',
'MEG 0622',
'MEG 0623',
'MEG 0621',
'MEG 0633',
'MEG 0632',
'MEG 0631',
'MEG 0642',
'MEG 0643',
'MEG 0641',
'MEG 0713',
'MEG 0712',
'MEG 0711',
'MEG 0723',
'MEG 0722',
'MEG 0721',
'MEG 0733',
'MEG 0732',
'MEG 0731',
'MEG 0743',
'MEG 0742',
'MEG 0741',
'MEG 0813',
'MEG 0812',
'MEG 0811',
'MEG 0822',
'MEG 0823',
'MEG 0821',
'MEG 0913',
'MEG 0912',
'MEG 0911',
'MEG 0923',
'MEG 0922',
'MEG 0921',
'MEG 0932',
'MEG 0933',
'MEG 0931',
'MEG 0942',
'MEG 0943',
'MEG 0941',
'MEG 1013',
'MEG 1012',
'MEG 1011',
'MEG 1023',
'MEG 1022',
'MEG 1021',
'MEG 1032',
'MEG 1033',
'MEG 1031',
'MEG 1043',
'MEG 1042',
'MEG 1041',
'MEG 1112',
'MEG 1113',
'MEG 1111',
'MEG 1123',
'MEG 1122',
'MEG 1121',
'MEG 1133',
'MEG 1132',
'MEG 1131',
'MEG 1142',
'MEG 1143',
'MEG 1141',
'MEG 1213',
'MEG 1212',
'MEG 1211',
'MEG 1223',
'MEG 1222',
'MEG 1221',
'MEG 1232',
'MEG 1233',
'MEG 1231',
'MEG 1243',
'MEG 1242',
'MEG 1241',
'MEG 1312',
'MEG 1313',
'MEG 1311',
'MEG 1323',
'MEG 1322',
'MEG 1321',
'MEG 1333',
'MEG 1332',
'MEG 1331',
'MEG 1342',
'MEG 1343',
'MEG 1341',
'MEG 1412',
'MEG 1413',
'MEG 1411',
'MEG 1423',
'MEG 1422',
'MEG 1421',
'MEG 1433',
'MEG 1432',
'MEG 1431',
'MEG 1442',
'MEG 1443',
'MEG 1441',
'MEG 1512',
'MEG 1513',
'MEG 1511',
'MEG 1522',
'MEG 1523',
'MEG 1521',
'MEG 1533',
'MEG 1532',
'MEG 1531',
'MEG 1543',
'MEG 1542',
'MEG 1541',
'MEG 1613',
'MEG 1612',
'MEG 1611',
'MEG 1622',
'MEG 1623',
'MEG 1621',
'MEG 1632',
'MEG 1633',
'MEG 1631',
'MEG 1643',
'MEG 1642',
'MEG 1641',
'MEG 1713',
'MEG 1712',
'MEG 1711',
'MEG 1722',
'MEG 1723',
'MEG 1721',
'MEG 1732',
'MEG 1733',
'MEG 1731',
'MEG 1743',
'MEG 1742',
'MEG 1741',
'MEG 1813',
'MEG 1812',
'MEG 1811',
'MEG 1822',
'MEG 1823',
'MEG 1821',
'MEG 1832',
'MEG 1833',
'MEG 1831',
'MEG 1843',
'MEG 1842',
'MEG 1841',
'MEG 1912',
'MEG 1913',
'MEG 1911',
'MEG 1923',
'MEG 1922',
'MEG 1921',
'MEG 1932',
'MEG 1933',
'MEG 1931',
'MEG 1943',
'MEG 1942',
'MEG 1941',
'MEG 2013',
'MEG 2012',
'MEG 2011',
'MEG 2023',
'MEG 2022',
'MEG 2021',
'MEG 2032',
'MEG 2033',
'MEG 2031',
'MEG 2042',
'MEG 2043',
'MEG 2041',
'MEG 2113',
'MEG 2112',
'MEG 2111',
'MEG 2122',
'MEG 2123',
'MEG 2121',
'MEG 2133',
'MEG 2132',
'MEG 2131',
'MEG 2143',
'MEG 2142',
'MEG 2141',
'MEG 2212',
'MEG 2213',
'MEG 2211',
'MEG 2223',
'MEG 2222',
'MEG 2221',
'MEG 2233',
'MEG 2232',
'MEG 2231',
'MEG 2242',
'MEG 2243',
'MEG 2241',
'MEG 2312',
'MEG 2313',
'MEG 2311',
'MEG 2323',
'MEG 2322',
'MEG 2321',
'MEG 2332',
'MEG 2333',
'MEG 2331',
'MEG 2343',
'MEG 2342',
'MEG 2341',
'MEG 2412',
'MEG 2413',
'MEG 2411',
'MEG 2423',
'MEG 2422',
'MEG 2421',
'MEG 2433',
'MEG 2432',
'MEG 2431',
'MEG 2442',
'MEG 2443',
'MEG 2441',
'MEG 2512',
'MEG 2513',
'MEG 2511',
'MEG 2522',
'MEG 2523',
'MEG 2521',
'MEG 2533',
'MEG 2532',
'MEG 2531',
'MEG 2543',
'MEG 2542',
'MEG 2541',
'MEG 2612',
'MEG 2613',
'MEG 2611',
'MEG 2623',
'MEG 2622',
'MEG 2621',
'MEG 2633',
'MEG 2632',
'MEG 2631',
'MEG 2642',
'MEG 2643',
'MEG 2641',
'STI 001',
'STI 002',
'STI 003',
'STI 004',
'STI 005',
'STI 006',
'STI 014',
'STI 015',
'STI 016',
'EEG 001',
'EEG 002',
'EEG 003',
'EEG 004',
'EEG 005',
'EEG 006',
'EEG 007',
'EEG 008',
'EEG 009',
'EEG 010',
'EEG 011',
'EEG 012',
'EEG 013',
'EEG 014',
'EEG 015',
'EEG 016',
'EEG 017',
'EEG 018',
'EEG 019',
'EEG 020',
'EEG 021',
'EEG 022',
'EEG 023',
'EEG 024',
'EEG 025',
'EEG 026',
'EEG 027',
'EEG 028',
'EEG 029',
'EEG 030',
'EEG 031',
'EEG 032',
'EEG 033',
'EEG 034',
'EEG 035',
'EEG 036',
'EEG 037',
'EEG 038',
'EEG 039',
'EEG 040',
'EEG 041',
'EEG 042',
'EEG 043',
'EEG 044',
'EEG 045',
'EEG 046',
'EEG 047',
'EEG 048',
'EEG 049',
'EEG 050',
'EEG 051',
'EEG 052',
'EEG 053',
'EEG 054',
'EEG 055',
'EEG 056',
'EEG 057',
'EEG 058',
'EEG 059',
'EEG 060',
'EOG 061']Exercise: Get the list of bad channels ("bads") from raw.info.
Solution
raw.info["bads"]['MEG 2443', 'EEG 053']Exercise: Get the array of .times from the raw object. How many time points have been recorded in this data?
Solution
raw.timesarray([0.00000000e+00, 1.66496011e-03, 3.32992022e-03, ...,
2.77710351e+02, 2.77712016e+02, 2.77713681e+02], shape=(166800,))Exercise: Get the data array from raw. How many channels are there in total?
Solution
raw.get_data()array([[ 9.64355481e-12, 0.00000000e+00, 0.00000000e+00, ...,
-1.92871096e-12, 2.89306644e-12, 3.85742192e-12],
[-4.82177740e-12, -2.89306644e-12, -9.64355481e-13, ...,
-9.64355481e-13, -9.64355481e-13, -1.92871096e-12],
[ 1.01074222e-13, 6.31713890e-14, 7.58056668e-14, ...,
-4.80102556e-13, -6.06445334e-13, -5.93811056e-13],
...,
[ 3.88542173e-05, 4.07510373e-05, 4.09957883e-05, ...,
6.72453304e-05, 6.68782039e-05, 6.91421504e-05],
[ 6.58391126e-05, 6.80025648e-05, 6.81779798e-05, ...,
8.51932390e-05, 8.58948991e-05, 8.89938982e-05],
[ 2.85661012e-04, 2.83699953e-04, 2.80431520e-04, ...,
2.64089357e-04, 2.62781984e-04, 2.57552492e-04]],
shape=(376, 166800))Section 2: Selecting Channels and Data Segments
Background
MEG and EEG recordings can get very large. The sample dataset we are working with here contains 60 EEG and 306 MEG channels plus some additional auxiliary channels to record the stimuli and electrooculogram (EOG). However, often we want to focus our analysis on a subset of channels where we expect the neural phenomenon of interest. We may also want to select a specific time range, for example when stimuli were presented. In this section, you are going to learn how to pick channels and crop the data to a specific time range. When calling methods such as .pick() or .crop(), the Raw object is modified in-place, which means that the data stored in Raw is overwritten with the values returned by those methods. If we want to keep the original data, we can .copy() the Raw object first and then apply the modifications to the copy.
Exercises
In this section, you are going to learn to pick channels, either by type or name, from an MNE Raw object and crop the data to a specific time range. To keep the original data, we are going to copy the Raw object and modify the copy. Don’t worry though if you accidentally overwrite the original data! You can simply execute the cell that loads the sample data at the beginning of this notebook to reload the original data. Here are some useful code snippets for solving the exercises in this section:
| Code | Description |
|---|---|
raw.pick(["eeg"]) |
Select all "eeg" channels from raw |
raw.pick(["EEG 017", "EEG 018"]) |
Select the channels "EEG 017" and "EEG 018" from raw |
raw.crop(tmin=10, tmax=20) |
Crop the data recorded between 10 and 20 seconds |
raw2 = raw.copy() |
Create a copy of raw and store it in the variable raw2 |
raw.plot_sensors(ch_type="mag") |
Plot the sensor layout for all magnetometers |
raw.plot_sensors(ch_type="mag", show_names=True) |
Plot the sensor layout for all magnetometers with their names |
Example: Create a copy of raw called raw_eeg and select all "eeg", "stim" and "eog" channels.
raw_eeg = raw.copy()
raw_eeg.pick(["eeg", "stim", "eog"])| General | ||
|---|---|---|
| Filename(s) | sample_audvis_raw.fif | |
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:04:38 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 166,800 | |
| Channels | ||
| EEG | and | |
| EOG | ||
| Stimulus | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
Exercise: Create a copy of raw called raw_meg and select all "meg", "stim" and "eog" channels.
Solution
raw_meg = raw.copy()
raw_meg.pick(["meg", "stim", "eog"])| General | ||
|---|---|---|
| Filename(s) | sample_audvis_raw.fif | |
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:04:38 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 166,800 | |
| Channels | ||
| Magnetometers | ||
| Gradiometers | and | |
| EOG | ||
| Stimulus | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
| Projections |
PCA-v1 (off)
PCA-v2 (off) PCA-v3 (off) |
|
Exercise: Plot all magnetometer sensors.
Solution
raw.plot_sensors(ch_type="mag");Exercise: Plot all EEG sensors with their names.
Solution
raw.plot_sensors(ch_type="eeg", show_names=True);Example: Create a copy of raw called raw_eeg_left and select the channels stored in the list left.
left = ["EEG 017", "EEG 018", "EEG 025", "EEG 026"]
raw_eeg_left = raw.copy()
raw_eeg_left.pick(left)| General | ||
|---|---|---|
| Filename(s) | sample_audvis_raw.fif | |
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:04:38 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 166,800 | |
| Channels | ||
| EEG | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
Exercise: Create a copy of raw called raw_eeg_right and select the channels stored in the list right.
right = ["EEG 023", "EEG 024", "EEG 034", "EEG 035"]Solution
raw_eeg_right = raw.copy()
raw_eeg_right.pick(right)| General | ||
|---|---|---|
| Filename(s) | sample_audvis_raw.fif | |
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:04:38 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 166,800 | |
| Channels | ||
| EEG | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
Example: Create a copy of raw called raw_min1 and crop it to the data recorded within the first minute.
raw_min1 = raw.copy()
raw_min1.crop(tmin=0, tmax=60)| General | ||
|---|---|---|
| Filename(s) | sample_audvis_raw.fif | |
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:01:01 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 36,038 | |
| Channels | ||
| Magnetometers | ||
| Gradiometers | and | |
| EEG | and | |
| EOG | ||
| Stimulus | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
| Projections |
PCA-v1 (off)
PCA-v2 (off) PCA-v3 (off) |
|
Exercise: Create a copy of raw called raw_min2 and crop it to the data recorded within the second minute.
Solution
raw_min2 = raw.copy()
raw_min2.crop(tmin=60, tmax=120)| General | ||
|---|---|---|
| Filename(s) | sample_audvis_raw.fif | |
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:01:01 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 36,038 | |
| Channels | ||
| Magnetometers | ||
| Gradiometers | and | |
| EEG | and | |
| EOG | ||
| Stimulus | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
| Projections |
PCA-v1 (off)
PCA-v2 (off) PCA-v3 (off) |
|
Section 3: Manual Annotation of Raw EEG Data
Background
When working with EEG data, it is common to encounter segments that are contaminated by artifacts such as muscle movements, eye blinks, or electrode pops. MNE-Python allows you to mark these segments using annotations. Annotations are metadata that store the onset, duration, and a description for each marked segment. Any annotation whose description starts with "BAD_" is treated specially by MNE — these segments will be automatically excluded from further analysis steps like epoching. Annotations can be added interactively through the plotting GUI or programmatically in code. Once segments are annotated, you can extract or remove them using methods like .crop_by_annotations().
Exercises
In this section, you are going to learn how to inspect, create, and modify annotations on raw data. You will use the interactive GUI to manually mark bad segments and learn how to add annotations programmatically. Finally, there will be a demo that shows how to crop raw data to remove the annotations. Here are the code examples required to solve the exercises:
| Code | Description |
|---|---|
raw.annotations |
Get the annotations stored in raw |
raw.annotations[0] |
Get the first annotation |
raw.annotations.onset |
Get the onset for all annotations |
raw.annotations.description |
Get the description for all annotations |
raw.annotations.duration |
Get the duration for all annotations |
raw.annotations.append(onset=3, duration=0.5, description="BAD_") |
Add a new annotation to raw at 3 seconds with a duration of 0.5 seconds |
raw.crop_by_annotations() |
Extract the annotated segments from raw as a list of Raw objects |
mne.concatenate_raws([raw1, raw2]) |
Concatenate a list of Raw objects into one |
Run the cell below to create a copy of raw and select all "eeg" channels.
raw_eeg = raw.copy()
raw_eeg.pick("eeg")| General | ||
|---|---|---|
| Filename(s) | sample_audvis_raw.fif | |
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:04:38 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 166,800 | |
| Channels | ||
| EEG | and | |
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
Example: Print the annotations stored in raw_eeg.
raw_eeg.annotations<Annotations | 0 segments>Exercise: Use the .plot() method to open the MNE GUI. In the GUI, press a to enter annotation mode. Click the “Add new label” button to create a new label with the default name BAD_. Then left click and drag to annotate a segment. Annotate at least three data segments, then close the GUI.
Solution
raw_eeg.plot();Exercise: Print the annotations again. It should reflect the number of segments you manually annotated.
Solution
raw_eeg.annotations<Annotations | 3 segments: BAD_ (3)>Exercise: Print the first element in raw_eeg.annotations to see the exact onset and duration of the annotation.
Solution
raw_eeg.annotations[0]OrderedDict([('onset', np.float64(44.95597082905339)),
('duration', np.float64(1.0)),
('description', np.str_('BAD_')),
('orig_time',
datetime.datetime(2002, 12, 3, 19, 1, 10, 720100, tzinfo=datetime.timezone.utc)),
('extras', {})])Exercise: Print the .onset for all annotations.
Solution
raw_eeg.annotations.onsetarray([44.95597083, 49.95597083, 54.95597083])Exercise: Print the .description for all annotations.
Solution
raw_eeg.annotations.descriptionarray(['BAD_', 'BAD_', 'BAD_'], dtype='<U4')Example: Programmatically annotate a segment with the description "Test".
raw_eeg.annotations.append(onset=3, duration=0.5, description="Test")<Annotations | 4 segments: BAD_ (3), Test (1)>Exercise: Programmatically annotate a segment with a description of your choice.
Solution
raw_eeg.annotations.append(onset=6, duration=1.5, description="Test2")<Annotations | 5 segments: BAD_ (3), Test (1), Test2 (1)>Exercise: Use the .crop_by_annotations() method to extract the annotated segments.
Solution
raw_eeg.crop_by_annotations()[<Raw | sample_audvis_raw.fif, 60 x 301 (0.5 s), ~2.9 MiB, data not loaded>,
<Raw | sample_audvis_raw.fif, 60 x 902 (1.5 s), ~2.9 MiB, data not loaded>,
<Raw | sample_audvis_raw.fif, 60 x 602 (1.0 s), ~2.9 MiB, data not loaded>,
<Raw | sample_audvis_raw.fif, 60 x 1203 (2.0 s), ~2.9 MiB, data not loaded>,
<Raw | sample_audvis_raw.fif, 60 x 1803 (3.0 s), ~2.9 MiB, data not loaded>]Demo: Run the cell below to crop the raw data to exclude the segments annotated as "BAD_" and create a new Raw object called raw_clean. Usually, you would not do this explicitly. Instead, MNE will automatically remove "BAD_" segments when slicing the continuous raw data into epochs.
onsets = raw_eeg.annotations.onset[raw_eeg.annotations.description == "BAD_"]
durations = raw_eeg.annotations.duration[raw_eeg.annotations.description == "BAD_"]
edges = [raw_eeg.times[0]] + [t for o, d in zip(onsets, durations) for t in (o, o + d)] + [raw_eeg.times[-1]]
pairs = list(zip(edges[::2], edges[1::2]))
raw_clean = mne.concatenate_raws([raw_eeg.copy().crop(tmin=a, tmax=b) for a, b in pairs if b > a])
raw_clean| General | ||
|---|---|---|
| Filename(s) |
sample_audvis_raw.fif
sample_audvis_raw.fif sample_audvis_raw.fif sample_audvis_raw.fif |
|
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:04:32 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 163,198 | |
| Channels | ||
| EEG | and | |
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
Section 4: Loading Data from Different Device-Formats
Background
EEG and MEG data can be recorded using devices from different manufacturers, each of which stores data in its own file format. For example, Elekta/NEUROMAG systems use the FIF format, CTF systems store data in a directory with a .ds extension, and 4D Neuroimaging/BTI systems use their own binary format. On the EEG side, BrainVision stores data across a triplet of .vhdr, .vmrk, and .eeg files, while the European Data Format (EDF) uses a single .edf file. MNE-Python provides dedicated reader functions for each of these formats under mne.io, all of which return a Raw object with the same interface you have been using throughout this notebook. For a list of all supported file formats, check the MNE documentation.
Exercises
In this section, you are going to load raw data from different file formats. Each exercise provides a path to a sample dataset that will be downloaded automatically to your home directory. Feel free to remove these datasets at the end of the session to free up space on your hard drive. Here are the code examples required to solve the exercises:
| Code | Description |
|---|---|
mne.io.read_raw_ctf(raw_path) |
Read raw MEG data from the CTF format |
mne.io.read_raw_bti(raw_path) |
Read raw MEG data from the 4D Neuroimaging/BTI format |
mne.io.read_raw_brainvision(raw_path, preload=True) |
Read raw EEG data from the BrainVision format and preload the data into memory |
mne.io.read_raw_edf(raw_path, verbose=False) |
Read raw EEG data from the EDF format without verbose output |
Exercise: Read the raw MEG data stored in the CTF format from the raw_path defined below and plot it. This dataset contains somatosensory evoked responses to median nerve stimulation recorded with a CTF 275 MEG system.
data_path = mne.datasets.brainstorm.bst_raw.data_path()
raw_path = data_path / "MEG" / "bst_raw" / "subj001_somatosensory_20111109_01_AUX-f.ds"Solution
raw = mne.io.read_raw_ctf(raw_path)
raw.plot();ds directory : /home/atleeri/mne_data/MNE-brainstorm-data/bst_raw/MEG/bst_raw/subj001_somatosensory_20111109_01_AUX-f.ds
res4 data read.
hc data read.
Separate EEG position data file not present.
Quaternion matching (desired vs. transformed):
0.84 69.49 0.00 mm <-> 0.84 69.49 -0.00 mm (orig : -44.30 51.45 -252.43 mm) diff = 0.000 mm
-0.84 -69.49 0.00 mm <-> -0.84 -69.49 0.00 mm (orig : 46.28 -53.58 -243.47 mm) diff = 0.000 mm
86.41 0.00 0.00 mm <-> 86.41 0.00 0.00 mm (orig : 63.60 55.82 -230.26 mm) diff = 0.000 mm
Coordinate transformations established.
Reading digitizer points from ['/home/atleeri/mne_data/MNE-brainstorm-data/bst_raw/MEG/bst_raw/subj001_somatosensory_20111109_01_AUX-f.ds/subj00111092011.pos']...
Polhemus data for 3 HPI coils added
Device coordinate locations for 3 HPI coils added
Picked positions of 2 EEG channels from channel info
2 EEG locations added to Polhemus data.
Measurement info composed.
Finding samples for /home/atleeri/mne_data/MNE-brainstorm-data/bst_raw/MEG/bst_raw/subj001_somatosensory_20111109_01_AUX-f.ds/subj001_somatosensory_20111109_01_AUX-f.meg4:
System clock channel is available, checking which samples are valid.
240 x 1800 = 432000 samples from 302 chs
Current compensation grade : 3Exercise: Read the raw MEG data stored in the 4D Neuroimaging/BTI format from the raw_path defined below and plot it. This dataset contains phantom recordings from a 4D Neuroimaging/BTI MEG system, designed for validating source localization algorithms using a known current source.
data_path = mne.datasets.phantom_4dbti.data_path()
raw_path = data_path / "1" / "e,rfhp1.0Hz"Solution
raw = mne.io.read_raw_bti(raw_path)
raw.plot();Reading 4D PDF file /home/atleeri/mne_data/MNE-phantom-4DBTi/1/e,rfhp1.0Hz...
Creating Neuromag info structure ...
... Setting channel info structure.
... putting coil transforms in Neuromag coordinates
... Reading digitization points from /home/atleeri/mne_data/MNE-phantom-4DBTi/1/hs_file
Currently direct inclusion of 4D weight tables is not supported. For critical use cases please take into account the MNE command "mne_create_comp_data" to include weights as printed out by the 4D "print_table" routine.Exercise: Read the raw EEG data stored in the BrainVision format from the raw_path defined below with preload=True and plot it. This dataset contains 32-channel EEG recordings of a frequency-tagging experiment where participants observed checkerboard patterns inverting at 12 Hz or 15 Hz.
data_path = mne.datasets.ssvep.data_path()
raw_path = data_path / "sub-02" / "ses-01" / "eeg" / "sub-02_ses-01_task-ssvep_eeg.vhdr"Solution
raw = mne.io.read_raw_brainvision(raw_path, preload=True)
raw.plot();Extracting parameters from /home/atleeri/mne_data/ssvep-example-data/sub-02/ses-01/eeg/sub-02_ses-01_task-ssvep_eeg.vhdr...
Setting channel info structure...
Reading 0 ... 467579 = 0.000 ... 467.579 secs...Exercise: Read the raw EEG data stored in the EDF format from the raw_path defined below with preload=True and verbose=False and plot it. This dataset contains 64-channel EEG recordings of motor imagery tasks recorded with the BCI2000 system.
raw_path = mne.datasets.eegbci.load_data(subjects=1, runs=6)[0]Solution
raw = mne.io.read_raw_edf(raw_path, preload=True, verbose=False)
raw.plot();Optional: Delete the mne_data/ folder in your home directory to remove the downloaded sample data and free up space.
Section 5: DEMO: Creating a RawArray from Scratch
Even though MNE supports a wide variety of file formats, there may be situations where your data can’t be imported using the available functions. In this case, it is always possible to create a RawArray from scratch. To do this, you just need your data stored as a Numpy array and an Info object with the channel names, channel types, and sampling rate (other attributes are optional). Once created, the RawArray provides the same interface you have been working with throughout this notebook.
This demo will show how to create a RawArray with some randomly generated dummy data and save it in the FIF file format. Here is an explanation of the central code snippets:
| Code | Description |
|---|---|
np.random.randn(10) |
Generate 10 random numbers |
np.random.randn(5, 10) |
Generate a 5-by-10 matrix of random numbers |
mne.create_info(ch_names=["a", "b"], ch_types="eeg", sfreq=512) |
Generate an info object for two "eeg" channels named "a" and "b" with a sampling frequency of 512 |
mne.create_info(ch_names=["a", "b"], ch_types=["mag", "grad"], sfreq=512) |
Generate an info object for two channels where the first is a magnetometer and the second a gradiometer |
raw = mne.io.RawArray(data, info) |
Generate a raw data object from the data with the given info |
raw.save("recording-raw.fif", overwrite=True) |
Save the raw data to a FIF file |
First, we’ll generate some dummy data that are just random noise. We’ll generate 3 channels each with 1000 samples. Note that MNE always expects data to have the shape (n_channels, n_samples).
n_channels = 3
n_samples = 1000
data = np.random.randn(n_channels, n_samples)
data.shape(3, 1000)Next, we must create an Info object for our sensors. Let’s assume these are "eeg" channels recorded at a sampling frequency of 100 Hz.
info = mne.create_info(ch_names=["CH_1", "CH_2", "CH_3"], ch_types="eeg", sfreq=100)
info| General | ||
|---|---|---|
| MNE object type | Info | |
| Measurement date | Unknown | |
| Participant | Unknown | |
| Experimenter | Unknown | |
| Acquisition | ||
| Sampling frequency | 100.00 Hz | |
| Channels | ||
| EEG | ||
| Head & sensor digitization | Not available | |
| Filters | ||
| Highpass | 0.00 Hz | |
| Lowpass | 50.00 Hz | |
Now we can create a RawArray from data using the info created above. This works exactly like any other Raw object in MNE. For example, we can plot it using the MNE GUI.
raw = mne.io.RawArray(data=data, info=info)
raw.plot(scalings="auto");Creating RawArray with float64 data, n_channels=3, n_times=1000
Range : 0 ... 999 = 0.000 ... 9.990 secs
Ready.Finally, we can save the Raw object in the FIF file format so future analyses can skip the manual creation of the object. Per MNE’s convention, a raw data file always ends in "-raw.fif".
raw.save("dummy-raw.fif", overwrite=True);Overwriting existing file.
Writing /home/atleeri/repositories/new-learning-platform/notebooks/mne/01_raw_recordings_to_erps/01_working_with_raw_data/dummy-raw.fif
Overwriting existing file.
Closing /home/atleeri/repositories/new-learning-platform/notebooks/mne/01_raw_recordings_to_erps/01_working_with_raw_data/dummy-raw.fif
[done]