13. Writing modified files with MNE-BIDS

MNE-BIDS is designed such that it enforces good practices when working with BIDS data. One of the principles of creating BIDS datasets from raw data is that the raw data should ideally be written unmodified, as-is. To enforce this, mne_bids.write_raw_bids() performs some basic checks and will throw an exception if it believes you’re doing something that you really shouldn’t be doing (i.e., trying to store modified “raw” data as a BIDS raw data set.)

There might be some – rare! – situations, however, when working around this intentional limitation in MNE-BIDS can be warranted. For example, you might encounter data that has manually been split across multiple files during recording, even though it belongs to a single experimental run. In this case, you might want to concatenate the data before storing them in BIDS. This tutorial will give you an example on how to use mne_bids.write_raw_bids() to store such data, despite it being modified before writing.

Warning

Please be aware that the situations in which you would need to apply the following solution are extremely rare. If you ever find yourself wanting to apply this solution, please take a step back, take a deep breath and re-consider whether this is absolutely necessary. If even a slight doubt remains, reach out to the MNE-BIDS developers.

# Authors: Richard Höchenberger <richard.hoechenberger@gmail.com>
# License: BSD (3-clause)

Load the sample dataset, and create a concatenated raw data object.

from pathlib import Path
from tempfile import NamedTemporaryFile

import mne
from mne.datasets import sample

from mne_bids import write_raw_bids, BIDSPath


data_path = Path(sample.data_path())
raw_fname = data_path / 'MEG' / 'sample' / 'sample_audvis_raw.fif'
output_path = data_path / '..' / 'MNE-sample-data-bids'
bids_path = BIDSPath(subject='01', task='audiovisual', root=output_path)

raw = mne.io.read_raw_fif(raw_fname)
raw.info['line_freq'] = 60
raw_concat = mne.concatenate_raws([raw.copy(), raw])

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.

Trying to write these data will fail.

try:
    write_raw_bids(raw=raw_concat, bids_path=bids_path, overwrite=True)
except ValueError as e:
    print(f'Data cannot be written. Exception message was: {e}')

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.
Data cannot be written. Exception message was: The raw data you want to write contains more time points than the raw data on disk. It is possible that you concatenated your data, which write_raw_bids() won't accept. If you believe you have a valid use case that should be supported, please reach out to the developers at https://github.com/mne-tools/mne-bids/issues

We can work around this limitation by first writing the modified data to a temporary file, reading it back in, and then writing it via MNE-BIDS.

with NamedTemporaryFile(suffix='_raw.fif') as f:
    fname = f.name
    raw_concat.save(fname, overwrite=True)
    raw_concat = mne.io.read_raw_fif(fname, preload=False)
    write_raw_bids(raw=raw_concat, bids_path=bids_path, overwrite=True)

Out:

Overwriting existing file.
Writing /private/var/folders/xg/7d96k64d7jv9q1d88_s8swjh0000gn/T/tmp6arum250_raw.fif
Closing /private/var/folders/xg/7d96k64d7jv9q1d88_s8swjh0000gn/T/tmp6arum250_raw.fif
[done]
Opening raw data file /var/folders/xg/7d96k64d7jv9q1d88_s8swjh0000gn/T/tmp6arum250_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 ... 359399 =     42.956 ...   598.385 secs
Ready.
Opening raw data file /var/folders/xg/7d96k64d7jv9q1d88_s8swjh0000gn/T/tmp6arum250_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 ... 359399 =     42.956 ...   598.385 secs
Ready.

Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.tsv'...

participant_id  age     sex     hand
sub-01  n/a     n/a     n/a

Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/participants.json'...

{
    "participant_id": {
        "Description": "Unique participant identifier"
    },
    "age": {
        "Description": "Age of the participant at time of testing",
        "Units": "years"
    },
    "sex": {
        "Description": "Biological sex of the participant",
        "Levels": {
            "F": "female",
            "M": "male"
        }
    },
    "hand": {
        "Description": "Handedness of the participant",
        "Levels": {
            "R": "right",
            "L": "left",
            "A": "ambidextrous"
        }
    }
}

Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/meg/sub-01_coordsystem.json'...

