09. Storing empty room data in BIDS format

This example demonstrates how to store empty room data in BIDS format and how to retrieve them.

# Authors: Mainak Jas <mainakjas@gmail.com>
#
# License: BSD-3-Clause

We are dealing with MEG data, which is often accompanied by so-called “empty room” recordings for noise modeling. Below we show that we can use MNE-BIDS to also save such a recording with the just converted data.

Let us first import mne_bids.

import os.path as op
import shutil

from datetime import datetime, timezone

import mne
from mne.datasets import sample

from mne_bids import (write_raw_bids, read_raw_bids,
                      BIDSPath, print_dir_tree)

And define the paths and event_id dictionary.

data_path = sample.data_path()
raw_fname = op.join(data_path, 'MEG', 'sample', 'sample_audvis_raw.fif')

bids_root = op.join(data_path, '..', 'MNE-sample-data-bids')

To ensure the output path doesn’t contain any leftover files from previous tests and example runs, we simply delete it.

Warning

Do not delete directories that may contain important data!

Specify the raw_file and events_data and run the BIDS conversion, and write the BIDS data.

raw = mne.io.read_raw_fif(raw_fname)
raw.info['line_freq'] = 60  # specify power line frequency as required by BIDS

bids_path = BIDSPath(subject='01', session='01',
                     task='audiovisual', run='01', root=bids_root)
write_raw_bids(raw, bids_path, overwrite=True)

Out:

