Skip to content

Commit

Permalink
FIX : EDF+ Annotation Timestamps missing sub-second accuracy (#7875)
Browse files Browse the repository at this point in the history
* FIX : EDF+ Annotation Timestamps missing submillisecond accuracy

* review from @cbrnr

* udpate test + testing data

* rephrase

* Rename data

Co-authored-by: Clemens Brunner <[email protected]>
  • Loading branch information
agramfort and cbrnr authored Jun 8, 2020
1 parent f8d2ce1 commit b2615a3
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 4 deletions.
4 changes: 2 additions & 2 deletions mne/datasets/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ def _data_path(path=None, force_update=False, update_path=True, download=True,
path = _get_path(path, key, name)
# To update the testing or misc dataset, push commits, then make a new
# release on GitHub. Then update the "releases" variable:
releases = dict(testing='0.91', misc='0.6')
releases = dict(testing='0.92', misc='0.6')
# And also update the "md5_hashes['testing']" variable below.

# To update any other dataset, update the data archive itself (upload
Expand Down Expand Up @@ -326,7 +326,7 @@ def _data_path(path=None, force_update=False, update_path=True, download=True,
sample='12b75d1cb7df9dfb4ad73ed82f61094f',
somato='ea825966c0a1e9b2f84e3826c5500161',
spm='9f43f67150e3b694b523a21eb929ea75',
testing='f87f04fcdf56a7a55fb73b1b260b5b5b',
testing='42daafd1b882da2ef041de860ca6e771',
multimodal='26ec847ae9ab80f58f204d09e2c08367',
fnirs_motor='c4935d19ddab35422a69f3326a01fef8',
opm='370ad1dcfd5c47e029e692c85358a374',
Expand Down
15 changes: 13 additions & 2 deletions mne/io/edf/edf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1375,12 +1375,23 @@ def _read_annotations_edf(annotations):
triggers = re.findall(pat, tals.decode('latin-1'))

events = []
for ev in triggers:
onset = float(ev[0])
offset = 0.
for k, ev in enumerate(triggers):
onset = float(ev[0]) + offset
duration = float(ev[2]) if ev[2] else 0
for description in ev[3].split('\x14')[1:]:
if description:
events.append([onset, duration, description])
elif k == 0:
# The startdate/time of a file is specified in the EDF+ header
# fields 'startdate of recording' and 'starttime of recording'.
# These fields must indicate the absolute second in which the
# start of the first data record falls. So, the first TAL in
# the first data record always starts with +0.X, indicating
# that the first data record starts a fraction, X, of a second
# after the startdate/time that is specified in the EDF+
# header. If X=0, then the .X may be omitted.
offset = -onset

return zip(*events) if events else (list(), list(), list())

Expand Down
8 changes: 8 additions & 0 deletions mne/io/edf/tests/test_edf.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
'multiple_annotation_chans.bdf')
test_generator_bdf = op.join(data_path, 'BDF', 'test_generator_2.bdf')
test_generator_edf = op.join(data_path, 'EDF', 'test_generator_2.edf')
edf_annot_sub_s_path = op.join(data_path, 'EDF', 'subsecond_starttime.edf')

eog = ['REOG', 'LEOG', 'IEOG']
misc = ['EXG1', 'EXG5', 'EXG8', 'M1', 'M2']
Expand Down Expand Up @@ -385,3 +386,10 @@ def test_edf_lowpass_zero():
with pytest.warns(RuntimeWarning, match='too long.*truncated'):
raw = read_raw_edf(edf_stim_resamp_path)
assert_allclose(raw.info["lowpass"], raw.info["sfreq"] / 2)


@testing.requires_testing_data
def test_edf_annot_sub_s_onset():
"""Test reading of sub-second annotation onsets."""
raw = read_raw_edf(edf_annot_sub_s_path)
assert_allclose(raw.annotations.onset, [1.951172, 3.492188])

0 comments on commit b2615a3

Please sign in to comment.