Repository: mne-tools/mne-python

Issue:
save-load FIF round trip fails due to Annotations
```py
import os.path as op
import numpy as np
from numpy.testing import (assert_array_almost_equal, assert_array_equal,
                           assert_allclose)

from mne.datasets import testing
from mne.io import read_raw_fif
from mne.utils import _TempDir
from mne.annotations import Annotations

testing_path = testing.data_path(download=False)
data_dir = op.join(testing_path, 'MEG', 'sample')
fif_fname = op.join(data_dir, 'sample_audvis_trunc_raw.fif')
tmpdir = _TempDir()


raw_1 = read_raw_fif(fif_fname, preload=True)
raw_1.set_annotations(Annotations(np.arange(20), np.ones((20,)), 'test'))
split_fname = op.join(tmpdir, 'split_raw.fif')
raw_1.save(split_fname, buffer_size_sec=1.0, split_size='10MB')
raw_2 = read_raw_fif(split_fname)

print(raw_1.annotations)
print(raw_2.annotations)

assert_array_almost_equal(raw_1.annotations.onset, raw_2.annotations.onset)
```

I get two extra annotations at the end of the file that I've no idea where are they coming from.

```
<Annotations  |  20 segments : test (20), orig_time : 2002-12-03 19:01:10.720100>
<Annotations  |  22 segments : test (22), orig_time : 2002-12-03 19:01:10.720100>
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
~/code/mne-python/test_xx.py in <module>
     24 print(raw_2.annotations)
     25 
---> 26 assert_array_almost_equal(raw_1.annotations.onset, raw_2.annotations.onset)
     27 

~/miniconda3/envs/mne/lib/python3.6/site-packages/numpy/testing/_private/utils.py in assert_array_almost_equal(x, y, decimal, err_msg, verbose)
    971     assert_array_compare(compare, x, y, err_msg=err_msg, verbose=verbose,
    972              header=('Arrays are not almost equal to %d decimals' % decimal),
--> 973              precision=decimal)
    974 
    975 

~/miniconda3/envs/mne/lib/python3.6/site-packages/numpy/testing/_private/utils.py in assert_array_compare(comparison, x, y, err_msg, verbose, header, precision, equal_nan, equal_inf)
    738                                 verbose=verbose, header=header,
    739                                 names=('x', 'y'), precision=precision)
--> 740             raise AssertionError(msg)
    741 
    742         flagged = bool_(False)

AssertionError: 
Arrays are not almost equal to 6 decimals

(shapes (20,), (22,) mismatch)
 x: array([42.955971, 43.955971, 44.955971, 45.955971, 46.955971, 47.955971,
       48.955971, 49.955971, 50.955971, 51.955971, 52.955971, 53.955971,
       54.955971, 55.955971, 56.955971, 57.955971, 58.955971, 59.955971,
       60.955971, 61.955971])
 y: array([42.955971, 43.955971, 44.955971, 45.955971, 46.955971, 47.955971,
       48.955971, 49.955971, 50.955971, 51.955971, 52.955971, 53.955971,
       54.955971, 55.955971, 56.955971, 57.955971, 58.955971, 59.955971,
       60.955971, 61.955971, 62.958802, 62.958802])
```


Discussion:

Resolving patch:
diff --git a/mne/io/fiff/raw.py b/mne/io/fiff/raw.py
--- a/mne/io/fiff/raw.py
+++ b/mne/io/fiff/raw.py
@@ -21,8 +21,7 @@
                     _check_maxshield)
 from ..utils import _mult_cal_one
 
-from ...annotations import (Annotations, _combine_annotations,
-                            _read_annotations_fif)
+from ...annotations import Annotations, _read_annotations_fif
 
 from ...event import AcqParserFIF
 from ...utils import check_fname, logger, verbose, warn, fill_doc
@@ -104,16 +103,7 @@ def __init__(self, fname, allow_maxshield=False, preload=False,
             verbose=verbose)
 
         # combine annotations
-        self.set_annotations(raws[0].annotations, False)
-        if any([r.annotations for r in raws[1:]]):
-            n_samples = np.sum(self._last_samps - self._first_samps + 1)
-            for r in raws:
-                annotations = _combine_annotations(
-                    self.annotations, r.annotations,
-                    n_samples, self.first_samp, r.first_samp,
-                    r.info['sfreq'], self.info['meas_date'])
-                self.set_annotations(annotations, emit_warning=False)
-                n_samples += r.last_samp - r.first_samp + 1
+        self.set_annotations(raws[0].annotations, emit_warning=False)
 
         # Add annotations for in-data skips
         for extra in self._raw_extras:


Test patch:
diff --git a/mne/io/fiff/tests/test_raw_fiff.py b/mne/io/fiff/tests/test_raw_fiff.py
--- a/mne/io/fiff/tests/test_raw_fiff.py
+++ b/mne/io/fiff/tests/test_raw_fiff.py
@@ -382,14 +382,18 @@ def test_split_files(tmpdir):
     assert op.exists(split_fname_bids_part1)
     assert op.exists(split_fname_bids_part2)
 
+    annot = Annotations(np.arange(20), np.ones((20,)), 'test')
+    raw_1.set_annotations(annot)
     split_fname = op.join(tempdir, 'split_raw.fif')
     raw_1.save(split_fname, buffer_size_sec=1.0, split_size='10MB')
     raw_2 = read_raw_fif(split_fname)
     assert_allclose(raw_2.buffer_size_sec, 1., atol=1e-2)  # samp rate
-    assert_array_almost_equal(raw_1.annotations.onset, raw_2.annotations.onset)
-    assert_array_equal(raw_1.annotations.duration, raw_2.annotations.duration)
+    assert_allclose(raw_1.annotations.onset, raw_2.annotations.onset)
+    assert_allclose(raw_1.annotations.duration, raw_2.annotations.duration,
+                    rtol=0.001 / raw_2.info['sfreq'])
     assert_array_equal(raw_1.annotations.description,
                        raw_2.annotations.description)
+
     data_1, times_1 = raw_1[:, :]
     data_2, times_2 = raw_2[:, :]
     assert_array_equal(data_1, data_2)
@@ -407,6 +411,8 @@ def test_split_files(tmpdir):
     # somehow, the numbers below for e.g. split_size might need to be
     # adjusted.
     raw_crop = raw_1.copy().crop(0, 5)
+    raw_crop.set_annotations(Annotations([2.], [5.5], 'test'),
+                             emit_warning=False)
     with pytest.raises(ValueError,
                        match='after writing measurement information'):
         raw_crop.save(split_fname, split_size='1MB',  # too small a size