{
    "MEGCoordinateSystem": "ElektaNeuromag",
    "MEGCoordinateUnits": "m",
    "MEGCoordinateSystemDescription": "RAS orientation and the origin between the ears",
    "HeadCoilCoordinates": {
        "NAS": [
            3.725290298461914e-09,
            0.10260561108589172,
            4.190951585769653e-09
        ],
        "LPA": [
            -0.07137660682201385,
            0.0,
            5.122274160385132e-09
        ],
        "RPA": [
            0.07526767998933792,
            0.0,
            5.587935447692871e-09
        ],
        "coil1": [
            0.032922741025686264,
            0.09897983074188232,
            0.07984329760074615
        ],
        "coil2": [
            -0.06998106092214584,
            0.06771647930145264,
            0.06888450682163239
        ],
        "coil3": [
            -0.07260829955339432,
            -0.02086828649044037,
            0.0971473976969719
        ],
        "coil4": [
            0.04996863007545471,
            -0.007233052980154753,
            0.1228904277086258
        ]
    },
    "HeadCoilCoordinateSystem": "ElektaNeuromag",
    "HeadCoilCoordinateUnits": "m"
}

Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/meg/sub-01_task-audiovisual_events.tsv'...

onset   duration        trial_type      value   sample
277.7153462901591       0.0     BAD boundary    1       166800
277.7153462901591       0.0     EDGE boundary   2       166800

Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/dataset_description.json'...

{
    "Name": " ",
    "BIDSVersion": "1.4.0",
    "DatasetType": "raw",
    "Authors": [
        "Please cite MNE-BIDS in your publication before removing this (citations in README)"
    ]
}
Reading 0 ... 333599  =      0.000 ...   555.429 secs...

Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/meg/sub-01_task-audiovisual_meg.json'...

{
    "TaskName": "audiovisual",
    "Manufacturer": "Elekta",
    "PowerLineFrequency": 60.0,
    "SamplingFrequency": 600.614990234375,
    "SoftwareFilters": "n/a",
    "RecordingDuration": 555.4290276202087,
    "RecordingType": "continuous",
    "DewarPosition": "n/a",
    "DigitizedLandmarks": false,
    "DigitizedHeadPoints": false,
    "MEGChannelCount": 306,
    "MEGREFChannelCount": 0,
    "EEGChannelCount": 60,
    "EOGChannelCount": 1,
    "ECGChannelCount": 0,
    "EMGChannelCount": 0,
    "MiscChannelCount": 0,
    "TriggerChannelCount": 9
}

Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/meg/sub-01_task-audiovisual_channels.tsv'...

name    type    units   low_cutoff      high_cutoff     description     sampling_frequency      status  status_description
MEG 0113        MEGGRADPLANAR   T/m     0.10000000149011612     172.17630004882812      Planar Gradiometer      600.614990234375        good    n/a
MEG 0112        MEGGRADPLANAR   T/m     0.10000000149011612     172.17630004882812      Planar Gradiometer      600.614990234375        good    n/a
MEG 0111        MEGMAG  T       0.10000000149011612     172.17630004882812      Magnetometer    600.614990234375        good    n/a
MEG 0122        MEGGRADPLANAR   T/m     0.10000000149011612     172.17630004882812      Planar Gradiometer      600.614990234375        good    n/a
MEG 0123        MEGGRADPLANAR   T/m     0.10000000149011612     172.17630004882812      Planar Gradiometer      600.614990234375        good    n/a
Copying data files to sub-01_task-audiovisual_meg.fif
Overwriting existing file.
Reserving possible split file sub-01_task-audiovisual_split-01_meg.fif
Writing /Users/hoechenberger/mne_data/MNE-sample-data-bids/sub-01/meg/sub-01_task-audiovisual_meg.fif
Closing /Users/hoechenberger/mne_data/MNE-sample-data-bids/sub-01/meg/sub-01_task-audiovisual_meg.fif
[done]

Writing '/Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/sub-01_scans.tsv'...

filename        acq_time
meg/sub-01_task-audiovisual_meg.fif     2002-12-03T19:01:10.720100Z
Wrote /Users/hoechenberger/mne_data/MNE-sample-data/../MNE-sample-data-bids/sub-01/sub-01_scans.tsv entry with meg/sub-01_task-audiovisual_meg.fif.

That’s it!

Warning

Remember, this should only ever be a last resort!

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

Gallery generated by Sphinx-Gallery