Repository: mne-tools/mne-bids

Issue:
Automated event renaming doesn't always do the right thing
```python
# %%
from pathlib import Path
from mne_bids import BIDSPath, read_raw_bids

root = Path('~/mne_data/eeg_matchingpennies')
bp = BIDSPath(
    subject='05',
    task='matchingpennies',
    suffix='eeg',
    extension='.vhdr',
    datatype='eeg',
    root=root
)
raw = read_raw_bids(bp)
```
```
The event "left" refers to multiple event values. Creating hierarchical event names.
    Renaming event: left -> left/n/a
    Renaming event: left -> left/n/a
    Renaming event: left -> left/1
    Renaming event: left -> left/n/a
    Renaming event: left -> left/n/a
    Renaming event: left -> left/1
    Renaming event: left -> left/n/a
    Renaming event: left -> left/n/a
    Renaming event: left -> left/1
...
```
The `n/a`s clearly shoulnd't be there.


Discussion:
@sappelhoff (in case you have a minute to spare :))

It appears that the `eeg_matchingpennies` events TSV file for `sub-05` starts out like this:

```
onset              	duration 	trial_type 	response_time      	stim_file      	value 	sample  	stage 	trial 	bci_prediction 	bci_prediction_valid 	n_repeated 	latency
15.038933333332999 	n/a      	right      	116.666666667      	left_hand.png  	n/a   	n/a     	1     	1     	right          	1                    	2          	-4.2
18.038933333333    	n/a      	right      	116.666666667      	left_hand.png  	n/a   	n/a     	1     	1     	right          	1                    	2          	-4.2
18.1556            	0        	right      	116.666666667      	left_hand.png  	2     	90778   	1     	1     	right          	1                    	2          	-4.2
```

IMHO this is the same event listed 3 times, and only once associated with a `value` and a `sample`, right?

The `duration` of the first two seems to be in violation of BIDS:

<img width="696" alt="Screen Shot 2022-01-06 at 19 05 21" src="https://user-images.githubusercontent.com/2046265/148429635-a88eb2a9-5364-43de-8568-324c30aa0104.png">

https://bids-specification.readthedocs.io/en/stable/04-modality-specific-files/05-task-events.html

Now I'm wondering if we should just explicitly skip rows that don't have a proper `duration` set , or issue a warning, or just remain silent and potentially produce garbage and blame it on the user, who fed us a dataset that's not fully BIDS-compliant?

cc @agramfort 
The `n/a` durations indicate that they are NOT zero (not instantaneous events), but that they are also unknown --> this is data from back when I was a masters student and recording some things for an internship, so ... there are many things that didn't go perfect :slightly_smiling_face: 

The basic problem is that back then, I formatted the BIDS dataset in a "by trial" fashion --> each row in events.tsv corresponds to **one** event in a trial ... and many columns encode additional stuff that happened during the trial ... **but not necessarily at the time of the event corresponding to that row**

This is bad practice and I should have just recorded all events and organized `events.tsv` in a "by event" fashion, where each row is an actual event, and each trial has multiple rows (because typically there are a ton of events happening each trial).

---

The current "version" of matchingpennies was created after a long discussion with Kay because we wanted to add HED tags to the dataset. See: https://github.com/bids-standard/bids-examples/pull/191

We then realized the "by trial" versus "by event" issue, and I pushed changes to make the dataset to be more in a "by event" style ... unfortunately I didn't have enough data to reproduce all the details, so that's where the `n/a`s come from.

Fast forward: Meanwhile, HED has moved to version 3, and we've all gotten a little smarter along the way, so I have a PR open to "revert" the dataset back to the original "by trial" style ... because it's tidier, and HED should be able to deal with "by trial" event structures as well (it's just less detailed than "by events"). See: https://github.com/bids-standard/bids-examples/pull/265

Unfortunately, that PR has stalled for quite a while now.

---

One last comment: I don't think `n/a` as `duration` should be invalid ... sometimes you just don't **know** the duration :thinking: 
Thanks @sappelhoff! I'll try to make things work better with the current version of the dataset. Don't bother touching it.

Resolving patch:
diff --git a/mne_bids/read.py b/mne_bids/read.py
--- a/mne_bids/read.py
+++ b/mne_bids/read.py
@@ -416,7 +416,9 @@ def _handle_events_reading(events_fname, raw):
                         f'The event "{trial_type}" refers to multiple event '
                         f'values. Creating hierarchical event names.')
                     for ii in idx:
-                        new_name = f'{trial_type}/{values[ii]}'
+                        value = values[ii]
+                        value = 'na' if value == 'n/a' else value
+                        new_name = f'{trial_type}/{value}'
                         logger.info(f'    Renaming event: {trial_type} -> '
                                     f'{new_name}')
                         trial_types[ii] = new_name


Test patch:
diff --git a/mne_bids/tests/test_read.py b/mne_bids/tests/test_read.py
--- a/mne_bids/tests/test_read.py
+++ b/mne_bids/tests/test_read.py
@@ -347,11 +347,12 @@ def test_handle_events_reading(tmp_path):
         raw = _handle_events_reading(events_fname, raw)
     events, event_id = mne.events_from_annotations(raw)
 
-    # Test with same `trial_type` referring to different `value`
-    events = {'onset': [11, 12, 13],
-              'duration': ['n/a', 'n/a', 'n/a'],
-              'trial_type': ["event1", "event1", "event2"],
-              'value': [1, 2, 3]}
+    # Test with same `trial_type` referring to different `value`:
+    # The events should be renamed automatically
+    events = {'onset': [11, 12, 13, 14, 15],
+              'duration': ['n/a', 'n/a', 'n/a', 'n/a', 'n/a'],
+              'trial_type': ["event1", "event1", "event2", "event3", "event3"],
+              'value': [1, 2, 3, 4, 'n/a']}
     events_fname = tmp_path / 'bids3' / 'sub-01_task-test_events.json'
     events_fname.parent.mkdir()
     _to_tsv(events, events_fname)
@@ -359,9 +360,11 @@ def test_handle_events_reading(tmp_path):
     raw = _handle_events_reading(events_fname, raw)
     events, event_id = mne.events_from_annotations(raw)
 
-    assert len(events) == 3
+    assert len(events) == 5
     assert 'event1/1' in event_id
     assert 'event1/2' in event_id
+    assert 'event3/4' in event_id
+    assert 'event3/na' in event_id  # 'n/a' value should become 'na'
     # The event with unique value mapping should not be renamed
     assert 'event2' in event_id