Opening raw data file /Users/hoechenberger/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.
Opening raw data file /Users/hoechenberger/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.
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/README'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.tsv'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.json'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/ses-01/meg/sub-01_ses-01_coordsystem.json'...
/Users/hoechenberger/Development/mne-bids/mne_bids/read.py:176: RuntimeWarning: No events found or provided. Please add annotations to the raw data, or provide the events_data and event_id parameters. For resting state data, BIDS recommends naming the task using labels beginning with "rest".
  warn('No events found or provided. Please add annotations to the raw '
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/dataset_description.json'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/ses-01/meg/sub-01_ses-01_task-audiovisual_run-01_meg.json'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/ses-01/meg/sub-01_ses-01_task-audiovisual_run-01_channels.tsv'...
Copying data files to sub-01_ses-01_task-audiovisual_run-01_meg.fif
Reserving possible split file sub-01_ses-01_task-audiovisual_run-01_split-01_meg.fif
Writing /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/ses-01/meg/sub-01_ses-01_task-audiovisual_run-01_meg.fif
Closing /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/ses-01/meg/sub-01_ses-01_task-audiovisual_run-01_meg.fif
[done]
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/ses-01/sub-01_ses-01_scans.tsv'...
Wrote /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/ses-01/sub-01_ses-01_scans.tsv entry with meg/sub-01_ses-01_task-audiovisual_run-01_meg.fif.

BIDSPath(
root: /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids
datatype: meg
basename: sub-01_ses-01_task-audiovisual_run-01_meg.fif)

Specify some empty room data and run BIDS conversion on it.

er_raw_fname = op.join(data_path, 'MEG', 'sample', 'ernoise_raw.fif')
er_raw = mne.io.read_raw_fif(er_raw_fname)
er_raw.info['line_freq'] = 60  # specify power line frequency as req. by BIDS

# For empty room data we need to specify the recording date in the format
# YYYYMMDD for the session id.
er_date = er_raw.info['meas_date'].strftime('%Y%m%d')
print(er_date)

Out:

Opening raw data file /Users/hoechenberger/mne_data/MNE-sample-data/MEG/sample/ernoise_raw.fif...
Isotrak not found
    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 : 19800 ... 85867 =     32.966 ...   142.965 secs
Ready.
20021206

The measurement date is

raw_date = raw.info['meas_date'].strftime('%Y%m%d')
print(raw_date)

Out:

20021203

We also need to specify that the subject ID is ‘emptyroom’, and that the task is ‘noise’ (these are BIDS rules).

er_bids_path = BIDSPath(subject='emptyroom', session=er_date,
                        task='noise', root=bids_root)
write_raw_bids(er_raw, er_bids_path, overwrite=True)

Out:

Opening raw data file /Users/hoechenberger/mne_data/MNE-sample-data/MEG/sample/ernoise_raw.fif...
Isotrak not found
    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 : 19800 ... 85867 =     32.966 ...   142.965 secs
Ready.
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.tsv'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.json'...
Writing of electrodes.tsv is not supported for data type "meg". Skipping ...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/dataset_description.json'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021206/meg/sub-emptyroom_ses-20021206_task-noise_meg.json'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021206/meg/sub-emptyroom_ses-20021206_task-noise_channels.tsv'...
Copying data files to sub-emptyroom_ses-20021206_task-noise_meg.fif
Reserving possible split file sub-emptyroom_ses-20021206_task-noise_split-01_meg.fif
Writing /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021206/meg/sub-emptyroom_ses-20021206_task-noise_meg.fif
Closing /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021206/meg/sub-emptyroom_ses-20021206_task-noise_meg.fif
[done]
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021206/sub-emptyroom_ses-20021206_scans.tsv'...
Wrote /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021206/sub-emptyroom_ses-20021206_scans.tsv entry with meg/sub-emptyroom_ses-20021206_task-noise_meg.fif.

BIDSPath(
root: /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids
datatype: meg
basename: sub-emptyroom_ses-20021206_task-noise_meg.fif)

Just to illustrate, we can save more than one empty room file for different dates. Here, they will all contain the same data but in your study, they will be different on different days.

dates = ['20021204', '20021201', '20021001']

for date in dates:
    er_bids_path.update(session=date)
    er_meas_date = datetime.strptime(date, '%Y%m%d')
    er_raw.set_meas_date(er_meas_date.replace(tzinfo=timezone.utc))
    write_raw_bids(er_raw, er_bids_path, overwrite=True)

Out:

Opening raw data file /Users/hoechenberger/mne_data/MNE-sample-data/MEG/sample/ernoise_raw.fif...
Isotrak not found
    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 : 19800 ... 85867 =     32.966 ...   142.965 secs
Ready.
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.tsv'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.json'...
Writing of electrodes.tsv is not supported for data type "meg". Skipping ...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/dataset_description.json'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021204/meg/sub-emptyroom_ses-20021204_task-noise_meg.json'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021204/meg/sub-emptyroom_ses-20021204_task-noise_channels.tsv'...
Copying data files to sub-emptyroom_ses-20021204_task-noise_meg.fif
Reserving possible split file sub-emptyroom_ses-20021204_task-noise_split-01_meg.fif
Writing /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021204/meg/sub-emptyroom_ses-20021204_task-noise_meg.fif
Closing /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021204/meg/sub-emptyroom_ses-20021204_task-noise_meg.fif
[done]
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021204/sub-emptyroom_ses-20021204_scans.tsv'...
Wrote /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021204/sub-emptyroom_ses-20021204_scans.tsv entry with meg/sub-emptyroom_ses-20021204_task-noise_meg.fif.
Opening raw data file /Users/hoechenberger/mne_data/MNE-sample-data/MEG/sample/ernoise_raw.fif...
Isotrak not found
    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 : 19800 ... 85867 =     32.966 ...   142.965 secs
Ready.
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.tsv'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.json'...
Writing of electrodes.tsv is not supported for data type "meg". Skipping ...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/dataset_description.json'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021201/meg/sub-emptyroom_ses-20021201_task-noise_meg.json'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021201/meg/sub-emptyroom_ses-20021201_task-noise_channels.tsv'...
Copying data files to sub-emptyroom_ses-20021201_task-noise_meg.fif
Reserving possible split file sub-emptyroom_ses-20021201_task-noise_split-01_meg.fif
Writing /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021201/meg/sub-emptyroom_ses-20021201_task-noise_meg.fif
Closing /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021201/meg/sub-emptyroom_ses-20021201_task-noise_meg.fif
[done]
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021201/sub-emptyroom_ses-20021201_scans.tsv'...
Wrote /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021201/sub-emptyroom_ses-20021201_scans.tsv entry with meg/sub-emptyroom_ses-20021201_task-noise_meg.fif.
Opening raw data file /Users/hoechenberger/mne_data/MNE-sample-data/MEG/sample/ernoise_raw.fif...
Isotrak not found
    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 : 19800 ... 85867 =     32.966 ...   142.965 secs
Ready.
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.tsv'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.json'...
Writing of electrodes.tsv is not supported for data type "meg". Skipping ...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/dataset_description.json'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021001/meg/sub-emptyroom_ses-20021001_task-noise_meg.json'...
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021001/meg/sub-emptyroom_ses-20021001_task-noise_channels.tsv'...
Copying data files to sub-emptyroom_ses-20021001_task-noise_meg.fif
Reserving possible split file sub-emptyroom_ses-20021001_task-noise_split-01_meg.fif
Writing /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021001/meg/sub-emptyroom_ses-20021001_task-noise_meg.fif
Closing /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021001/meg/sub-emptyroom_ses-20021001_task-noise_meg.fif
[done]
Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021001/sub-emptyroom_ses-20021001_scans.tsv'...
Wrote /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021001/sub-emptyroom_ses-20021001_scans.tsv entry with meg/sub-emptyroom_ses-20021001_task-noise_meg.fif.

Let us look at the directory structure

Out:

|MNE-sample-data-bids/
|--- README
|--- dataset_description.json
|--- participants.json
|--- participants.tsv
|--- sub-01/
|------ ses-01/
|--------- sub-01_ses-01_scans.tsv
|--------- meg/
|------------ sub-01_ses-01_coordsystem.json
|------------ sub-01_ses-01_task-audiovisual_run-01_channels.tsv
|------------ sub-01_ses-01_task-audiovisual_run-01_meg.fif
|------------ sub-01_ses-01_task-audiovisual_run-01_meg.json
|--- sub-emptyroom/
|------ ses-20021001/
|--------- sub-emptyroom_ses-20021001_scans.tsv
|--------- meg/
|------------ sub-emptyroom_ses-20021001_task-noise_channels.tsv
|------------ sub-emptyroom_ses-20021001_task-noise_meg.fif
|------------ sub-emptyroom_ses-20021001_task-noise_meg.json
|------ ses-20021201/
|--------- sub-emptyroom_ses-20021201_scans.tsv
|--------- meg/
|------------ sub-emptyroom_ses-20021201_task-noise_channels.tsv
|------------ sub-emptyroom_ses-20021201_task-noise_meg.fif
|------------ sub-emptyroom_ses-20021201_task-noise_meg.json
|------ ses-20021204/
|--------- sub-emptyroom_ses-20021204_scans.tsv
|--------- meg/
|------------ sub-emptyroom_ses-20021204_task-noise_channels.tsv
|------------ sub-emptyroom_ses-20021204_task-noise_meg.fif
|------------ sub-emptyroom_ses-20021204_task-noise_meg.json
|------ ses-20021206/
|--------- sub-emptyroom_ses-20021206_scans.tsv
|--------- meg/
|------------ sub-emptyroom_ses-20021206_task-noise_channels.tsv
|------------ sub-emptyroom_ses-20021206_task-noise_meg.fif
|------------ sub-emptyroom_ses-20021206_task-noise_meg.json

To get an accurate estimate of the noise, it is important that the empty room recording be as close in date as the raw data. We can retrieve the basename corresponding to the empty room recording that is closest in time to the experimental measurement.

Out:

The MEG sidecar file does not contain an "AssociatedEmptyRoom" entry. Will try to find a matching empty-room recording based on the measurement date …
Opening raw data file /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/ses-01/meg/sub-01_ses-01_task-audiovisual_run-01_meg.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.
/Users/hoechenberger/Development/mne-bids/mne_bids/path.py:1473: RuntimeWarning: Did not find any events.tsv associated with sub-01_ses-01_task-audiovisual_run-01.

The search_str was "/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/**/meg/sub-01_ses-01*events.tsv"
  warn(msg)
Reading channel info from /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/ses-01/meg/sub-01_ses-01_task-audiovisual_run-01_channels.tsv.
/Users/hoechenberger/Development/mne-bids/mne_bids/read.py:553: RuntimeWarning: The unit for channel(s) STI 001, STI 002, STI 003, STI 004, STI 005, STI 006, STI 014, STI 015, STI 016 has changed from V to NA.
  raw.set_channel_types(ch_type_map_avail)
/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021204/meg/sub-emptyroom_ses-20021204_task-noise_meg.fif

Finally, we can read the empty room file using

Out:

Opening raw data file /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021204/meg/sub-emptyroom_ses-20021204_task-noise_meg.fif...
Isotrak not found
    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 : 19800 ... 85867 =     32.966 ...   142.965 secs
Ready.
/Users/hoechenberger/Development/mne-bids/mne_bids/path.py:1473: RuntimeWarning: Did not find any events.tsv associated with sub-emptyroom_ses-20021204_task-noise.

The search_str was "/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/**/meg/sub-emptyroom_ses-20021204*events.tsv"
  warn(msg)
Reading channel info from /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-emptyroom/ses-20021204/meg/sub-emptyroom_ses-20021204_task-noise_channels.tsv.
/Users/hoechenberger/Development/mne-bids/mne_bids/read.py:553: RuntimeWarning: The unit for channel(s) STI 001, STI 002, STI 003, STI 004, STI 005, STI 006, STI 014, STI 015, STI 016 has changed from V to NA.
  raw.set_channel_types(ch_type_map_avail)
<Raw | sub-emptyroom_ses-20021204_task-noise_meg.fif, 315 x 66068 (110.0 s), ~368 kB, data not loaded>

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

Gallery generated by Sphinx-Gallery