# events shift after raw.add\_channels

**URL:** <https://mne.discourse.group/t/events-shift-after-raw-add-channels/3591>\
**Category:** Support & Discussions\
**Tags:** annotations\
**Created:** [August 26, 2021, 6:16am UTC](https://mne.discourse.group/t/events-shift-after-raw-add-channels/3591 "2021-08-26T06:16:15Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![GanshengT](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/ganshengt/32/646_2.png) [@GanshengT](https://mne.discourse.group/u/GanshengT)\
**Post date:** [August 26, 2021, 6:16am UTC](https://mne.discourse.group/t/events-shift-after-raw-add-channels/3591/1 "2021-08-26T06:16:15Z")

</div>

**If you have a question or issue with MNE-Python, please include the following info:**

- MNE-Python version: 0.23.0
- operating system: windows

Hi!

I found out that the events shift after add\_channels operations. The processing includes cropping the EEG signal according to the experimental paradigm with the following codes. The onset point is stored in the **alighmentInfo**. I plot the **eeg\_raw** before and after cropping to see whether after cropping, the events still match the signals. And the answer is yes. It seems that events from annotations do not change, what changes is the **eeg\_raw. first\_time**.

```python
# read and cut EEG #
eeg_raw = mne.io.read_raw_eeglab(eeg_fName, preload=True)
eeg_raw.plot()
eeg_raw.set_montage('standard_1020')
eeg_raw.crop(tmin=alignmentInfo.loc[(alignmentInfo['sessionIdx'] == session_idx) &
                                    (alignmentInfo['contraction_type'] == 'iVC'),
                                    'EEG'].values[0] / eeg_raw.info['sfreq'])
eeg_raw.plot()
events, events_id = mne.events_from_annotations(eeg_raw)

```

Then I would add EMG channels into the dataset. Basically, this step includes reading, cropping, and filtering the EMG signals.

```python
# read and cut EMG 
ch_types = ['emg'] * 8  
emg_ch_names = ['FDS', 'FCU', 'FCR', 'ECU', 'ECRL', 'BBS', 'TBL', 'LD']
info = mne.create_info(ch_names=emg_ch_names, sfreq=sfreq_emg, ch_types=ch_types)
emg_data = pd.read_csv(emg_fName, header=None, skiprows=3,
                       sep=' ', usecols=np.arange(0, 8), skipfooter=0, engine='python')
emg_data = emg_data.iloc[alignmentInfo.loc[(alignmentInfo['sessionIdx'] == session_idx) &
                                           (alignmentInfo['contraction_type'] == 'iVC'),
                                           'EMG'].values[0]:, :].values
emg_data = emg_data.T / 1e6 # uV to V
emg_raw = mne.io.RawArray(emg_data, info)
emg_raw.filter(l_freq=10, h_freq=250, picks='all')
emg_raw.resample(sfreq=sfreq_eeg)

# data alighment 
t_end = min(len(eeg_raw), len(emg_raw)) / sfreq_eeg - 1/sfreq_eeg # find the shortest length of EEG and EMG
emg_raw.crop(tmax=t_end)
eeg_raw.crop(tmax=t_end)
emg_raw.info['highpass'] = eeg_raw.info['highpass']
# In reality, EEGs are bandpassed from 1-45Hz, EMGs are bandpassed from 10-200Hz
emg_raw.info['lowpass'] = eeg_raw.info['lowpass']
eeg2merge_raw = eeg_raw.copy()

```

Here’s the problematic function.  
`aligned_raw = eeg2merge_raw.add_channels([emg_raw])`  
After doing _add\_channels_, the events no longer match the signals. I look deeper into what changed. It seems that the _aligned\_raw.first\_time_ is as same as _eeg\_raw.first\_time_. However, **mne.events\_from\_annotations(aligned\_raw)** = **mne.events\_from\_annotations(aligned\_raw)** + _aligned\_raw.first\_time_.

I think this could be misleading for the users of MNE as the changes is not presumably intended. At the end, I resolve the issue with the following codes.

```python
# calibrate annotation
onsets = events[:, 0] / sfreq_eeg - aligned_raw.first_time
durations = events[:, 1]
descriptions = events[:, 2]
annotations = mne.Annotations(onsets, durations, descriptions) 
aligned_raw.set_annotations(annotations)

```

I would like to know what happens when we do the **add\_channels** operation.

---

<div class="post-metadata">

**Author:** ![richard](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/richard/32/15_2.png) [@richard](https://mne.discourse.group/u/richard)\
**Post date:** [August 26, 2021, 8:13am UTC](https://mne.discourse.group/t/events-shift-after-raw-add-channels/3591/2 "2021-08-26T08:13:45Z")

</div>

Hello @GanshengT, do you think you could produce a minimal working example (MWE) based on the MNE `sample` dataset (or any other publicly available data – could also be your own dataset if you are okay with sharing it) to demonstrate the issue? I had a bit of trouble following what exactly you’re doing and which lines are important and which aren’t. An MWE would help others better understand what and where things are going wrong exactly.

Thank you,  
Richard

---

<div class="post-metadata">

**Author:** ![GanshengT](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/ganshengt/32/646_2.png) [@GanshengT](https://mne.discourse.group/u/GanshengT)\
**Post date:** [August 27, 2021, 5:48am UTC](https://mne.discourse.group/t/events-shift-after-raw-add-channels/3591/3 "2021-08-27T05:48:07Z")

</div>

Of course, here is an MWE. I uploaded files used to reproduce the same results. Please download them at [CM-graph/sample\_data/subj61 at master · GanshengT/CM-graph · GitHub](https://github.com/GanshengT/CM-graph/tree/master/sample_data/subj61).

The first thing I do is reading the EEG data.

```python
import pandas as pd
import numpy as np
import mne
eeg_fName = 'subj61/EEG/subj61_iVC_s01.set' # please define fName accordingly
emg_fName = 'subj61/EMG/subj61_iVC_s01.txt'
alignmentInfo_fName = 'subj61/subj61_alignmentInfo.txt'
eeg_raw = mne.io.read_raw_eeglab(eeg_fName, preload=True)
eeg_raw.set_montage('standard_1020')
eeg_raw.filter(l_freq=1, h_freq=45)
eeg_raw.plot(n_channels=5, scalings=1e-4, duration=15, start=25)

```

Here is what the raw EEG data looks like.

 ![image](https://global.discourse-cdn.com/free1/uploads/mne/original/1X/66b628e4b782637e3eced440249be5ab0f294431.jpeg)

The next thing I do is cropping the raw EEG data based on the alignment information. In fact, the EEG begins few seconds prior to the EMG recording.

```python
alignmentInfo = pd.read_csv(alignmentInfo_fName, skiprows=0, sep=',', engine='python')
eeg_raw.crop(tmin=alignmentInfo.loc[(alignmentInfo['sessionIdx'] == 's01') &
                                    (alignmentInfo['contraction_type'] == 'iVC'),
                                    'EEG'].values[0] / eeg_raw.info['sfreq'])
eeg_raw.plot(n_channels=5, scalings=1e-4, duration=15, start=25)

```

And here is the result. So far so good, the events and the signals were shifted forward simultaneously.

 ![image](https://global.discourse-cdn.com/free1/uploads/mne/original/1X/d3881cc08382d5f07ac769c29184737689cf0106.jpeg)

When I concatenate the EEG data and the EMG data, the problem occurs.

```python
ch_types = ['emg'] * 8 
emg_ch_names = ['FDS', 'FCU', 'FCR', 'ECU', 'ECRL', 'BBS', 'TBL', 'LD']
info = mne.create_info(ch_names=emg_ch_names, sfreq=1000, ch_types=ch_types)
emg_data = pd.read_csv(emg_fName, header=None, skiprows=3,
                       sep=' ', usecols=np.arange(0, 8), skipfooter=0, engine='python')
emg_data = emg_data.iloc[alignmentInfo.loc[(alignmentInfo['sessionIdx'] == 's01') &
                                           (alignmentInfo['contraction_type'] == 'iVC'),
                                           'EMG'].values[0]:, :].values
emg_data = emg_data.T / 1e6 # uV to V
emg_raw = mne.io.RawArray(emg_data, info)
emg_raw.filter(l_freq=10, h_freq=250, picks='all')
emg_raw.resample(sfreq=500)
t_end = min(len(eeg_raw), len(emg_raw)) / 500 - 1 / 500 # find the shortest length of EEG and EMG
emg_raw.crop(tmax=t_end)
eeg_raw.crop(tmax=t_end)
emg_raw.info['highpass'] = eeg_raw.info['highpass']
# In reality, EEGs are bandpassed from 1-45Hz, EMGs are bandpassed from 10-200Hz
emg_raw.info['lowpass'] = eeg_raw.info['lowpass']
eeg2merge_raw = eeg_raw.copy()
aligned_raw = eeg2merge_raw.add_channels([emg_raw])
aligned_raw.plot(n_channels=5, scalings=1e-4, duration=15, start=25)

```

As shown in the figure below, we see the data (signals) were shifted forwarded as expected. But the events did not.

 ![image](https://global.discourse-cdn.com/free1/uploads/mne/original/1X/6bf55bca79cccfce844cebcaa69928a434342579.jpeg)

---

<div class="post-metadata">

**Author:** ![GanshengT](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/ganshengt/32/646_2.png) [@GanshengT](https://mne.discourse.group/u/GanshengT)\
**Post date:** [August 27, 2021, 5:51am UTC](https://mne.discourse.group/t/events-shift-after-raw-add-channels/3591/4 "2021-08-27T05:51:15Z")

</div>

BTW, I also tested with mne dataset. But this time everything works fine. I wonder whether there is a problem with data imported from EEGLAB?  
Here is an MWE.

```python
from mne.io import concatenate_raws, read_raw_edf
from mne.datasets import eegbci
import mne
%matplotlib qt
sfreq=160
raw_fnames = eegbci.load_data(1, 1)
raws = [read_raw_edf(f, preload=True) for f in raw_fnames]
raw = concatenate_raws(raws)
# define 2 events
onsets = [4, 8]
durations = [0, 0]
descriptions = ['event1', 'event2']
annotations = mne.Annotations(onsets, durations, descriptions) 
raw.set_annotations(annotations)
raw.plot(n_channels=5, scalings=1e-4, duration=10)

```

 ![image](https://global.discourse-cdn.com/free1/uploads/mne/original/1X/5169dc5b895ac294b63988834a62bdd3c5c19e53.jpeg)

```python
emg_data = raw.get_data()[1:3, :] # define 2 emg chs
ch_types = ['emg'] * 2  
emg_ch_names = ['emg1', 'emg2']
info = mne.create_info(ch_names=emg_ch_names, sfreq=sfreq, ch_types=ch_types)
emg_raw = mne.io.RawArray(emg_data, info)
raw.crop(tmin=3)
raw.plot(n_channels=5, scalings=1e-4, duration=10)

```

 ![image](https://global.discourse-cdn.com/free1/uploads/mne/original/1X/9fa5a2892dd2953de15fa8137822ba81de5292f1.jpeg)

```python
# align eeg and emg data
t_end = min(len(raw),emg_data.shape[1]) / sfreq - 1 / sfreq
emg_raw.crop(tmax=t_end)
raw.crop(tmax=t_end)
eeg_raw = raw.copy()
aligned_raw = eeg_raw.add_channels([emg_raw])
aligned_raw.plot(n_channels=5, scalings=1e-4, duration=10)

```

 ![image](https://global.discourse-cdn.com/free1/uploads/mne/original/1X/2170b985512cc4b62ab38e846631eb4c74728aa7.jpeg)
