Skip to content

Commit

Permalink
Write events.json with "sample" and "value" entries
Browse files Browse the repository at this point in the history
  • Loading branch information
hoechenberger committed Apr 22, 2023
1 parent ee09799 commit 177828e
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 12 deletions.
2 changes: 1 addition & 1 deletion doc/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Detailed list of changes
🧐 API and behavior changes
^^^^^^^^^^^^^^^^^^^^^^^^^^^

- ...
- When writing events, we now also create an ``*_events.json`` file in addition to ``*_events.tsv``. This ensures compatibility with the upcoming release of BIDS 1.9, by `Richard Höchenberger`_ (:gh:`1131`)

🛠 Requirements
^^^^^^^^^^^^^^^
Expand Down
6 changes: 6 additions & 0 deletions mne_bids/tests/test_write.py
Original file line number Diff line number Diff line change
Expand Up @@ -2647,6 +2647,7 @@ def test_annotations_and_events(_bids_validate, tmp_path, write_events):
suffix='events',
extension='.tsv',
)
events_json_fname = events_tsv_fname.copy().update(extension='.json')

events = mne.read_events(events_fname)
events = events[events[:, 2] != 0] # drop unknown "0" events
Expand Down Expand Up @@ -2699,6 +2700,11 @@ def test_annotations_and_events(_bids_validate, tmp_path, write_events):

if write_events:
n_events_expected = len(events) + len(raw.annotations)
events_json = json.loads(
events_json_fname.fpath.read_text(encoding='utf-8')
)
assert 'value' in events_json
assert 'sample' in events_json
else:
n_events_expected = len(raw.annotations)

Expand Down
59 changes: 48 additions & 11 deletions mne_bids/write.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,39 @@ def _events_tsv(events, durations, raw, fname, trial_type, overwrite=False):
_write_tsv(fname, data, overwrite)


def _events_json(fname, overwrite=False):
"""Create participants.json for non-default columns in accompanying TSV.
Parameters
----------
fname : str | mne_bids.BIDSPath
Output filename.
overwrite : bool
Whether to overwrite the output file if it exists.
"""
new_data = {
'sample': {
'Description': 'The event onset time in number of sampling points.'
},
'value': {
'Description': (
'The event code / trigger code associated with the event.'
)
}
}

# make sure to append any JSON fields added by the user
fname = Path(fname)
if fname.exists():
orig_data = json.loads(
fname.read_text(encoding='utf-8'),
object_pairs_hook=OrderedDict
)
new_data = {**orig_data, **new_data}

_write_json(fname, new_data, overwrite)


def _readme(datatype, fname, overwrite=False):
"""Create a README file and save it.
Expand Down Expand Up @@ -454,15 +487,15 @@ def _participants_json(fname, overwrite=False):
Parameters
----------
fname : str | mne_bids.BIDSPath
Filename to save the scans.tsv to.
Output filename.
overwrite : bool
Defaults to False.
Whether to overwrite the existing data in the file.
If there is already data for the given `fname` and overwrite is False,
an error will be raised.
"""
data = {
new_data = {
'participant_id': {
'Description': 'Unique participant identifier'
},
Expand Down Expand Up @@ -500,15 +533,13 @@ def _participants_json(fname, overwrite=False):
# if `overwrite` is True
fname = Path(fname)
if fname.exists():
orig_cols = json.loads(
orig_data = json.loads(
fname.read_text(encoding='utf-8'),
object_pairs_hook=OrderedDict
)
for key, val in orig_cols.items():
if key not in data:
data[key] = val
new_data = {**orig_data, **new_data}

_write_json(fname, data, overwrite)
_write_json(fname, new_data, overwrite)


def _scans_tsv(raw, raw_fname, fname, keep_source, overwrite=False):
Expand Down Expand Up @@ -1763,7 +1794,10 @@ def write_raw_bids(

sidecar_path = bids_path.copy().update(suffix=bids_path.datatype,
extension='.json')
events_path = bids_path.copy().update(suffix='events', extension='.tsv')
events_tsv_path = bids_path.copy().update(
suffix='events', extension='.tsv'
)
events_json_path = events_tsv_path.copy().update(extension='.json')
channels_path = bids_path.copy().update(
suffix='channels', extension='.tsv')

Expand Down Expand Up @@ -1838,9 +1872,12 @@ def write_raw_bids(
events_array, event_dur, event_desc_id_map = _read_events(
events, event_id, raw, bids_path=bids_path)
if events_array.size != 0:
_events_tsv(events=events_array, durations=event_dur, raw=raw,
fname=events_path.fpath, trial_type=event_desc_id_map,
overwrite=overwrite)
_events_tsv(
events=events_array, durations=event_dur, raw=raw,
fname=events_tsv_path.fpath, trial_type=event_desc_id_map,
overwrite=overwrite
)
_events_json(fname=events_json_path.fpath, overwrite=overwrite)
# Kepp events_array around for BrainVision writing below.
del event_desc_id_map, events, event_id, event_dur

Expand Down

0 comments on commit 177828e

Please sign in to comment.