Repository: mne-tools/mne-python

Issue:
BUG: "mne.read_annotations"

#### Describe the bug
When I used the command '**mne.read_annotations'** to read .csv file. The **onset** always is 0.  However, the **duration** and **description** work well. If I change the file into .txt, it works correctly. 





Discussion:
it's because the .csv reader expects onsets to be timestamps. We should be
done is raise a meaning warning / error when onsets is not timestamps in
.csv eg suggesting to use .txt

>

I think a better solution would be to add an argument to indicate whether absolute or relative timestamps are present. Then we are independent of the file extension, which is a good thing because it is not clear why .csv should have absolute timestamps and .txt relative ones. Or maybe we can even auto-detect the format of the onsets?
but then you have one parameter that only makes sense for one file type as
the others are unambiguous
renaming a file to .txt is easy enough I would say

>

It is true that this would lead to a vector of 0s

```py
@pytest.fixture(scope='session')
def dummy_annotation_csv_notimestamp_file(tmpdir_factory):
    """Create csv file for testing."""
    content = ("onset,duration,description\n"
               "3.14, 42, AA \n"
               "6.28, 48, BB")

    fname = tmpdir_factory.mktemp('data').join('annotations_txt.csv')
    fname.write(content)
    return fname
```

we either support it or we throw an error when its not a datetime. The problem of this is that we take the first as the `orig_time` and that might lead to unwanted results. 

this example should give `[0, 3.14]` as onsets which I'm not sure if its good or not.

> but then you have one parameter that only makes sense for one file type as
the others are unambiguous

The file extension shouldn't be important at all, so the parameter makes sense for any file type. I don't see the deeper motivation why CSV contains timestamps and TXT doesn't.

> renaming a file to .txt is easy enough I would say

Sure it's easy, but it is still confusing.
@massich alright, this is a problem. Then maybe the docs should be clearer on the distinction between the two formats and (most importantly) if something is ambiguous we should throw an error.
+1 to improve the doc and raise an error


Resolving patch:
diff --git a/mne/annotations.py b/mne/annotations.py
--- a/mne/annotations.py
+++ b/mne/annotations.py
@@ -575,6 +575,12 @@ def read_annotations(fname, sfreq='auto', uint16_codec=None):
     -------
     annot : instance of Annotations | None
         The annotations.
+
+    Notes
+    -----
+    The annotations stored in a .csv require the onset columns to be
+    timestamps. If you have onsets as floats (in seconds), you should use the
+    .txt extension.
     """
     from .io.brainvision.brainvision import _read_annotations_brainvision
     from .io.eeglab.eeglab import _read_annotations_eeglab
@@ -648,6 +654,14 @@ def _read_annotations_csv(fname):
     description = df['description'].values
     if orig_time == 0:
         orig_time = None
+
+    if onset_dt.unique().size != onset.unique().size:
+        warn("The number of onsets in the '.csv' file (%d) does not match "
+             "the number of onsets in the Annotations created (%d). If "
+             "this happens because you did not encode your onsets as "
+             "timestamps you should save your files as '.txt'." %
+             (onset_dt.unique().size, onset.unique().size))
+
     return Annotations(onset, duration, description, orig_time)
 
 


Test patch:
diff --git a/mne/tests/test_annotations.py b/mne/tests/test_annotations.py
--- a/mne/tests/test_annotations.py
+++ b/mne/tests/test_annotations.py
@@ -686,8 +686,22 @@ def dummy_annotation_csv_file(tmpdir_factory):
     return fname
 
 
+@pytest.fixture(scope='session')
+def dummy_broken_annotation_csv_file(tmpdir_factory):
+    """Create csv file for testing."""
+    content = ("onset,duration,description\n"
+               "1.,1.0,AA\n"
+               "3.,2.425,BB")
+
+    fname = tmpdir_factory.mktemp('data').join('annotations_broken.csv')
+    fname.write(content)
+    return fname
+
+
 @requires_version('pandas', '0.16')
-def test_io_annotation_csv(dummy_annotation_csv_file, tmpdir_factory):
+def test_io_annotation_csv(dummy_annotation_csv_file,
+                           dummy_broken_annotation_csv_file,
+                           tmpdir_factory):
     """Test CSV input/output."""
     annot = read_annotations(str(dummy_annotation_csv_file))
     assert annot.orig_time == 1038942071.7201
@@ -707,6 +721,10 @@ def test_io_annotation_csv(dummy_annotation_csv_file, tmpdir_factory):
     annot2 = read_annotations(fname)
     _assert_annotations_equal(annot, annot2)
 
+    # Test broken .csv that does not use timestamps
+    with pytest.warns(RuntimeWarning, match='The number of onsets in the'):
+        annot2 = read_annotations(str(dummy_broken_annotation_csv_file))
+
 
 # Test for IO with .txt files