Epoch order during EEG preprocessing

Hi,

I’m currently using events_from_annot, event_dict = mne.events_from_annotations(raw) as part of my epoching process, and have managed to get outputs following preprocessing.

However, the epoch order does not match the order in which the experiment ran. For example, if events ran A, B, C, and D during data collection, the print(events_from_annot[:5]) gives me an order of C, B, A, D. Any reason why this is the case?

Thank you.

Cheers,
Thapa

Hello, have you checked whether the annotations are actually in the expected order?

Best wishes,
Richard

Hi Richard,

Yup, I checked it, and they’re not in the correct order. Therefore, I was wondering why this was the case.

Below is the output from print(events_from_annot[:5]). The event order should start from 1, 2, 3, or 4 onwards (events were randomised for each participant).

Am I right in interpreting the first column as the index of the Event? If yes, then the question is how was this determined as its determining the Epoch order below.

[[ 5455     0     8]
 [ 5711     0    20]
 [ 5968     0    20]
 [ 6224     0    20]
 [24296     0    25]
 [26471     0     4]
 [28306     0     1]
 [30276     0     1]
 [32010     0     3]
 [33746     0     3]]

Cheers,
Thapa

But how do you expect the events — which you create from the annotations — to be in the correct order if the annotations are already not in the correct order? It seems to me you need to fix your annotations…

Did you specify this by passing event_id when converting the annotations to events? Because otherwise MNE will basically assign arbitrary numbers as event codes.

No worries, Richard.

I’ve figured it out. All I had to do was reorder the list from events_from_annot using the lines below:

events_from_annot, event_dict = mne.events_from_annotations(raw)

sort_events_from_annot = events_from_annot[events_from_annot[:, 2].argsort()]

print(sort_events_from_annot)

I now get the output in the correct order:

[[ 84978      0      1]
 [ 48362      0      1]
 [103967      0      1]
 [121117      0      1]
 [ 58472      0      1]
 [105642      0      1]
 [ 71226      0      2]
 [127843      0      2]
 [122811      0      2]
 [ 76343      0      2]
 [114219      0      2]
 [112456      0      2]
 [ 95332      0      3]
 [100496      0      3]
 [ 61863      0      3]

Thank you.

Cheers,
Thapa

But now your events array is not ordered by sample numbers. You should not use this to create epochs! (Not sure if that would work anyway). We expect sample numbers to be monotonically increasing.

Can you check your raw.annotations? This is what you start out with, and events are created using those annotations.

Thanks, Clemens and Richard.

Here is the output from raw.annotations

Below are raw annotations
<Annotations | 87 segments: A (6), B (6), D (20), E (24), F (1), G (2), H ...>

Could you show us the output of raw.annotations.to_data_frame()? This will produce a pandas dataframe with onset, description, and duration of all annotations. You can then use this table to verify how your annotations get converted to events. BTW, this information can also be found in event_dict, the second return value of mne.events_from_annotations() - what does it look like in your case?

2 Likes

Here’s the output from raw.annotations.to_data_frame().head(20):


onset	duration	description
0	2022-07-26 08:32:00.678001	0.0	RS232 Trigger: 115('s')
1	2022-07-26 08:32:01.682999	0.0	RS232 Trigger: 115('s')
2	2022-07-26 08:32:02.683998	0.0	RS232 Trigger: 115('s')
3	2022-07-26 08:32:40.308998	0.0	RS232 Trigger: 100('d')
4	2022-07-26 08:32:47.757004	0.0	RS232 Trigger: 101('e')
5	2022-07-26 08:32:55.166000	0.0	RS232 Trigger: 100('d')
6	2022-07-26 08:33:02.076004	0.0	RS232 Trigger: 100('d')
7	2022-07-26 08:33:08.705002	0.0	RS232 Trigger: 101('e')
8	2022-07-26 08:33:15.257004	0.0	RS232 Trigger: 100('d')
9	2022-07-26 08:33:21.906006	0.0	RS232 Trigger: 101('e')
10	2022-07-26 08:33:28.572006	0.0	RS232 Trigger: 101('e')
11	2022-07-26 08:33:35.350006	0.0	RS232 Trigger: 101('e')
12	2022-07-26 08:33:42.233002	0.0	RS232 Trigger: 101('e')
13	2022-07-26 08:33:48.776993	0.0	RS232 Trigger: 101('e')
14	2022-07-26 08:33:55.225006	0.0	RS232 Trigger: 101('e')
15	2022-07-26 08:34:01.912994	0.0	RS232 Trigger: 97('a')
16	2022-07-26 08:34:08.570007	0.0	RS232 Trigger: 99('c')
17	2022-07-26 08:34:15.093002	0.0	RS232 Trigger: 99('c')
18	2022-07-26 08:34:21.796005	0.0	RS232 Trigger: 101('e')
19	2022-07-26 08:34:28.223007	0.0	RS232 Trigger: 101('e')

And from event_dict

{"RS232 Trigger: 100('d')": 1,
 "RS232 Trigger: 101('e')": 2,
 "RS232 Trigger: 102('f')": 3,
 "RS232 Trigger: 103('g')": 4,
 "RS232 Trigger: 104('h')": 5,
 "RS232 Trigger: 106('j')": 6,
 "RS232 Trigger: 107('k')": 7,
 "RS232 Trigger: 108('l')": 8,
 "RS232 Trigger: 109('m')": 9,
 "RS232 Trigger: 110('n')": 10,
 "RS232 Trigger: 111('o')": 11,
 "RS232 Trigger: 112('p')": 12,
 "RS232 Trigger: 113('q')": 13,
 "RS232 Trigger: 114('r')": 14,
 "RS232 Trigger: 115('s')": 15,
 "RS232 Trigger: 116('t')": 16,
 "RS232 Trigger: 117('u')": 17,
 "RS232 Trigger: 118('v')": 18,
 "RS232 Trigger: 119('w')": 19,
 "RS232 Trigger: 97('a')": 20,
 "RS232 Trigger: 98('b')": 21,
 "RS232 Trigger: 99('c')": 22}

OK, and the problem is that your events do not match this sequence? Can you show the first twenty rows from your events again please?

Thanks, Clemens.

The events[:20] match the sequence of raw.annotations.to_data_frame().head(20) above :slight_smile:

array([[17326,     0,    15],
       [17583,     0,    15],
       [17839,     0,    15],
       [27471,     0,     1],
       [29378,     0,     2],
       [31274,     0,     1],
       [33043,     0,     1],
       [34740,     0,     2],
       [36418,     0,     1],
       [38120,     0,     2],
       [39826,     0,     2],
       [41562,     0,     2],
       [43324,     0,     2],
       [44999,     0,     2],
       [46650,     0,     2],
       [48362,     0,    20],
       [50066,     0,    22],
       [51736,     0,    22],
       [53452,     0,     2],
       [55097,     0,     2]])

So this means problem solved :smiling_face:?

1 Like

Yup! All good.

I was looking at the wrong variable :slight_smile:

Thanks, Clemens! Much appreciated!

2 Likes