mne-python: EDF read in not working in certain files, read in slow

edf_test_edited.zip edf_test.zip

The attached EDF file “edf_test.edf” can be opened via pyedflib:

Python 3.6.6 |Anaconda custom (64-bit)| (default, Jun 28 2018, 11:07:29) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import pyedflib

In [2]: f = pyedflib.EdfReader("edf_test.edf")

In [3]: f.readSignal(chn=0)
Out[3]: 
array([-18000.        , -18000.        , -18000.        , ...,
         4210.98649577,   4210.98649577,   4210.98649577])

File cannot be opened with mne:

In [1]: import mne

In [2]: mne.io.read_raw_edf("edf_test.edf", preload = True)
Extracting EDF parameters from edf_test.edf...
EDF file detected
Setting channel info structure...
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-2-8bfb048068a5> in <module>()
----> 1 mne.io.read_raw_edf("edf_test.edf", preload = True)

~/anaconda3/lib/python3.6/site-packages/mne/io/edf/edf.py in read_raw_edf(input_fname, montage, eog, misc, stim_channel, annot, annotmap, exclude, preload, verbose)
   1237     return RawEDF(input_fname=input_fname, montage=montage, eog=eog, misc=misc,
   1238                   stim_channel=stim_channel, annot=annot, annotmap=annotmap,
-> 1239                   exclude=exclude, preload=preload, verbose=verbose)

~/anaconda3/lib/python3.6/site-packages/mne/io/edf/edf.py in __init__(self, input_fname, montage, eog, misc, stim_channel, annot, annotmap, exclude, preload, verbose)

~/anaconda3/lib/python3.6/site-packages/mne/utils.py in verbose(function, *args, **kwargs)
    727         with use_log_level(verbose_level):
    728             return function(*args, **kwargs)
--> 729     return function(*args, **kwargs)
    730 
    731 

~/anaconda3/lib/python3.6/site-packages/mne/io/edf/edf.py in __init__(self, input_fname, montage, eog, misc, stim_channel, annot, annotmap, exclude, preload, verbose)
    156         input_fname = os.path.abspath(input_fname)
    157         info, edf_info = _get_info(input_fname, stim_channel, annot,
--> 158                                    annotmap, eog, misc, exclude, preload)
    159         logger.info('Creating raw.info structure...')
    160         _check_update_montage(info, montage)

~/anaconda3/lib/python3.6/site-packages/mne/io/edf/edf.py in _get_info(fname, stim_channel, annot, annotmap, eog, misc, exclude, preload)
    509         data_samps = np.delete(n_samps, slice(stim_channel, stim_channel + 1))
    510     sfreq = data_samps.max() * \
--> 511         edf_info['record_length'][1] / edf_info['record_length'][0]
    512 
    513     info = _empty_info(sfreq)

~/anaconda3/lib/python3.6/site-packages/numpy/core/_methods.py in _amax(a, axis, out, keepdims)
     24 # small reductions
     25 def _amax(a, axis=None, out=None, keepdims=False):
---> 26     return umr_maximum(a, axis, None, out, keepdims)
     27 
     28 def _amin(a, axis=None, out=None, keepdims=False):

ValueError: zero-size array to reduction operation maximum which has no identity

With nme, adding stim_chan = None solves the problem:

In [3]: mne.io.read_raw_edf("edf_test.edf", preload = True, stim_channel=None)
Extracting EDF parameters from edf_test.edf...
EDF file detected
Setting channel info structure...
Creating raw.info structure...In [1]: import mne

In [2]: mne.io.read_raw_edf("edf_test_edited.edf", preload=True)
Extracting EDF parameters from edf_test_edited.edf...
EDF file detected
EDF annotations detected (consider using raw.find_edf_events() to extract them)
Setting channel info structure...
Creating raw.info structure...
Reading 0 ... 1843199  =      0.000 ...  3599.998 secs...
Out[2]: <RawEDF  |  edf_test_edited.edf, n_channels x n_times : 2 x 1843200 (3600.0 sec), ~28.1 MB, data loaded>

Reading 0 ... 1843199  =      0.000 ...  3599.998 secs...
Out[3]: <RawEDF  |  edf_test.edf, n_channels x n_times : 1 x 1843200 (3600.0 sec), ~14.1 MB, data loaded>

The same EDF file with annotations (edf_test_edited.edf):

In [3]: mne.io.read_raw_edf("edf_test_edited.edf", preload = True)
Extracting EDF parameters from edf_test_edited.edf...
EDF file detected
EDF annotations detected (consider using raw.find_edf_events() to extract them)
Setting channel info structure...
Creating raw.info structure...
Reading 0 ... 1843199  =      0.000 ...  3599.998 secs...
Out[3]: <RawEDF  |  edf_test_edited.edf, n_channels x n_times : 2 x 1843200 (3600.0 sec), ~28.1 MB, data loaded>

Note that the EDF files only contain 1 channel, but <RawEDF | edf_test_edited.edf, n_channels x n_times : 2 x 1843200 (3600.0 sec), ~28.1 MB, data loaded> states n_channels = 2.

Additionaly, EDF readin is really slow with stim_chan = None:

Timing for read in of annotated file without stim_channel=None is really slow:

%timeit mne.io.read_raw_edf("edf_test_edited.edf", preload=True)
Extracting EDF parameters from edf_test_edited.edf...
EDF file detected
EDF annotations detected (consider using raw.find_edf_events() to extract them)
Setting channel info structure...
Creating raw.info structure...
Reading 0 ... 1843199  =      0.000 ...  3599.998 secs..
4.59 s ± 12.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

compared to read in with stim_chan=None:

%timeit mne.io.read_raw_edf("edf_test_edited.edf", preload=True, stim_channel=None)
Extracting EDF parameters from edf_test_edited.edf...
EDF file detected
EDF annotations detected (consider using raw.find_edf_events() to extract them)
Setting channel info structure...
Creating raw.info structure...
<magic-timeit>:1: RuntimeWarning: 1 channel names are too long, have been truncated to 15 characters:
['EDF Annotations-1']
1 channel names are too long, have been truncated to 15 characters:
['EDF Annotations-1']
Reading 0 ... 1843199  =      0.000 ...  3599.998 secs...
59.2 ms ± 962 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

Can these issues be solved?

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 16 (11 by maintainers)

Most upvoted comments

I don’t have much time to comment but the annotations in edf files should become raw.annotations attribute by default and not produce a stim channel if not present in the file. Then it should be possible to get events from raw.annotations.

See previous discussion on this.

It will speed up IO by avoiding extra allocations and heavily simply EDF IO code, especially with preload=False