Repository: mne-tools/mne-python

Issue:
Concatenating many epoch objects (~60) leads to overflow warning and subsequent errors
#### Describe the bug
I've tried concatenating about 60 epochs objects (each from a separate run) and get an overflow warning, after which the epochs are dropped leading to an error when the resulting `BaseEpochs` object is constructed. See stdout below.

I suspect that this is due to the offset that is  added to each extra set of epoch events, after which the new values + offset are added to the offset. See [lines 2876 to 2881 in the epochs module](https://github.com/mne-tools/mne-python/blob/master/mne/epochs.py#L2876).  In effect, the offset is doubled every time. Is this intended?

If not, ~~I can give a shot at fixing it with a PR?~~ I've now opened PR #5496 

This happens if I `print(np.max(events_offset))`
```
565391
1319897
2830598
5851880
11882823
====SNIP====
829328844905734424
1658657689811660608
3317315379623504407
6634630759247204105
/home/adf/vandejjf/Projects/mne-python/mne/epochs.py:2881: RuntimeWarning: overflow encountered in long_scalars
  int((10 + tmax) * epochs.info['sfreq']))
-5177482555214963201
8091778963279816905
-2263186147149728930
-4526372294299265164
-9052744588598338535
341254896513063932
```

#### Steps and/or code to reproduce

This can be replicated by adding these lines to `test_concatenate_epochs` in the epochs unit test:

```Python
    # test large number of epochs
    long_epochs_list = [epochs.copy() for ii in range(60)]
    many_epochs_cat = concatenate_epochs(long_epochs_list)
```


#### Expected results
The epochs to be concatenated and returned as one Epochs object.


#### Actual results
```
/home/adf/vandejjf/Projects/eegprep/env/src/mne/mne/epochs.py:2881: RuntimeWarning: overflow encountered in long_scalars
  int((10 + tmax) * epochs.info['sfreq']))
/home/adf/vandejjf/Projects/eegprep/eegprep/preproc.py:84: RuntimeWarning: The events passed to the Epochs constructor are not chronologically ordered.
  task_epochs = mne.epochs.concatenate_epochs(task_epochs_list)
The events passed to the Epochs constructor are not chronologically ordered.
3554 matching events found
Applying baseline correction (mode: mean)
Not setting metadata
3554 bad epochs dropped
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
~/Projects/eegprep/eegprep/preproc.py in <module>()
     84         task_epochs = mne.epochs.concatenate_epochs(task_epochs_list)
     85         task_epochs = task_epochs.pick_types(eeg=True, exclude=refChannels)
---> 86         task_epochs.save(join(derivdir, 'sub-{}_task-{}_epo.fif'.format(sub, task)))

~/Projects/eegprep/env/src/mne/mne/epochs.py in save(self, fname, split_size, verbose)

~/Projects/eegprep/env/src/mne/mne/utils.py in verbose(function, *args, **kwargs)
    736         # set it back if we get an exception
    737         with use_log_level(verbose_level):
--> 738             return function(*args, **kwargs)
    739     return function(*args, **kwargs)
    740 

~/Projects/eegprep/env/src/mne/mne/epochs.py in save(self, fname, split_size, verbose)
   1652         self.drop_bad()
   1653         self._check_consistency()
-> 1654         total_size = self[0].get_data().nbytes * len(self)
   1655         total_size /= 2  # 64bit data converted to 32bit before writing.
   1656         n_parts = int(np.ceil(total_size / float(split_size)))

~/Projects/eegprep/env/src/mne/mne/epochs.py in __getitem__(self, item)
   1486                .. versionadded:: 0.16
   1487         """
-> 1488         return self._getitem(item)
   1489 
   1490     def _getitem(self, item, reason='IGNORED', copy=True, drop_event_id=True,

~/Projects/eegprep/env/src/mne/mne/epochs.py in _getitem(***failed resolving arguments***)
   1537                 select = np.array([], int)
   1538 
-> 1539         key_selection = epochs.selection[select]
   1540         if reason is not None:
   1541             for k in np.setdiff1d(epochs.selection, key_selection):

IndexError: index 0 is out of bounds for axis 1 with size 0
```



#### Additional information
sys-info
```
Platform:      Linux-4.15.0-33-generic-x86_64-with-Ubuntu-18.04-bionic
Python:        3.6.5 (default, Apr  1 2018, 05:46:30)  [GCC 7.3.0]
Executable:    /home/adf/vandejjf/Projects/mne-python/env/bin/python
CPU:           x86_64: 4 cores
Memory:        7.7 GB

mne:           0.17.dev0
numpy:         1.15.1 {blas=openblas, lapack=openblas}
scipy:         1.1.0
matplotlib:    2.2.3 {backend=TkAgg}

sklearn:       0.19.2
nibabel:       2.3.0
mayavi:        4.6.2 {qt_api=pyqt5}
cupy:          Not found
pandas:        0.23.4
dipy:          Not found

```



Discussion:

Resolving patch:
diff --git a/mne/epochs.py b/mne/epochs.py
--- a/mne/epochs.py
+++ b/mne/epochs.py
@@ -2877,7 +2877,7 @@ def _concatenate_epochs(epochs_list, with_data=True, add_offset=True):
             evs[:, 0] += events_offset
         # Update offset for the next iteration.
         # offset is the last epoch + tmax + 10 second
-        events_offset += (np.max(evs[:, 0]) +
+        events_offset += (np.max(epochs.events[:, 0]) +
                           int((10 + tmax) * epochs.info['sfreq']))
         events.append(evs)
         selection = np.concatenate((selection, epochs.selection))


Test patch:
diff --git a/mne/tests/test_epochs.py b/mne/tests/test_epochs.py
--- a/mne/tests/test_epochs.py
+++ b/mne/tests/test_epochs.py
@@ -2158,6 +2158,12 @@ def test_concatenate_epochs():
         rel_pos = epochs_list[ii].events[:, 0] - evs[:, 0]
         assert (sum(rel_pos - rel_pos[0]) == 0)
 
+    # test large number of epochs
+    long_epochs_list = [epochs.copy() for ii in range(60)]
+    many_epochs_cat = concatenate_epochs(long_epochs_list)
+    max_expected_sample_index = 60 * 1.2 * np.max(epochs.events[:, 0])
+    assert np.max(many_epochs_cat.events[:, 0]) < max_expected_sample_index
+
 
 def test_add_channels():
     """Test epoch splitting / re-appending channel types."""