Repository: mne-tools/mne-python

Issue:
Cropping and first event index
It seems that when using events to crop a file, and then subsequently getting the events of the cropped file with initial_event=True, the first event has an incorrect index of 0, when it should be equal to raw.first_samp. If you use a start time one sample prior to this event, the first event has the correct index.


```
import mne.datasets
from pathlib import Path
import mne

sample_data_folder = mne.datasets.sample.data_path()
sample_data_raw_file = os.path.join(sample_data_folder, 'MEG', 'sample',
                                    'sample_audvis_filt-0-40_raw.fif')
raw = mne.io.read_raw_fif(sample_data_raw_file)
# extract events
events = mne.find_events(raw, shortest_event=1, initial_event=True)

# use the fifth event as the start and the 10th event as the stop
start_event_idx = 5
stop_event_idx = 10
print("Start event:", events[start_event_idx,:])
print("Stop event:", events[stop_event_idx,:])
print("First sample index:", raw.first_samp)
# events include the raw.first_samp offset, so must subtract that to get the actual index in the raw.times array
start_idx = events[start_event_idx,0] - raw.first_samp
stop_idx = events[stop_event_idx,0] - raw.first_samp
start_time = raw.times[start_idx] 
start_time_2 = raw.times[start_idx-1] # start one time sample before the event occurs
stop_time = raw.times[stop_idx]

print(f"splitting from index {start_idx} to {stop_idx}")
print(f"splitting from time {start_time} to {stop_time}")
print("====")
print(f"splitting from index {start_idx-1} to {stop_idx}")
print(f"splitting from time {start_time_2} to {stop_time}")

# crop from exactly the start event to the stop event, inclusive
cropped_eeg = raw.copy().crop(tmin=start_time, tmax=stop_time, include_tmax = True)
# crop starting 1 time sample before the start event to the stop event, inclusive
cropped_eeg_2 = raw.copy().crop(tmin=start_time_2, tmax=stop_time, include_tmax = True)

# get the events from both cropped data
cropped_events = mne.find_events(cropped_eeg, shortest_event=1, initial_event=True)
cropped_events_2 = mne.find_events(cropped_eeg_2, shortest_event=1, initial_event=True)

print("raw has length:", len(raw.times))
print("cropped has length:", len(cropped_eeg.times))
print("cropped 2 has length:", len(cropped_eeg_2.times)) # should be len(cropped_eeg.times)+1

# print the events, they should all be exactly the same
for idx, event in enumerate(cropped_events):
    print(cropped_events[idx,:], events[start_event_idx+idx,:], cropped_events_2[idx,:])

```

This produces the following output:

```
Opening raw data file /root/mne_data/MNE-sample-data/MEG/sample/sample_audvis_filt-0-40_raw.fif...
    Read a total of 4 projection items:
        PCA-v1 (1 x 102)  idle
        PCA-v2 (1 x 102)  idle
        PCA-v3 (1 x 102)  idle
        Average EEG reference (1 x 60)  idle
    Range : 6450 ... 48149 =     42.956 ...   320.665 secs
Ready.
319 events found
Event IDs: [ 1  2  3  4  5 32]
Start event: [7506    0    3]
Stop event: [8025    0    1]
First sample index: 6450
splitting from index 1056 to 1575
splitting from time 7.032791503175253 to 10.489248690815362
====
splitting from index 1055 to 1575
splitting from time 7.02613166273664 to 10.489248690815362
6 events found
Event IDs: [1 2 3 4]
6 events found
Event IDs: [1 2 3 4]
raw has length: 41700
cropped has length: 520
cropped 2 has length: 521
[0 0 3] [7506    0    3] [7506    0    3]
[7612    0    1] [7612    0    1] [7612    0    1]
[7709    0    4] [7709    0    4] [7709    0    4]
[7810    0    2] [7810    0    2] [7810    0    2]
[7916    0    3] [7916    0    3] [7916    0    3]
[8025    0    1] [8025    0    1] [8025    0    1]
```

My expectation is that they should all print identically, i.e. the first event in cropped_events should be [7506, 0, 3] and not [0, 0, 3]. By starting one time sample prior to the event start, it produces expected results. Is this intended behavior?


Discussion:
Hello! 👋 Thanks for opening your first issue here! ❤️ We will try to get back to you soon. 🚴🏽‍♂️


Resolving patch:
diff --git a/mne/event.py b/mne/event.py
--- a/mne/event.py
+++ b/mne/event.py
@@ -474,7 +474,8 @@ def _find_events(data, first_samp, verbose=None, output='onset',
     initial_value = data[0, 0]
     if initial_value != 0:
         if initial_event:
-            events = np.insert(events, 0, [0, 0, initial_value], axis=0)
+            events = np.insert(
+                events, 0, [first_samp, 0, initial_value], axis=0)
         else:
             logger.info('Trigger channel has a non-zero initial value of {} '
                         '(consider using initial_event=True to detect this '


Test patch:
diff --git a/mne/tests/test_event.py b/mne/tests/test_event.py
--- a/mne/tests/test_event.py
+++ b/mne/tests/test_event.py
@@ -381,12 +381,12 @@ def test_find_events():
     # test initial_event argument
     info = create_info(['MYSTI'], 1000, 'stim')
     data = np.zeros((1, 1000))
-    raw = RawArray(data, info)
+    raw = RawArray(data, info, first_samp=7)
     data[0, :10] = 100
     data[0, 30:40] = 200
-    assert_array_equal(find_events(raw, 'MYSTI'), [[30, 0, 200]])
+    assert_array_equal(find_events(raw, 'MYSTI'), [[37, 0, 200]])
     assert_array_equal(find_events(raw, 'MYSTI', initial_event=True),
-                       [[0, 0, 100], [30, 0, 200]])
+                       [[7, 0, 100], [37, 0, 200]])
 
     # test error message for raw without stim channels
     raw = read_raw_fif(raw_fname, preload=True)